WynApse Home Page
Home    Blog    About    Contact       
Latest Article:


My Tags:
My Sponsors:






Lifetime Member:

Blog Roller using RssTookit



AZGroups used to have a 'Blog Roller', which consisted of the latest couple entries from any of the member's blogs. I liked going there and being able to read the 'headlines' and decide what I wanted to read rather than either go through each blog in order, or wait for them to show up in email.

Squeet came along, and maybe that's when the roller went away. Squeet works great, and I have a bunch of feeds being emailed to me at home and at my work email address. This is an excellent solution for me, working inside a restrictive environment. I'm fairly certain that I wouldn't be able to run something like a feed reader that's out there hammering on the web for very long without attracting a group of IT folks at my desk.

Bloglines gets a little closer with their Playlists, and there's also Google Reader, and probably others as well. These are the only ones I've played with.

All of these solutions have some drawbacks, at least for how I'd like to use them. Google Reader and Bloglines both seem to have 'stale' data. This must have something to do with their caching and the fact that it's supporting tons of people, not just me. I don't fault them for how they are doing it, but if I want to see what Scott Guthrie is writing, I'd rather see what he wrote this morning, than what he wrote last week. Squeet is much better in this respect, but I've had some messages come through multiple times, and again there's a lag between publishing and receiving.

If I'm wanting to take a short break from work, it would be much quicker to have one 'go-to' place to have all the folks I want to read all clustered together, showing the top x headlines from their blogs.

My Blog Roller

My solution was, obviously, to code up my own. When I saw articles or code that I thought would be useful to me, I captured them. It wasn't until I found Dmitryr's RssToolkit, however, that I knew I found IT. I played with the 'Scenarios' delivered with the toolkit, and very quickly had a single-feed aggregator running. I also quickly realized that multiples might be a problem because I really didn't want to code up a variable number of instances of the same code.

After playing with the code for a bit, I did a search for RssToolkit and found a posting by wsmonroe where he discussed opening the channel and extracting the information yourself rather than just binding to the source.

The Challenges

My list of challenges then became smaller, and were more or less controlled. I already had the newsfeeds in my database because I display them in a block on my MasterPage. So bringing them out to a datareader and stepping through them should be no problem. For each one, I then had a name and a link, so I could feed the link into the code hacked from wsmonroe's article.

But I still needed a way to get the headings and links to the web page. Because of how I wanted the display to appear, a Repeater was the logical choice. That way I could code up the Header with captions and the easily control the data display. Looking through Stephen Walther's ASP.NET Unleashed, I found that the Repeater can be bound to anything that looks like a collection. I was going to go for a SortedList first, but abandonded it in favor of an ArrayList because I could have multiple elements of data.

In a post at Velocity Reviews by Karl Seguin, Karl points out that DataBinder.Eval understands the getter property, and that was the end of the exploration.

Client Code

On the client side, the only thing showing is the Repeater control:

<asp:Repeater ID="Repeater1" runat="server">
    <HeaderTemplate>
       <table border=0 cellpadding=0 cellspacing=0>
          <tr>
             <td class="HeadingName">Blog Owner</td>
             <td class="HeadingOther">Date</td>
             <td class="HeadingOther">Entry Title</td>
          </tr>
    </HeaderTemplate>
    <ItemTemplate>
       <tr>
          <td nowrap=nowrap style="font-family: Tahoma; color: #00008b; font-size: large; padding-right: 10px">
             <%# DataBinder.Eval(Container.DataItem, "Owner") %>
          </td>
          <td nowrap=nowrap style="font-family: Tahoma; color: #00008b; font-size: small; padding-right: 10px">
             <%# StripDate((string)DataBinder.Eval(Container.DataItem, "PageDate")) %>
          </td>
          <td style="font-family: Tahoma; color: #00008b; font-size: small">
             <a href="<%# DataBinder.Eval(Container.DataItem, "PageLink") %>" target="_blank"><%# DataBinder.Eval(Container.DataItem, "PageTitle") %></a>
          </td>
       </tr>
    </ItemTemplate>
    <FooterTemplate>
       </table>
    </FooterTemplate>
