2011-03-27 47 views
6

我正試圖解決所有在http://captainobvio.us上生成的RSS源在Internet Explorer(版本8和9)中產生以下錯誤的錯誤:.NET ServiceModel.Syndication - 更改RSS源上的編碼

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

而且這裏是我的代碼看起來像實際建立飼料,使用System.ServiceModel.Syndication在.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; 

我想要做的是將XML文檔更改爲utf-8而不是utf-16。我還檢查了Encoding命名空間,看看是否有UTF16選項(所以我可以更正HTTP標頭而不是XML文檔),但無法找到它。

是否有一種簡單的方法直接從System.ServiceModel.Syndication更改XML文檔上的編碼屬性?解決這個問題最簡單的方法是什麼?

回答

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); 
} 
+2

達林,優秀的答案。我甚至沒有考慮將StringBuilder作爲問題的根源,並且您對ActionResult進行子類化的建議非常好。如果我可以不止一次地讚揚你,我會。 – Aaronontheweb 2011-03-28 21:25:13

+0

@Aaronontheweb,很高興我能幫上忙。 – 2011-03-28 21:26:31