RSS Feed with the new ASP.NET MVC Framework

I thought I'd add my own MVC example to the great work that ScottGu and Hanselman have already outlined...     I know folks are ready to get their hands on these bits and believe me the team is working hard to get them out in a public CTP as soon as we can.. In the mean time, you will have to settle for these teasers ;-) 

 

In this example, I am going to walk through building an RSS feed from data in a relational database..  My goal here is to give you and idea of what is possible with the MVC support that is coming out as a CTP soon for ASP.NET...

 

File/New Project and select the MVC Project item

image

There is some good stuff here, that really shows you how to get going... but for what we are going to do, we don't really need it...  so go ahead and clear out all the directories and files under Views, Models and Controllers... we will build this from scratch.

 

Creating the Model

Because I had an existing database, I chose to start with it...  I added my VideoDatabase.mdf file from another project I worked on recently.. of course any database would work.  Then I created a Linq model and called it "VideoDatabase.dbml"... Notice of course EntityFramework would work really well here as well... 

image

In the LINQ designer, I added the Items table to the design surface

image

and then moved the resulting VideoDatabase.dbml file to the Models directory... We now have our model done! 

 

Creating the Controller

Next we add our controller which handles the UI logic of our application..  I click on the Controllers folder and Add new item

image

I called it FeedController, but remember, this has to end in Controller as there are some conventions we use to find these types.. I added the following code to get the list of items from the database and pass it to the view...

    public class FeedController : Controller

    {

        //example: https://localhost:64701/

        [ControllerAction]

        public void Index()

        {

            VideoDatabaseDataContext context = new VideoDatabaseDataContext();

            var list =

                from item in context.Items

                orderby item.Title

                select item;

            RenderView("Feed", list.ToList());

        }
}

(note: be sure to add using MvcApplication.Models)

 

Creating the View

The view we want for an RSS feed is actually an not HTML... it is an XML file... but we want to programmatically generate it.  I started by creating a new directory called "Feed" under "View" and added an MVC View Page called "Feed"... 

image

Then I went to my blog and grabbed the RSS feed to use as an example.  You can create a temporary XML file in VS to view it cleanly, then strip all but one entry...   You will end up with something like this:

image

Next we need to parameterize this to use the data from our Model... 

The first thing to do to enable that is to type the ViewData this page will work with.. you do that by going into the codebehind and setting the base class to be associated with the Item from our Model...  

namespace MvcApplication.Views.Feed

{

    public partial class Feed : ViewPage<IList<Item>>

    {

    }

}

(note: be sure to add using System.Collections.Generic and using MvcApplication.Models)

Then, back in the feed.aspx page, you can access the view data... right before the open <item> add the start of a foreach loop, then close it after the end...

<%  foreach (Item item in this.ViewData) { %>

 

    <item>

Then, replace each value with the appropriate data from the view programmatically... 

<link><%= item.VideoLink%> </link>

What you end up with looks like this:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Feed.aspx.cs" Inherits="MvcApplication.Views.Feed.Feed" %>

<%@ Import Namespace="MvcApplication.Models" %>

<%@ Import Namespace="System.Collections.Generic" %><?xml version="1.0" encoding="utf-8"?>

<rss version="2.0" xmlns:atom="https://www.w3.org/2005/Atom" xmlns:cf="https://www.microsoft.com/schemas/rss/core/2005" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/" xmlns:wfw="https://wellformedweb.org/CommentAPI/">

  <channel xmlns:cfi="https://www.microsoft.com/schemas/rss/core/2005/internal" cfi:lastdownloaderror="None">

    <title cf:type="text"> MySilverlightTV Feed</title>

    <link>https://blogs.msdn.com/brada/default.aspx</link>

    <description cf:type="text">Check out the latest videos from MySilverlightTV</description>

    <dc:language>en-US</dc:language>

    <generator>MVC RSS</generator>

 <% foreach (Item item in this.ViewData) { %>

 

    <item>

      <title xmlns:cf="https://www.microsoft.com/schemas/rss/core/2005" cf:type="text">

        <%= item.Title %> </title>

      <link><%= item.VideoLink%> </link>

      <pubDate><%= DateTime.Now.ToFileTimeUtc() %> </pubDate>

      <author><%= item.Owner%> </author>

      <description xmlns:cf="https://www.microsoft.com/schemas/rss/core/2005" cf:type="html">

        <%= item.Description %>

      </description>

    </item>

 <% } %>

  </channel>

</rss>

 

 

Run it

We want to navigate to the Controller we created..  so navigate to https://localhost:64701/feed

and you get this beautiful RSS feed ready to work in any blog reader:

image

 

But there is more

Of course there is was only a few lines of code here, but really I could have done this just as easily, what does all that MVC stuff buy you?    Well, a good architecture for one, and that means it is super flexible.  So when you need to add a different feed, say the most popular items, or the new items added, or the top 10 items, it is very easy to do...  Here are a few more items I added by only touching the controller, everything else stayed the same:

 

    public class FeedController : Controller

    {

        //example: https://localhost:64701/

        [ControllerAction]

        public void Index()

        {

            VideoDatabaseDataContext context = new VideoDatabaseDataContext();

            var list =

                from item in context.Items

                orderby item.Title

                select item;

            RenderView("Feed", list.ToList());

        }

        //example: https://localhost:64701/feed/Top10

        [ControllerAction]

        public void Top10()

        {

            VideoDatabaseDataContext context = new VideoDatabaseDataContext();

            var list =

                from item in context.Items

                orderby item.Rating

                select item;

            RenderView("Feed", list.Take(10).ToList());

        }

        //example: https://localhost:64701/feed/Top?n=2

        [ControllerAction]

        public void Top(int n)

        {

            VideoDatabaseDataContext context = new VideoDatabaseDataContext();

            var list =

                from item in context.Items

                orderby item.Rating

                select item;

            RenderView("Feed", list.Take(n).ToList());

        }

        //example: https://localhost:64701/feed/FromMSFT

        [ControllerAction]

        public void FromMSFT()

        {

            VideoDatabaseDataContext context = new VideoDatabaseDataContext();

            var list =

                from item in context.Items

                orderby item.Title

                where item.Owner == "MSFT"

                select item;

            RenderView("Feed", list.ToList());

        }

        //example: https://localhost:64701/feed/FromPublisher?Publisher=WildAmerica

        [ControllerAction]

        public void FromPublisher(string publisher)

        {

            VideoDatabaseDataContext context = new VideoDatabaseDataContext();

            var list =

                from item in context.Items

                orderby item.Title

                where item.Owner == publisher

                select item;

            RenderView("Feed", list.ToList());

        }

    }

 

 

What do you think?  are we on the right track?