</asp:Repeater>

Note the syntax on, for example, the Owner:

<%# DataBinder.Eval(Container.DataItem, "Owner") %>

"Owner" is not the name of the field, it is the name of the getter for the field as you will see in the Code Behind.

Code Behind

I have one class defined for populating my ArrayList, and that is blogPage, shown in part here:

public class blogPage
{
    string _Owner;
    string _PageTitle;
    string _PageDate;
    string _PageLink;

    public blogPage(string sOwner, string sPageTitle, string sPageDate, string sPageLink)
    {
        _Owner = sOwner;
        _PageTitle = sPageTitle;
        _PageDate = sPageDate;
        _PageLink = sPageLink;
    }

    public string Owner
    {
        get
        {
            return _Owner;
        }
        set
        {
            _Owner = Owner;
        }
    }

This class will get tweaked as I add reading "Atom" feeds, and possibly show the first few lines of the post.

The code that populates the Repeater is here in it's entirety:

ArrayList aList = new ArrayList();

Support LocSupt = new Support();

SqlDataReader drFeeds = LocSupt.getNewsFeeds();

while (!drFeeds.IsClosed && drFeeds.Read())
{
    if ((drFeeds[0].ToString() == "") || (drFeeds[1].ToString() == ""))
    {
        break;
    }
    RssToolkit.GenericRssChannel rssData = RssToolkit.GenericRssChannel.LoadChannel(drFeeds[1].ToString());
    int nCount = 0;
    foreach (RssToolkit.GenericRssElement Item in rssData.Items)
    {
        aList.Add(new blogPage(drFeeds[0].ToString(), Item.Attributes["Title"], Item.Attributes["PubDate"], Item.Attributes["Link"]));
        if (nCount++ == 2)
        {
            break;
        }
    }
        aList.Add(new blogPage("-----", "", "", ""));

}
drFeeds.Close();

this.Repeater1.DataSource = aList;
this.Repeater1.DataBind();

I wanted a way to separate the individual authors and struck upon the idea of simply adding a list entry that only has the Author populated, and with "-" marks. I tried using a line of spaces, but the Repeater ignored it.

Support is a generic name I use for my support class to provide database access or other generic functionality that I want to keep out of my code body. getNewsFeeds simply returns an SqlDataReader of the author and link fields from my NewsFeeds table.

The link is used to load the channel, and the ListArray is populated with feed data for the latest 3 entries.

The Repeater DataSource is then pointed at the list, and a DataBind() executed, completing the task.

One more small piece of Code Behind remains and that is the code executed during

<%# StripDate((string)DataBinder.Eval(Container.DataItem, "PageDate")) %>

and that is the StripDate method. The dates returned on the blogs are, for the most part, of the form:

Sun, 26 Mar 2006 08:05:00 GMT

As a real quick-and-dirty, I pulled out just the date part as a string, without any other manipulation. That's not a great solution as you can tell from the dates on the DotNetBips entries. A better (enhancement) solution would be to convert the string to a date and pop it back out the way I want it.

Enhancements

The date issue mentioned above is one obvious enhancement, since the current solution was just slapped together.

I need to deal with "Atom" feeds. I dropped Squeet's feed into the list without thinking about it, and the page blew up. That would not be good remotely since I don't have direct database access from the office during the day.

The time-to-screen is a little rough. If it bothers me a LOT, I've been thinking of some caching of data. It's only a link and caption times 3 for each feed, but somehow need to make it be seamless... I'll keep thinking.

For active blogs like ASP.NET, only showing 3 doesn't cut it, and I may want to consider date checking at the least. Maybe show 2 days worth or back in time until I get 3... interesting logic puzzle on that one maybe.

The 'Add a feed' code is very brittle at this point, with only 'Add', no way to Modify or Delete, so that will have to be augmented now that things are functional, but that's not something a reader of the page would notice

Overall, it serves my purpose and that was it's reason for being, so I'm happy with it!



Copyright © 2006-2017, WynApse