ASP.NET MVC中的RSS源


113

您如何建议在ASP.NET MVC中处理RSS源?使用第三方图书馆?在BCL中使用RSS内容?只是制作一个呈现XML的RSS视图?还是完全不同的东西?


使用RssToolkit,您只需要在项目中具有一个.ashx文件即可生成RSS feed。然后,您可以将其URL重写为友好的URL。我认为这种方法没有针对MVC的任何东西。
Mahdi Taghizadeh,

这是一个后续帖子,它通过通用的SyndicationAction结果类以及304 NotModified条件获取筛选器,进一步完善了RssActionResult的想法。58bits.com/blog/...
湛蓝的海水

我已经写了一个RssResult,您可以看一下。它应该满足您的要求http://www.wduffy.co.uk/blog/rssresult-aspnet-mvc-rss-actionresult/
WDuffy

1
只是为了在上次编辑后的18个月内更新此问题-质疑“在.net和mvc的迭代中是否发生了变化,这些都会改变我们如何处理供稿管理问题?”似乎是合理的?共识(通过不同的SO线程)是:“无根本变化-这仍然是您的最佳选择。”
justSteve 2011年

ASP.NET MVC的错误建议。
tugberk 2011年

Answers:


64

这是我的建议:

  1. 创建一个名为RssResult的类,该类继承了抽象基类ActionResult。
  2. 重写ExecuteResult方法。
  3. ExecuteResult由调用者传递给ControllerContext,您可以通过它获取数据和内容类型。
  4. 将内容类型更改为rss后,您将需要将数据序列化为RSS(使用您自己的代码或其他库)并写入响应。

  5. 在要返回rss的控制器上创建一个动作,并将返回类型设置为RssResult。根据要返回的内容从模型中获取数据。

  6. 然后,对该操作的任何请求都会收到您选择的任何数据的rss。

这可能是返回rss对ASP.NET MVC中的请求做出响应的最快和可重用的方法。


10
Hanselman有一个类似的解决方案(视频:大约41m开始),他从FileResult继承而来。这样,您可以调用类的构造函数,base("application/rss+xml")并避免执行第3步和第4步。他确实重写了ExecuteResult,但这并不是至关重要的。他也快捷了很多典型的,朴素的代码,并使用的3.5+功能SyndicateItemSyndicateFeedRss20FeedFormatter
patridge

@Dale:当您要输出以馈入部分视图时,是否可以写入响应?谢谢。
基督教徒

1
从我之前的评论中更新了Hanselman的视频链接。
patridge'7

150

.NET框架公开了处理联合的类:SyndicationFeed等。因此,除了自己进行渲染或使用其他建议的RSS库之外,为什么不让该框架来处理它呢?

基本上,您只需要以下自定义ActionResult即可开始使用:

public class RssActionResult : ActionResult
{
    public SyndicationFeed Feed { get; set; }

    public override void ExecuteResult(ControllerContext context)
    {
        context.HttpContext.Response.ContentType = "application/rss+xml";

        Rss20FeedFormatter rssFormatter = new Rss20FeedFormatter(Feed);
        using (XmlWriter writer = XmlWriter.Create(context.HttpContext.Response.Output))
        {
            rssFormatter.WriteTo(writer);
        }
    }
}

现在,在控制器操作中,您可以简单地返回以下内容:

return new RssActionResult() { Feed = myFeedInstance };

我的博客上有完整的示例,网址http://www.developerzen.com/2009/01/11/aspnet-mvc-rss-feed-action-result/


34

我同意哈克德的观点。我目前正在使用MVC框架来实现我的站点/博客,并采用了创建RSS新视图的简单方法:

<%@ Page ContentType="application/rss+xml" Language="C#" AutoEventWireup="true" CodeBehind="PostRSS.aspx.cs" Inherits="rr.web.Views.Blog.PostRSS" %><?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>ricky rosario's blog</title>
<link>http://<%= Request.Url.Host %></link>
<description>Blog RSS feed for rickyrosario.com</description>
<lastBuildDate><%= ViewData.Model.First().DatePublished.Value.ToUniversalTime().ToString("r") %></lastBuildDate>
<language>en-us</language>
<% foreach (Post p in ViewData.Model) { %>
    <item>
    <title><%= Html.Encode(p.Title) %></title>
    <link>http://<%= Request.Url.Host + Url.Action("ViewPostByName", new RouteValueDictionary(new { name = p.Name })) %></link>
    <guid>http://<%= Request.Url.Host + Url.Action("ViewPostByName", new RouteValueDictionary(new { name = p.Name })) %></guid>
    <pubDate><%= p.DatePublished.Value.ToUniversalTime().ToString("r") %></pubDate>
    <description><%= Html.Encode(p.Content) %></description>
    </item>
<% } %>
</channel>
</rss>

