Creating an RSS Reader Using ASP.NET and LINQ – Part 2

Back in Part 1, we put together the first part of our application. We defined a list of RSS feeds and pulled in the list into a drop-down list box. In this post, we’ll get our selection from the user and build a list of atricles from the RSS feed data.

Entry Data Storage

The first step is to decide what data we want to display. In our example, we’ll display the following fields:

  • Title
  • Published Date
  • Tags

Along with these fields, we’ll need to know the entry’s URL so that we can allow the user to display the blog entry. As with the feed definitions, we’ll store this information in a basic class:

public class BlogEntryDefinition
{
   public string Title { get; set; }
   public string Url { get; set; }
   public IEnumerable Tags { get; set; }
   public DateTime Published { get; set; }
}

Getting The User’s Selection

Before we can process the feed data, we need to know what feed the user wants to display. In our display, we placed an Open button next to our combo box. When the user presses this button, this will let our program know when to process the selection.

We must fist update our display code for the button, specifying an event handler method that will be called when the user clicks on the button. We do this by specifying a method name for the OnClick parameter:

<asp:Button ID="OpenButton"
            Text="Open"
            OnClick="OpenButton_OnClick"
            runat="server" />

Back in our code-behind, we need to define the method:

protected void OpenButton_OnClick(object sender, EventArgs e)
{
}

When the user clicks on the button, this method will be called. The sender parameter will be the object that initiated the OnClick event, in this case our button, and the e parameter will contain the arguments for the event. In our example, we won’t use these parameters.

Loading The Blog Entry Definitions

To load up the list of blog entries, we process the data in the same way that we did when we loaded up our feed definitions. The only difference is that rather than getting the data from a file on our web server, we are loading the data from a URL. We get the URL from our drop-down list box control through the SelectedValue property:

XDocument rssFeed = XDocument.Load(FeedList.SelectedValue);
var posts = from item in rssFeed.Descendants("item")
select new BlogEntryDefinition()
{
   Title = (string)item.Element("title"),
   Url = (string)item.Element("link"),
   Published = DateTime.Parse((string)item.Element("pubDate")),
   Tags = from category in item.Elements("category")
          orderby (string)category
          select (string)category
};

Building The Display

There are multiple ways in which you could display the data. In our example, we’ll use a grid view control. We’ll manually define the columns of the control so that we can specify custom cell values:

<asp:GridView ID="FeedDetailsGrid"
              runat="server"
              AutoGenerateColumns="false"
              Font-Name="Verdana"
              Font-Size="10pt"
              Cellpadding="4"
              HeaderStyle-BackColor="#444444"
              HeaderStyle-ForeColor="White"
              AlternatingRowStyle-BackColor="#dddddd">
              <Columns>
                <asp:TemplateField>
                  <HeaderTemplate>Published</HeaderTemplate>
                  <ItemTemplate>
                    <%#Eval("Published", "{0:G}") %>
                  </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField>
                  <HeaderTemplate>Article</HeaderTemplate>
                  <ItemTemplate>
                    <a href='<%#Eval("Url") %>' target="_blank"><%#Eval("Title") %></a>
                  </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField>
                  <HeaderTemplate>Tags</HeaderTemplate>
                  <ItemTemplate>
                    <asp:Repeater ID="TagRepeater"
                                  DataSource='<%#Eval("Tags") %>'
                                  runat="server">
                      <ItemTemplate>
                        <%#Container.DataItem %>
                      </ItemTemplate>
                      <SeparatorTemplate>,</SeparatorTemplate>
                    </asp:Repeater>
                  </ItemTemplate>
                </asp:TemplateField>
              </Columns>
</asp:GridView>

Putting It Together

First we handled the processing when the user clicked on the Open button. Then we built a display to contain all the data. Now, we need tell our grid view control what data it will be displaying. This process is the same as it was with the drop-down list box control:

FeedDetailsGrid.DataSource = feeds;
FeedDetailsGrid.DataBind();

Now, when we click on the Open button, we get a nicely formatted grid with the list of blog entries from the selected feed:

Conclusion

