【问题标题】:.NET ServiceModel.Syndication - Changing Encoding on RSS Feed.NET ServiceModel.Syndication - 更改 RSS 提要的编码
【发布时间】:2011-03-28 14:51:26
【问题描述】:

我正在尝试解决我在http://captainobvio.us 生成的所有 RSS 提要在 Internet Explorer(版本 8 和 9)中产生以下错误的错误:

Feed 代码错误 从当前切换 编码为指定的编码不是 支持的。行:1 个字符:40

<?xml version="1.0" encoding="utf-16"?>

问题在于通过 HTTP 标头发送的实际编码类型与文档声明的不同。这是我的代码将提要的输出写入 HTML 的样子:

public ContentResult Index()
        {
            var feed = _syndication.SyndicateIdeas(_repository.GetIdeas(0,15).Ideas);

            var sb = new StringBuilder();
            using (var writer = XmlWriter.Create(sb, new XmlWriterSettings { Encoding = Encoding.UTF8, NewLineHandling = NewLineHandling.Entitize, NewLineOnAttributes = true, Indent = true}))
            {
                feed.SaveAsRss20(writer);
                writer.Close();
            }

            return Content(sb.ToString(), "application/rss+xml", Encoding.UTF8);
        } 

这是我在 .NET 4.0 中使用 System.ServiceModel.Syndication 实际构建提要的代码:

var feed = new SyndicationFeed("CaptainObvio.us - Recent Ideas",
                                          "The most recent ideas posted by the Community on CaptainObvio.us", new Uri("http://captainobvio.us/"), "CaptainObvio.us", new DateTimeOffset(ideas[0].DatePosted), items)
                           {
                               Generator = "CaptainObvio.us - http://captainobvio.us/"
                           };

            return feed;

我想做的是将 XML 文档更改为读取 utf-8 而不是 utf-16。我还检查了 Encoding 命名空间以查看是否有 UTF16 选项(因此我可以更正 HTTP 标头而不是 XML 文档)并且找不到。

有没有一种简单的方法可以直接从 System.ServiceModel.Syndication 更改 XML 文档的编码属性?解决此问题的最简单方法是什么?

【问题讨论】:

    标签: .net asp.net asp.net-mvc xml rss


    【解决方案1】:

    发生这种情况的原因是您将 StringBuilder 传递给 XmlWriter 构造函数。 .NET 中的字符串是 unicode,因此 XmlWriter 假定为 utf-16,您无法对其进行修改。

    所以你可以使用流而不是字符串生成器,然后你可以通过设置来控制编码:

    var settings = new XmlWriterSettings 
    { 
        Encoding = Encoding.UTF8, 
        NewLineHandling = NewLineHandling.Entitize, 
        NewLineOnAttributes = true, 
        Indent = true 
    };
    using (var stream = new MemoryStream())
    using (var writer = XmlWriter.Create(stream, settings))
    {
        feed.SaveAsRss20(writer);
        writer.Flush();
        return File(stream.ToArray(), "application/rss+xml; charset=utf-8");
    }
    

    所有这一切都说得更好,更 MVCish,我建议你的解决方案是写一个SyndicationResult

    public class SyndicationResult : ActionResult
    {
        private readonly SyndicationFeed _feed;
        public SyndicationResult(SyndicationFeed feed)
        {
            if (feed == null)
            {
                throw new HttpException(401, "Not found");
            }
            _feed = feed;
        }
    
        public override void ExecuteResult(ControllerContext context)
        {
            var settings = new XmlWriterSettings
            {
                Encoding = Encoding.UTF8,
                NewLineHandling = NewLineHandling.Entitize,
                NewLineOnAttributes = true,
                Indent = true
            };
    
            var response = context.HttpContext.Response;
            response.ContentType = "application/rss+xml; charset=utf-8";
            using (var writer = XmlWriter.Create(response.OutputStream, settings))
            {
                _feed.SaveAsRss20(writer);
            }
        }
    }
    

    并在您的控制器操作中简单地返回此结果,这样您就不会用管道代码混淆您的控制器操作:

    public ActionResult Index()
    {
        var ideas = _repository.GetIdeas(0, 15).Ideas;
        var feed = _syndication.SyndicateIdeas(ideas);
        return new SyndicationResult(feed);
    } 
    

    【讨论】:

    • 达林,出色的答案。我什至没有想过将 StringBuilder 视为问题的根源,并且您对 ActionResult 子类化的建议非常好。如果我能不止一次给你投票,我会的。
    • @Aaronontheweb,很高兴我能帮上忙。
    猜你喜欢
    • 2015-03-30
    • 2015-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-09
    相关资源
    最近更新 更多