有关更多信息,请查看(无耻的插件)http://rickyrosario.com/blog/creating-an-rss-feed-in-asp-net-mvc


4
供Razor使用:@model PageModel @ {Response.ContentType =“ application / rss + xml”; } <?xml version =“ 1.0” encoding =“ UTF-8”?>
Anthony Johnston

2
什么开销?您的意思是您编写更少的代码以更易读的方式完成同一件事的事实?
保罗

12

另一种疯狂的方法却有其优势,那就是使用普通的.aspx视图来呈现RSS。在您的操作方法中,只需设置适当的内容类型。这种方法的一个好处是很容易理解正在渲染的内容以及如何添加自定义元素(例如地理位置)。

再说一次,列出的其他方法可能更好,我只是没有使用过。;)


3
@Haacked:世界充满了由模板系统生成的无效RSS XML。请不要添乱!Ricky,HTML编码!= XML编码。
布拉德·威尔逊

以下是来自MSDN的Html Encode的文档:>由于当前的实现细节,该函数可以用作xmlEncode函数。当前,此函数使用的所有命名实体也是xml预定义的命名实体。它们是<>“&编码为&lt;&gt;和&amp;。其他实体采用十进制编码,例如&#160; 。http://msdn.microsoft.com/en-us/library/73z22y6h.aspx
瑞奇

通过这种方式如何确保XML有效?如果将视图呈现与传入的Web请求分离,以使XML视图或电子邮件模板(如在rails上完成ruby)成为可能,那就太好了。
Paco

您可以创建一个从ActionResult派生的RssResult,而不是使用视图引擎。我们使用JsonResult将对象序列化为JSON。在您的情况下,您会发现一些序列化程序(我认为WCF有一个)可以序列化为RSS。
哈克

8

我是从Eran Kampf和Scott Hanselman vid(忘记了链接)那里获得的,所以它与这里的其他帖子只是略有不同,但希望会有所帮助,并准备好粘贴粘贴作为rss feed示例。

从我的博客

伊兰·坎普夫(Eran Kampf)

using System;
using System.Collections.Generic;
using System.ServiceModel.Syndication;
using System.Web;
using System.Web.Mvc;
using System.Xml;

namespace MVC3JavaScript_3_2012.Rss
{
    public class RssFeed : FileResult
    {
        private Uri _currentUrl;
        private readonly string _title;
        private readonly string _description;
        private readonly List<SyndicationItem> _items;

        public RssFeed(string contentType, string title, string description, List<SyndicationItem> items)
            : base(contentType)
        {
            _title = title;
            _description = description;
            _items = items;
        }

        protected override void WriteFile(HttpResponseBase response)
        {
            var feed = new SyndicationFeed(title: this._title, description: _description, feedAlternateLink: _currentUrl,
                                           items: this._items);
            var formatter = new Rss20FeedFormatter(feed);
            using (var writer = XmlWriter.Create(response.Output))
            {
                formatter.WriteTo(writer);
            }
        }

        public override void ExecuteResult(ControllerContext context)
        {
            _currentUrl = context.RequestContext.HttpContext.Request.Url;
            base.ExecuteResult(context);
        }
    }
}

还有控制器代码。

    [HttpGet]
public ActionResult RssFeed()
{
    var items = new List<SyndicationItem>();
    for (int i = 0; i < 20; i++)
    {
        var item = new SyndicationItem()
        {
            Id = Guid.NewGuid().ToString(),
            Title = SyndicationContent.CreatePlaintextContent(String.Format("My Title {0}", Guid.NewGuid())),
            Content = SyndicationContent.CreateHtmlContent("Content The stuff."),
            PublishDate = DateTime.Now
        };
        item.Links.Add(SyndicationLink.CreateAlternateLink(new Uri("http://www.google.com")));//Nothing alternate about it. It is the MAIN link for the item.
        items.Add(item);
    }

    return new RssFeed(title: "Greatness",
                       items: items,
                       contentType: "application/rss+xml",
                       description: String.Format("Sooper Dooper {0}", Guid.NewGuid()));

}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.