首页 文章

.NET ServiceModel.Syndication - 更改RSS源上的编码

提问于
浏览
6

我'm trying to solve a bug where all of the RSS feeds I'生成http://captainobvio.us在Internet Explorer(版本8和9)中产生以下错误:

Feed code error从当前编码切换到不支持的指定编码 . 行: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实际构建feed的代码:

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文档的编码属性?解决此问题的最简单方法是什么?

1 回答

  • 13

    发生这种情况的原因是因为您将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);
    }
    

相关问题