Rss20FeedFormatter 忽略 SyndicateItem.Summary 的 TextSynminationContent 类型
在 WCF 项目中使用 Rss20FeedFormatter 类时,我尝试使用 部分包装描述元素的内容。我发现无论我做什么,描述元素的 HTML 内容总是被编码,并且 CDATA 部分从未被添加。在查看 Rss20FeedFormatter 的源代码后,我发现在构建 Summary 节点时,它基本上创建了一个新的 TextSyndicateContent 实例,该实例会清除之前指定的任何设置(我认为)。
我的代码
public class CDataSyndicationContent : TextSyndicationContent
{
public CDataSyndicationContent(TextSyndicationContent content)
: base(content)
{
}
protected override void WriteContentsTo(System.Xml.XmlWriter writer)
{
writer.WriteCData(Text);
}
}
...(以下代码应使用 CDATA 部分包装摘要)
SyndicationItem item = new SyndicationItem();
item.Title = new TextSyndicationContent(name);
item.Summary = new CDataSyndicationContent(
new TextSyndicationContent(
"<div>This is a test</div>",
TextSyndicationContentKind.Html));
Rss20FeedFormatter 代码 (据我所知,由于这种逻辑,上述代码不起作用)
...
else if (reader.IsStartElement("description", ""))
result.Summary = new TextSyndicationContent(reader.ReadElementString());
...
作为一种解决方法,我求助于使用 RSS20FeedFormatter 来构建 RSS,然后手动修补 RSS。例如:
StringBuilder buffer = new StringBuilder();
XmlTextWriter writer = new XmlTextWriter(new StringWriter(buffer));
feedFormatter.WriteTo(writer ); // feedFormatter = RSS20FeedFormatter
PostProcessOutputBuffer(buffer);
WebOperationContext.Current.OutgoingResponse.ContentType =
"application/xml; charset=utf-8";
return new MemoryStream(Encoding.UTF8.GetBytes(buffer.ToString()));
...
public void PostProcessOutputBuffer(StringBuilder buffer)
{
var xmlDoc = XDocument.Parse(buffer.ToString());
foreach (var element in xmlDoc.Descendants("channel").First()
.Descendants("item")
.Descendants("description"))
{
VerifyCdataHtmlEncoding(buffer, element);
}
foreach (var element in xmlDoc.Descendants("channel").First()
.Descendants("description"))
{
VerifyCdataHtmlEncoding(buffer, element);
}
buffer.Replace(" xmlns:a10=\"http://www.w3.org/2005/Atom\"",
" xmlns:atom=\"http://www.w3.org/2005/Atom\"");
buffer.Replace("a10:", "atom:");
}
private static void VerifyCdataHtmlEncoding(StringBuilder buffer,
XElement element)
{
if (!element.Value.Contains("<") || !element.Value.Contains(">"))
{
return;
}
var cdataValue = string.Format("<{0}><![CDATA[{1}]]></{2}>",
element.Name,
element.Value,
element.Name);
buffer.Replace(element.ToString(), cdataValue);
}
此解决方法的想法来自以下位置,我只是对其进行了调整以与 WCF 而不是 MVC 一起使用。 是否
我只是想知道 这只是 Rss20FeedFormatter 中的一个错误还是设计使然?另外,如果有人有更好的解决方案,我很想听听!
While using the Rss20FeedFormatter class in a WCF project, I was trying to wrap the content of my description elements with a <![CDATA[ ]]>
section. I found that no matter what I did, the HTML content of the description elements was always encoded and the CDATA section was never added. After peering into the source code of Rss20FeedFormatter, I found that when building the Summary node, it basically creates a new TextSyndicationContent instance which wipes out whatever settings were previously specified (I think).
My Code
public class CDataSyndicationContent : TextSyndicationContent
{
public CDataSyndicationContent(TextSyndicationContent content)
: base(content)
{
}
protected override void WriteContentsTo(System.Xml.XmlWriter writer)
{
writer.WriteCData(Text);
}
}
... (The following code should wrap the Summary with a CDATA section)
SyndicationItem item = new SyndicationItem();
item.Title = new TextSyndicationContent(name);
item.Summary = new CDataSyndicationContent(
new TextSyndicationContent(
"<div>This is a test</div>",
TextSyndicationContentKind.Html));
Rss20FeedFormatter Code
(AFAIK, the above code does not work because of this logic)
...
else if (reader.IsStartElement("description", ""))
result.Summary = new TextSyndicationContent(reader.ReadElementString());
...
As a workaround, I've resorted to using the RSS20FeedFormatter to build the RSS, and then patch the RSS manually. For example:
StringBuilder buffer = new StringBuilder();
XmlTextWriter writer = new XmlTextWriter(new StringWriter(buffer));
feedFormatter.WriteTo(writer ); // feedFormatter = RSS20FeedFormatter
PostProcessOutputBuffer(buffer);
WebOperationContext.Current.OutgoingResponse.ContentType =
"application/xml; charset=utf-8";
return new MemoryStream(Encoding.UTF8.GetBytes(buffer.ToString()));
...
public void PostProcessOutputBuffer(StringBuilder buffer)
{
var xmlDoc = XDocument.Parse(buffer.ToString());
foreach (var element in xmlDoc.Descendants("channel").First()
.Descendants("item")
.Descendants("description"))
{
VerifyCdataHtmlEncoding(buffer, element);
}
foreach (var element in xmlDoc.Descendants("channel").First()
.Descendants("description"))
{
VerifyCdataHtmlEncoding(buffer, element);
}
buffer.Replace(" xmlns:a10=\"http://www.w3.org/2005/Atom\"",
" xmlns:atom=\"http://www.w3.org/2005/Atom\"");
buffer.Replace("a10:", "atom:");
}
private static void VerifyCdataHtmlEncoding(StringBuilder buffer,
XElement element)
{
if (!element.Value.Contains("<") || !element.Value.Contains(">"))
{
return;
}
var cdataValue = string.Format("<{0}><![CDATA[{1}]]></{2}>",
element.Name,
element.Value,
element.Name);
buffer.Replace(element.ToString(), cdataValue);
}
The idea for this workaround came from the following location, I just adapted it to work with WCF instead of MVC. http://localhost:8732/Design_Time_Addresses/SyndicationServiceLibrary1/Feed1/
I'm just wondering if this is simply a bug in Rss20FeedFormatter or is it by design? Also, if anyone has a better solution, I'd love to hear it!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
好吧@Page Brooks,我认为这更多地是一个解决方案,而不是一个问题:)。谢谢!!!并回答你的问题(;)),是的,我绝对认为这是 Rss20FeedFormatter 中的一个错误(尽管我没有追究它那么远),因为遇到了与你描述的完全相同的问题。
您的帖子中有“localhost:8732”推荐,但它在我的本地主机上不可用;)。我认为您的意思是将“PostProcessOutputBuffer”解决方法归功于这篇文章:
http://damieng.com/ blog/2010/04/26/creating-rss-feeds-in-asp-net-mvc
或者实际上它不在这篇文章中,而是在 David Whitney 的评论中,后来他在这里单独提出了要点:
https://gist.github.com/davidwhitney/1027181
感谢您提供的改编这个解决方法更符合我的需求,因为我也找到了解决方法,但仍在努力适应 MVC。现在我只需要调整您的解决方案,将 RSS 提要放入我正在使用的 .ashx 处理程序中的当前 Http 请求。
基本上,我猜测您提到的使用 CDataSyndicateContent 的修复是从 2011 年 2 月开始的,假设你从这篇文章中得到了它(至少我做到了):
SynminationFeed:内容为 CDATA?
此修复程序在某些较新的 ASP.NET 版本或其他版本中停止工作,由于 Rss20FeedFormatter 的代码更改为您在帖子中放置的内容。此代码更改也可能是对 MVC 框架中其他内容的改进,但对于那些使用 CDataSyndicateContent 修复的人来说,它肯定会导致错误!
Well @Page Brooks, I see this more as a solution then as a question :). Thanks!!! And to answer your question ( ;) ), yes, I definitely think this is a bug in the Rss20FeedFormatter (though I did not chase it as far), because had encountered precisely the same issue that you described.
You have a 'localhost:8732' referral in your post, but it wasn't available on my localhost ;). I think you meant to credit the 'PostProcessOutputBuffer' workaround to this post:
http://damieng.com/blog/2010/04/26/creating-rss-feeds-in-asp-net-mvc
Or actually it is not in this post, but in a comment to it by David Whitney, which he later put in a seperate gist here:
https://gist.github.com/davidwhitney/1027181
Thank you for providing the adaption of this workaround more to my needs, because I had found the workaround too, but was still struggling to do the adaptation from MVC. Now I only needed to tweak your solution to put the RSS feed to the current Http request in the .ashx handler that I was using it in.
Basically I'm guessing that the fix you mentioned using the CDataSyndicationContent, is from feb 2011, assuming you got it from this post (at least I did):
SyndicationFeed: Content as CDATA?
This fix stopped working in some newer ASP.NET version or something, due to the code of the Rss20FeedFormatter changing to what you put in your post. This code change might as well have been an improvement for other stuff that IS in the MVC framework, but for those using the CDataSyndicationContent fix it definitely causes a bug!
我确信已经有人指出了这一点,但这是我使用的一个愚蠢的解决方法。
t.OutputSettings 是 XmlWriterSettings 类型,其中 cdataSections 填充有单个 XmlQualifiedName“描述”。
希望它对其他人有帮助。
I'm sure someone pointed this out already but this a stupid workaround I used.
t.OutputSettings is of type XmlWriterSettings with cdataSections being populated with a single XmlQualifiedName "description".
Hope it helps someone else.
我在其他地方找到了 Cdata 的代码,
代码将其称为类似的内容:
但是“WriteContentsTo”函数没有被调用。
我尝试了 Atom10FeedFormatter,而不是 Rss20FeedFormatter - 并且它有效!
显然,这提供了 Atom feed,而不是传统的 RSS - 但值得一提。
输出代码为:
I found the code for Cdata elsewhere
Code to call it something along the lines:
However the "WriteContentsTo" function wasn't being called.
Instead of Rss20FeedFormatter I tried Atom10FeedFormatter - and it worked!
Obviously this gives Atom feed rather than traditional RSS - but worth mentioning.
Output code is: