.NET ServiceModel.Syndication - 改变编码处理RSS FeedServiceModel、NET、Syndication、Feed

2023-09-03 07:34:55 作者:hi,那就是温暖的i

我试图解决,所有的RSS源,我在 http://captainobvio.us生产产生如下的错误在Internet Explorer中的错误(版本8和9):

  

饲料code错误的电流开关   编码到指定的编码不   支持。行:1字符:40

 < XML版本=1.0编码=UTF-16&GT?;
 

的问题是,通过HTTP头中发送实际的编码类型是比文档声明不同。这里是我的code看起来像写饲料的产量为HTML:

 公共ContentResult类型指数()
        {
            VAR饲料= _syndication.SyndicateIdeas(_repository.GetIdeas(0,15).Ideas);

            VAR SB =新的StringBuilder();
            使用(VAR作家= XmlWriter.Create(SB,新XmlWriterSettings {编码= Encoding.UTF8,NewLineHandling = NewLineHandling.Entitize,NewLineOnAttributes = TRUE,缩进= TRUE}))
            {
                feed.SaveAsRss20(作家);
                writer.Close();
            }

            返回内容(sb.ToString(),应用程序/ RSS + XML,Encoding.UTF8);
        }
 

和这里是我的code看起来像实际构建的饲料,使用System.ServiceModel.Syndication在.NET 4.0中:

  VAR饲料=新SyndicationFeed(CaptainObvio.us  - 最近的点子,
                                          ,新的URI(http://captainobvio.us/)发布的社会各界对CaptainObvio.us最新的思想,CaptainObvio.us,新的DateTimeOffset(思路[0] .DatePosted)项)
                           {
                               发电机=CaptainObvio.us  -  http://captainobvio.us/
                           };

            返回饲料;
 
Algorius Net Viewer特别版 Algorius Net Viewer下载 10.0.7 破解版 新云软件园

我希望做的是改变XML文档读取UTF-8,而不是UTF-16。我还检查了编码命名空间,看看是否有一个UTF16选项(所以我可以纠正HTTP头,而不是XML文件),并没有能够找到一个。

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

解决方案

出现这种情况的原因是因为你正在传递一个StringBuilder到的XmlWriter构造。在.NET中的字符串是单向code这样的XmlWriter假定UTF-16和你无法修改此。

所以,你可以使用流而不是字符串生成器,那么你就可以控制与设置的编码:

  VAR设置=新XmlWriterSettings
{
    编码= Encoding.UTF8,
    NewLineHandling = NewLineHandling.Entitize,
    NewLineOnAttributes = TRUE,
    缩进=真
};
使用(VAR流=新的MemoryStream())
使用(VAR作家= XmlWriter.Create(流设置))
{
    feed.SaveAsRss20(作家);
    writer.Flush();
    返回文件(stream.ToArray(),应用程序/ RSS + XML;字符集= UTF-8);
}
 

所有这是说一个更好的,更MVCish和一个我会建议您的解决方案是写一个 SyndicationResult

 公共类SyndicationResult:的ActionResult
{
    私人只读SyndicationFeed _feed;
    公共SyndicationResult(SyndicationFeed供稿)
    {
        如果(原料== NULL)
        {
            抛出新HttpException(401,未找到);
        }
        _feed =饲料;
    }

    公众覆盖无效的ExecuteReuslt(ControllerContext上下文)
    {
        VAR设置=新XmlWriterSettings
        {
            编码= Encoding.UTF8,
            NewLineHandling = NewLineHandling.Entitize,
            NewLineOnAttributes = TRUE,
            缩进=真
        };

        VAR响应= context.HttpContext.Response;
        response.ContentType =应用程序/ RSS + XML;字符集= UTF-8;
        使用(VAR作家= XmlWriter.Create(response.OutputStream,设置))
        {
            _feed.SaveAsRss20(作家);
        }
    }
}
 

在你的控制器动作简单地返回这个结果,这样你就不会与管道code弄乱你的控制器操作:

 公众的ActionResult指数()
{
    VAR的想法= _repository.GetIdeas(0,15).Ideas;
    VAR饲料= _syndication.SyndicateIdeas(的想法);
    返回新SyndicationResult(饲料);
}
 

I'm trying to solve a bug where all of the RSS feeds I'm producing at http://captainobvio.us produce the following error in Internet Explorer (versions 8 and 9):

Feed code error Switch from current encoding to specified encoding not supported. Line: 1 Character: 40

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

The issue is that the actual encoding type sent via the HTTP header is different than what the document declares. Here is what my code looks like for writing the feed's output to 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);
        } 

And here is what my code looks like for actually building the feed, using System.ServiceModel.Syndication in .NET 4.0:

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;

What I would like to do is change the XML document to read utf-8 instead of utf-16. I also checked the Encoding namespace to see if there was a UTF16 option (so I could correct the HTTP header instead of the XML document) and wasn't able to find one.

Is there an easy way change the encoding attribute on the XML document directly from System.ServiceModel.Syndication? What's the easiest way to fix this issue?

解决方案

The reason this happens is because you are passing a StringBuilder to the XmlWriter constructor. Strings in .NET are unicode so XmlWriter assumes utf-16 and you cannot modify this.

So you could use a stream instead of string builder, then you can control the encoding with the settings:

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");
}

All this being said a far better, more MVCish and a one the I would recommend you solution is to write a 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);
        }
    }
}

and in your controller action simply return this result so that you don't clutter your controller actions with plumbing code:

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