Rss Feed Generation From a Custom RssResult

4.62 (8 votes)

When I looked at producing RSS Feeds in ASP.NET MVC before, I used the ContentResult method to return XML. Best Practice suggests that you should create a new ActionResult if required. So this article looks at creating an RssResult, and a different way to generate the feed itself.

If you look at the previous article, and its comments, you can see that there are a number of ways to produce RSS feeds in ASP.NET MVC. Some feel that you should return a model from the controller, and format it in a View, and others are happy not to have a View at all. I'm not keen on the idea of returning XML to a View template. It's prone to validation errors as it requires you to manually construct the XML. The same could be said of the approach using LINQ to XML in my previous article. However, in WCF there is an Rss20FeedFormatter class that solves the problem.

I'm going to start with the RssResult itself. This derives from ActionResult, and the ExecuteResult() method is over-ridden. You'll notice that System.ServiceModel.Syndication appears in the usings. and this is made available by adding a reference to System.ServiceModel.Web. Feed Formatters for RSS and Atom live in System.ServiceModel.Syndication. The RssResult class has a SyndicationFeed property, which is passed to the Rss20FeedFormatter object, which has a WriteTo() method. This takes an XmlWriter, and simply produces the XML as a result.


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

namespace MikesDotnetting.Models
{
    public class RssResult : ActionResult
    {
        public SyndicationFeed Feed { private get; set; }

        public override void ExecuteResult(ControllerContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            context.HttpContext.Response.ContentType = "text/xml";

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

At the moment, if you generate the Feed object in a Controller, you would have to call the ActionResult like this:


return new RssResult() {Feed = feed};

Ideally, we would like the call to the ActionResult to look similar to the shorthand available to existing framework ActionResults ( return View() instead of return new ViewResult()etc) so I am going to create a BaseXmlController to help with that:


using System.ServiceModel.Syndication;
using System.Web.Mvc;
using MikesDotnetting.Models;


namespace MikesDotnetting.Controllers
{
    public class BaseXmlController : Controller
    {
        protected static RssResult Rss(SyndicationFeed feed)
        {
            return new RssResult
            {
                Feed = feed
            };
        }


    }
}

Now, as with the Framework ActionResults, there is a method called Rss() which wraps the RssResult construction. So we'll have a look at the Controller action:


[OutputCache(VaryByParam = "none", Duration = 3600)]
public RssResult RssFeed()
{
    const string url = "http://www.mikesdotnetting.com/Article/{0}/{1}";
    var posts = repository.GetRSSFeed();
    var feed = new SyndicationFeed("Mikesdotnetting News Feed",
                    "Latest additions to Mikesdotnetting",
                    new Uri("http://www.mikesdotnetting.com/rss"))
                                 {
                                     Copyright =
                                             new TextSyndicationContent("(c)" + DateTime.Now.Year +
                                             ", Mikesdotnetting. All rights reserved")
                                 };
    var items = new List<SyndicationItem>();
    foreach (var post in posts)
    {
        var item = new SyndicationItem(
        			post.Head,
                    post.Intro,
                    new Uri(String.Format(url,
                    	post.ID,
                        post.Head.ToCleanUrl())),
                    post.ID.ToString(),
                    post.CreatedDate
                    );
        items.Add(item);
    }
    feed.Items = items;
    return Rss(feed);
}

I've added caching to this action, although the hour I've given it is a bit optimistic. My RSS feed changes once a week at most on average, but at least people can see new items within an hour of them appearing when they do finally make it onto my site. But you can see some of the Syndication classes at work. The top level class is a SyndicationFeed object, which is composed of a collection of SyndicationItem objects. ToCleanUrl() is an extension method I created to format the article titles to play nicely with URLs.

This approach certainly relieves the burden of generating valid RSS feeds as the Framework takes care of that for you. The use of custom ActionResults also reveals intentions very nicely. Anyone reading the code for this method can be in no doubt what it is intended to produce.

You might also like...

Date Posted:
Last Updated:
Posted by:
Total Views to date: 10273

0 Comments

Recent Comments

Pam 30/08/2017 11:30
In response to Sending Email in Razor Pages
Mike, RazorPages sound like a nice choice for somebody still working in ASP classic who wants to to...

Robby Robson 15/08/2017 00:43
In response to Routing in Razor Pages
Mike: great stuff. Now that .Core Standard 2.0 is formally out, how soon will you rewrite your book...

Satyabrata Mohapatra 28/07/2017 08:59
In response to Sending Email in Razor Pages
Bit off topic, but congratulation sir for your MVP award. You deserve it !!!...

Satyabrata Mohapatra 23/07/2017 16:43
In response to Razor Pages - The Elevator Pitch
@Dale Severin You can continue to build apps using asp.net web pages....

Satyabrata Mohapatra 23/07/2017 16:40
In response to Sending Email in Razor Pages
Thanks for sharing...learned a lot...

Gfw 22/07/2017 11:53
In response to Sending Email in Razor Pages
Question... Does System.Net.Mail support SSL?...

Dale Severin 20/07/2017 03:38
In response to Razor Pages - The Elevator Pitch
I work with razor web pages extensively. I appreciate the rapid development it permits me to I am as...

Obinna Okafor 14/07/2017 01:19
In response to Routing in Razor Pages
Thank you, Mike. Good post....

Satyabrata Mohapatra 11/07/2017 16:02
In response to Routing in Razor Pages
Very powerful routing system!!...

Cyrus 05/07/2017 03:41
In response to Razor Pages - Getting Started With The Preview
How can I trim packages and services as much as possible to use just razor pages? I don’t want to to...