As you’ve seen through these two posts, with just a little bit of code and a few screen controls, you can create a simple RSS reader. ASP.NET gives you a simple framework to leverage the .NET Framework to create a feature-rich website.

Creating an RSS Reader Using ASP.NET and LINQ – Part 1

With every release of the .NET Framework, more power has been placed in the developer’s hands.  We can now concentrate on the overall process of our applications rather than developing the low-level functionality.  In this post, I’ll start creating a simple RSS reader using ASP.NET and LINQ.

Feed Definitions

The first step is to decide how to define the RSS feed information and how our program will use it.  The basic information we’re going to need will be:

  • The name of the feed.
  • The URL of the feed.

For ease of maintenance, and to allow updating the list without having to edit our source code, we’ll store the feed definitions in an external file.  There are many options for this and we’ll use the easiest option: XML.  Our file will have a basic format, only storing the basic information that we need:

<!--?xml version="1.0" encoding="utf-8" ?-->
<Feeds>
  <Feed>
    <Name>Stuck In Customs</Name>
    <Url>http://www.stuckincustoms.com/feed/</Url>
  </Feed>
  <Feed>
    <Name>2000 Things You Should Know About C#</Name>
    <Url>http://csharp.2000things.com/feed/</Url>
  </Feed>
  <Feed>
    <Name>There, I Fixed It!</Name>
    <Url>http://feeds.feedburner.com/ThereIFixedIt</Url>
  </Feed>
</Feeds>

We’ll store this information in a basic class:

public class FeedDefinition
{
   public string Name { get; set; }
   public string Url { get; set; }
}

 

Loading the Feed Definitions

Now that we have our feed definitions stored in an external file and a class defined to store the information, we need to load that data into our application. Before we had the .NET Framework, we would have to read in the file and create our own XML parser in order to load the data. This process has become easier with each version of the .NET Framework.

By utilizing LINQ, the process of obtaining the data from an XML file has become quite easy:

XDocument feedDefinitions = XDocument.Load(Server.MapPath("Feeds.xml"));
var feeds = from feed in feedDefinitions.Descendants("Feed")
select new FeedDefinition()
{
  Name = (string)feed.Element("Name"),
  Url = (string)feed.Element("Url"),
};

Using just one line of code (line 1), the entire feed definition file is loaded and parsed for you. The contents are stored in an XDocument object.  Processing this object using LINQ (lines 3-8), we obtain a collection of FeedDefinition objects (IEnumerable<FeedDefinition>) that we will use in our web page.

Building The Display

Now that we have our data, we need to be able to display it to the user. We will use a drop-down list control that will allow the user to select a feed for reading. In our ASP.NET content page, we’ll define the our display as this:

<div class="feedList">
Feed:
<asp:DropDownList ID="FeedList"
                  DataValueField="Url"
                  DataTextField="Name"
                  runat="server" />
<asp:Button ID="OpenButton"
            Text="Open"
            runat="server" />
</div>

The drop-down list box will be bound to our feed data that we read in earlier. However, we have two fields in our data. Using the DropDownList control, we can display the Name property to the user and use the Url property for processing later on.

Putting It Together

Now that we have our feed definitions and our display, we just need to put them both together:

FeedList.DataSource = feeds;

FeedList.DataBind();

This code binds our feed definition collection to the drop-down list control. All we need to do now is put our code into our content page’s Page_Init method so that it’ll populate our control the first time our page is loaded.

protected void Page_Init()
{
XDocument feedDefinitions = XDocument.Load(Server.MapPath("Feeds.xml"));
var feeds = from feed in feedDefinitions.Descendants("Feed")
select new FeedDefinition()
{
   Name = (string)feed.Element("Name"),
   Url = (string)feed.Element("Url"),
};
FeedList.DataSource = feeds;
FeedList.DataBind();
}

It’s important that you load the feed definitions in Page_Init() rather than in Page_Load().  Putting them in Page_Init() will prevent the drop-down list control from getting reinitialized during postback when we implement our Open button in Part 2.

When we load our website, we get our list of feeds neatly displayed in our control:

Conclusion

In this post, we wrote the first half of our simple RSS reader web application. By using the .NET Framework and the LINQ feature, we were able to load a list of RSS feeds into our web page without writing a lot of code.

