Eduardo Molteni
Eduardo Molteni

Reputation: 39453

Good and full implementation of RSS feeds in ASP.net MVC

I've seen a few examples of RSS Feeds in ASP.NET MVC, like this, and some samples in projects (like Oxite), but none of them are complete.

Eg. None of them check for the header

  If-Modified-Since

in the request, to save bandwidth.

I do not want to reinvent the wheel, so I stop here asking for some directions.

Upvotes: 2

Views: 4666

Answers (3)

Eduardo Molteni
Eduardo Molteni

Reputation: 39453

I ended up with this. Please comment or edit the post if you find any error or better way to do it.

RssController

Imports System.ServiceModel.Syndication
Imports System.Xml
Imports System.Web.HttpContext

Function MasterRSS()
    Dim baseURL As String = "http://www.mysite.com"
    Dim feed As New SyndicationFeed("MySite - Master RSS", "", New Uri(baseURL))
    ''//Add a custom attribute.
    Dim xqName As New XmlQualifiedName("CustomAttribute")
    feed.AttributeExtensions.Add(xqName, "Value")

    Dim sp As New SyndicationPerson("[email protected]", "Jerry Seinfeld", "http://Jerry.blog.com")
    feed.Authors.Add(sp)

    Dim category As New SyndicationCategory("Category")
    feed.Categories.Add(category)

    feed.Contributors.Add(New SyndicationPerson("[email protected]", "Cosmo Kramer", "http://kramer.blog.com"))
    feed.Copyright = New TextSyndicationContent("MySite 2008")
    feed.Description = New TextSyndicationContent("My description")

    ''//Add a custom element.
    Dim doc As New XmlDocument()
    Dim feedElement As XmlElement = doc.CreateElement("CustomElement")
    feedElement.InnerText = "Some text"
    feed.ElementExtensions.Add(feedElement)

    feed.Generator = "Custom"
    feed.Id = "MySiteFeedID"
    feed.ImageUrl = New Uri("http://www.mysite.com/content/images/logo.png")

    ''//Items
    Dim ModifiedSince As Date
    If Not Date.TryParse(Current.Request.Headers("If-Modified-Since"), ModifiedSince) Then
        ModifiedSince = Date.Today.AddDays(-30) ''//Or whatever make sense to you.         
    Else
        ModifiedSince.AddMinutes(-5) ''//Just in case, we do not want to miss any item. 
    End If

    ''//the list of items.
    Dim items As New List(Of SyndicationItem)()


    Dim db As New mainDataContext
    Dim textContent As TextSyndicationContent, Item As SyndicationItem

    ''//Then send the list of post, comments, whatever.
    Dim Posts = (From p In db.Posts Where c.Date >= ModifiedSince Order By p.Date Descending)
    For Each Post In Posts
        Dim sb As New StringBuilder
        sb.AppendFormat("<p>{0}</p>", Post.FullText)
        textContent = New TextSyndicationContent(sb.ToString, TextSyndicationContentKind.Html)
        Item = New SyndicationItem("Post " + Post.PostID.ToString, textContent, New Uri(baseURL + "/Post/View/" + Post.PostID.ToString), "Post" + Post.PostID.ToString, Post.Date)
        items.Add(Item)
    Next


    If items.Count = 0 Then
        ''//send a 304 to the browser.
        Return View("304")
    End If

    feed.Items = items
    feed.Language = "es-ar"
    feed.LastUpdatedTime = (From i In items Select i.LastUpdatedTime Order By LastUpdatedTime Descending).FirstOrDefault

    ''//Not needed in this sample.
    ''//Dim link As New SyndicationLink(New Uri("http://server/link"), "alternate", "Link Title", "text/html", 1000)
    ''//feed.Links.Add(link)

    ViewData("feed") = feed
    Return View("Rss")

End Function

Rss View (rss.aspx)

Dim htmlwriter As System.IO.Stream = Response.OutputStream
Dim rssWriter As System.Xml.XmlWriter = System.Xml.XmlWriter.Create(htmlwriter)
Dim feed As System.ServiceModel.Syndication.SyndicationFeed = ViewData("feed")
Dim rssFormatter As New System.ServiceModel.Syndication.Rss20FeedFormatter(feed)
rssFormatter.WriteTo(rssWriter)
rssWriter.Close()

This way, you can reuse the view

Upvotes: 2

Duncan Smart
Duncan Smart

Reputation: 32088

If you use HttpContext.Response.Cache.SetCacheability, SetExpires and SetMaxAge then the ASP.NET caching system will take care of this for you - it understands the If-Modified-Since header. This blog entry shows how you can create an MVC Action Filter to do the necessary in MVC.

Upvotes: 2

Trevor de Koekkoek
Trevor de Koekkoek

Reputation: 2506

I haven't seen it implement HTTP_IF_MODIFIED_SINCE, but I would look into using the SyndicationFeed class. It makes it very simple to handle feeds without any parsing. I am currently using it for Atom feeds, but it is supposed to work for RSS as well:

function SyndicationFeed GetFeed(string url) {
  XmlReader reader = XmlReader.Create(url);
  SyndicationFeed feed = SyndicationFeed.Load(reader);
  return feed;
}

public ActionResult ShowFeed()
{
  string feedUrl = "somefeedurl";
  SyndicationFeed feed = GetFeed(feedUrl);
  return View(feed);
}

...then in the view:

  <%foreach (var item in ViewData.Model.Items) { %>
    <li><a href="<%=item.Id %>"><%=item.Title.Text %></a></li>
  <% } %>

Upvotes: 4

Related Questions