In part 2, we’ll show how to get a list of posts from the feed and display them along with other data related to the posts.

Why I Hate Computers: Reason 283

Those that know me hear me say often that “I hate computers.”  The first time someone hears me say that, their comment is usually “But, you make your living with computers!”  I have to politely tell that it doesn’t mean I have to like them.

I was recently working on an issue discovered by our QA tester.  We have a feature that allows access to dBase database files.  As most programs that provide this access, we utilize the Microsoft Jet Database Engine to perform the heavy lifting.  (I know, Jet is on it’s way out, but for now it still works.)

During my development, I tested this feature many times without any problems.  Now, our QA tester opens a problem ticket stating that he cannot see any of the database’s columns.  I attempt to duplicate it but cannot on my development machine, so I turn to one of my test machines.

Using a few different machines, I find that the issue is not the test file or the version of the operating system.  What is strange is that I can get it to work on one machine but cannot on another with the same operating system.  What’s worse, is that the error is not throwing an exception so my utility is not displaying anything to the user.

I do manage to finally get the application to throw an exception.  What’s strange is that the exception message is “Microsoft jet database engine could not find object ‘xyz.dbf'”.  SAY WHAT???  Not possible, the file is RIGHT THERE!!

Next I turn to my favorite tool, the web search.  A bit of searching turned up the following interesting text:

3011 – Microsoft jet database engine could not find object ‘xyz.dbf’…  Notice the dbf file extension.  A dbf file name needs to be in 8.3 DOS name format.   It is quite possible that some machines can open the file with a longer file name and others it must be in 8.3 DOS name format.

Now, isn’t that interesting?  Long file names have been in existence since Windows 95, but yet the jet database engine doesn’t support them after almost 15 years!  

By renaming the file to a DOS 8.3 format name resulted in a successful test on all systems.  (Yes, the internal “short” name, the one with the ‘~’, also worked.)  What is interesting is that one machine worked just fine with the long file name, but the rest didn’t.  If anyone has any input in to why long names work on some systems and not others, I’d appreciate the input.

Implementing Automatic Build Versions using PowerShell and Subversion

Recently I was tasked with implementing an automatic build and versioning system for our .NET development project. As part of that process, I needed to come up with a versioning mechanism to place into the process.

Background

The system had to be automatic so that any member of the team could implement it as part of a regular build cycle. Other projects within the company integrate with this project, so distribution builds are a weekly occurrence.

The build environment has been kept simple: Visual Studio 2008 and Subversion. Integration between the two was accomplished by using the ankhsvn Visual Studio plugin. To enable Subversion maintenance from outside of Visual Studio, the TortoiseSVN Explorer shell extension is used.

Build Versions

Due to the numerous builds that occur, it is necessary to integrate a build number into the application version information. The AssemblyVersion and AssemblyFileVersion attributes allow for a four level versioning system. Having four levels would allow us to simply add the build number to the end of our existing standard three-level version system (Major.Minor.ServicePack).

The only issue was how to come up with a build number that would be meaningful. Visual Studio has an option to replace the third and fourth levels with values that are hacks of the date and time of the build. However, this option resulted in the removal of the Service Pack number from our version number, which was not acceptable.

Back in Visual Basic 6, there was a build option that auto-incremented the last value in the version each time the output was built. That feature was not available in the C/C++ versions of Visual Studio and was not brought forward to the .NET versions. Although an auto-incrementing value allows for determining which build is newer, it provides for not much else.

The Plan

During my research, I came across a blog post where the author was utilizing the latest subversion revision as the build number. This allowed for a build to be directly connected to point in the subversion repository. However, this author’s instructions were utilizing MSBuild, which we were not.

The plan was to implement the following versioning scheme: Major.Minor.ServicePack.Build. The major, minor and service pack values would be specified manually and the build value would be generated automatically as part of the build process.

The Tools

Coming up with the versioning scheme was only half of the work.  The other half, and arguably the hardest half, was to come up with the actual implementation. The challenge was to determmine what tools would be needed to accomplish the task. The tools would have to be lightweight and easy to use.

I decided to utilize Windows PowerShell to accomplish the task. Not only could it be used for automating the build process, but it could also be used to perform automated tests on our .NET classes. PowerShell utilizes the .NET framework classes, so any task that we can accomplish in a .NET application could be accomplished in a PowerShell script.

To allow access to the Subversion repository, a command-line SVN client would be needed. I chose the SlikSVN client available from the Subversion client page. It comes with a Microsoft MSI installation package and was easily distributed to other team members.

The Setup

Before diving into the PowerShell script, some work had to be done to make the job easier and more efficient. Each project has its own AssemblyInfo.cs file. Since our procedure would only update the build number, this would mean that each AssemblyInfo.cs file would have to be updated with the major, minor and service pack numbers. As the number of projects grows, this task becomes more prone to error.

To solve this issue, the AssemblyInfo.cs file would be split into two files. The first file, AssemblyVersionInfo.cs, would contain the company, product, copyright and version information. The second, AssemblyInfo.cs, would contain the remaining attributes. AssemblyVersionInfo.cs would be a single file that would be shared by all projects, whereas AssemblyInfo.cs would be located in each project’s directory.

By placing all version information into a single file, this reduces the modifications needed by the development team when a version changes. It also allows the PowerShell script to simply modify a single file rather than having to search through each project directory.

Getting the Latest Revision Number

The first step in the process is to obtain the value of the latest Subversion revision. Alejandro Espinoza wrote a little PowerShell script that accomplished this task. With a bit of simplification for my use, here’s the result:

function GetLatestRevisionNumber()
{
$revLinePattern = "(.*?)(Revision: )(\d+\.?\d*)(.*?)";
$result = svn info .
$revision = 0;
if([regex]::Match($result, $revLinePattern)) {
$matches = [regex]::Split($result,$revLinePattern);
$revision = $matches[3];
}
return [int]$revision;
}

This PowerShell function calls ‘svn info’ to get the Subversion repository information for the current directory. Then it locates the line with ‘Revision’, pulls out the value and returns it to the caller.

Updating AssemblyVersionInfo.cs

Now that the latest revision value is obtained, we need to take that value and update the AssemblyVersionInfo.cs file. However, there are two issues that need to be addressed when doing so:

  1. If the build number in AssemblyVersionInfo.cs is the same, the file should not be updated.
  2. After the AssemblyVersionInfo.cs is updated, the new copy will be loaded back into the Subversion respository at the next revision level.

To address issue #1, the script will need to compare the updated value with the value that exists in the file. The file will only be updated if the value has changed.

To address issue #2, the revision level obtained above will be incremented before writing it to the file. Otherwise, the file will be updated each time the script is run. By incrementing the value, the value written to the file will match the level when the file is copied back into the respository after the update.

The PowerShell script to perform the update is quite simple:


function UpdateAssemblyVersion()
{
$currRevision = GetLatestRevisionNumber;
$nextRevision = [int]$currRevision + 1;
$versionPattern = '(?\d+)\.(?\d+)\.(?\d+)\.\d+';
$hasChanged = 0;
$assemblyFileData = Get-Content Common\AssemblyVersionInfo.cs;
for($line=0; $line -lt $assemblyFileData.Length; $line++)
{
$newLine = [regex]::Replace($assemblyFileData[$line], $versionPattern,
"`${major}.`${minor}.`${sp}." + $currRevision);
if($newLine.CompareTo($assemblyFileData[$line]) -ne 0)
{
$hasChanged = 1;
$newLine = [regex]::Replace($assemblyFileData[$line], $versionPattern,
"`${major}.`${minor}.`${sp}." + $nextRevision);
$currRevision = $nextRevision;
$assemblyFileData[$line] = $newLine;
}
}
if($hasChanged -eq 1)
{
write-host "Updating AssemblyVersionInfo.cs to version " $nextRevision ".";
Set-Content Common\AssemblyVersionInfo.cs $assemblyFileData;
svn commit Common -m `"Version change for build.`"
}
}

Conclusion

These PowerShell functions are simply two steps in the entire build automation process. When placed between a Subversion update and a Visual Studio compile, they provide an automated method for integrating meaningful build numbers into your .NET assemblies.