Page 1 of 1

Creating your own RSS Reader in C#

#1 PsychoCoder  Icon User is offline

  • Google.Sucks.Init(true);
  • member icon

Reputation: 1639
  • View blog
  • Posts: 19,853
  • Joined: 26-July 07

Post icon  Posted 05 October 2007 - 08:57 PM

Welcome to my tutorial on Creating your own RSS Reader in C#. This tutorial takes into consideration that you have a firm understanding of:

  • XML Namespace
  • Custom Classes


In this tutorial we will create 2 custom classes: RssManager.cs and Rss.cs. RssManager will have all the logic and functionality for retrieving the feed from the provided URL, parsing the XML in the feed, then populating a Structure created in Rss.css) to be returned to the main form to display the feed data.

RssManager.cs is a Serializable class. Serialization is storing the state of an object to a storage medium. In other words, you are converting your object from its normal state, into a form that can easily be stored, either to a disk file (hard drive) or into memory (MemoryStream), or the most common form is storing it as XML for retrieval later.

First we need to bring in our Namespaces we'll need for this class:


using System;
using System.Xml;
using System.Collections.ObjectModel;
using PC; //This is here as in my files my Namespace is PC




RssManager.cs Implements the IDisposable Interface so the signature for your class should look like:


public class RssManager : IDisposable
{
	 //we'll put our code in here
}




Now lets build our class. First we have 5 Global variables that will hold the values of our class Properties, here are the variables you need:


private string _url;
private string _feedTitle;
private string _feedDescription;
private Collection<Rss.Items> _rssItems = new Collection<Rss.Items>();
private bool _IsDisposed;




Now that we have these declared, lets move onto our Constructors. A Constructor is what allows you to instantiate a class. Your constructor can be empty, or you can initialize variables in your constructor. Our class will have 2 constructors, one sets out _url variable to an empty string,and one initializing the _url variable:


#region Constructors
/// <summary>
/// Empty constructor, allowing us to
/// instantiate our class and set our
/// _url variable to an empty string
/// </summary>
public RssManager()
{
	_url = string.Empty;
}

/// <summary>
/// Constructor allowing us to instantiate our class
/// and set the _url variable to a value
/// </summary>
/// <param name="feedUrl">The URL of the Rss feed</param>
public RssManager(string feedUrl)
{
	_url = feedUrl;
}

  #endregion




Now our constructors are out of the way, now we need to declare some public properties, that can be accessed by our form that's displaying the Rss information. We have 4 properties:

  • URL
  • FeedTitle
  • FeedDescription
  • RssItems
    • This property is actually a Collection, populated by the Structure in Rss.cs


Now for the code of our properties:


#region Properties  

  /// <summary>
  /// Gets or sets the URL of the RSS feed to parse.
  /// </summary>
  public string Url
  {
	get { return _url; }
	set { _url = value; }
  }

  
  /// <summary>
  /// Gets all the items in the RSS feed.
  /// </summary>
  public Collection<Rss.Items> RssItems
  {
	get { return _rssItems; }
  }
	  
  /// <summary>
  /// Gets the title of the RSS feed.
  /// </summary>
  public string FeedTitle
  {
	get { return _feedTitle; }
  }
	  
  /// <summary>
  /// Gets the description of the RSS feed.
  /// </summary>
  public string FeedDescription
  {
	get { return _feedDescription; }
  }

  #endregion




As you can see, both properties have a get and a set, meaning they are set in our form. Now we get into the "meat" of the RssManager Class. We will now take a look at the methods that retrieve the Rss feed, and that parse the XML from the feed. First we will look at the GetFeed() Method. This method returns a Collection of type Rss.Items, which, once again, is the structure created in the Rss.cs Class. In this class we will use:


/// <summary>
/// Retrieves the remote RSS feed and parses it.
/// </summary>
public Collection<Rss.Items> GetFeed()
{
  //check to see if the FeedURL is empty
	if (String.IsNullOrEmpty(Url))
	{
		//throw an exception if not provided
		throw new ArgumentException("You must provide a feed URL");
	}
		//start the parsing process
	using (XmlReader reader = XmlReader.Create(Url))
	{
		 XmlDocument xmlDoc = new XmlDocument();
		 xmlDoc.Load(reader);
		 //parse the items of the feed
		 ParseDocElements(xmlDoc.SelectSingleNode("//channel"), "title", ref _feedTitle);
		 ParseDocElements(xmlDoc.SelectSingleNode("//channel"), "description", ref _feedDescription);
		 ParseRssItems(xmlDoc);
		 //return the feed items
		 return _rssItems;
	}
}




You will notice that in this method we call 2 other methods:

  • ParseDocumentElements: Used to parse the elements of the XML document returned from the feed
  • ParseRssItems: Used to parse the XmlNode that contains the items of the feed


First lets take a look at the ParseDocElements Method. Here we create a new Rss.Items Collection Object, then parse the returned XML, populating the items of the collection:


/// <summary>
/// Parses the xml document in order to retrieve the RSS items.
/// </summary>
private void ParseRssItems(XmlDocument xmlDoc)
{
	_rssItems.Clear();
	XmlNodeList nodes = xmlDoc.SelectNodes("rss/channel/item");

	foreach (XmlNode node in nodes)
	{
	  Rss.Items item = new Rss.Items();
	  ParseDocElements(node, "title", ref item.Title);
	  ParseDocElements(node, "description", ref item.Description);
	  ParseDocElements(node, "link", ref item.Link);

	  string date = null;
	  ParseDocElements(node, "pubDate", ref date);
	  DateTime.TryParse(date, out item.Date);

	  _rssItems.Add(item);
	}
}




This method also calls the ParseDocElements, so now lets take a look at that method. Here we inspect each XmlNode to see if it contains a property of the RSS feed:


/// <summary>
/// Parses the XmlNode with the specified XPath query 
/// and assigns the value to the property parameter.
/// </summary>
private void ParseDocElements(XmlNode parent, string xPath, ref string property)
{
	XmlNode node = parent.SelectSingleNode(xPath);
	if (node != null)
	  property = node.InnerText;
	else
	  property = "Unresolvable";
}




Finally we'll take a look at the 2 Dispose Methods. One is a provate, the other is the public one. Here is the code for each:


#region IDisposable Members  

  /// <summary>
  /// Performs the disposal.
  /// </summary>
  private void Dispose(bool disposing)
  {
	if (disposing && !_IsDisposed)
	{
	  _rssItems.Clear();
	  _url = null;
	  _feedTitle = null;
	  _feedDescription = null;
	}

	_IsDisposed = true;
  }

  /// <summary>
  /// Releases the object to the garbage collector
  /// </summary>
  public void Dispose()
  {
	Dispose(true);
	GC.SuppressFinalize(this);
  }

  #endregion




That is the end of the RssManager.cs Class. As you can see it contains all the methods and properties we need for our Rss Reader. In this class we referred to Rss.Items on several occasions. This class is a structure created to hold the items of the Rss Feed

  • Date
  • Title
  • Description
  • Link


Since this is a small class, I'll show all the code in the class at once (since it is just a structure).


using System;
using System.Collections.Generic;
using System.Text;

namespace PC
{
	public class Rss
	{
		/// <summary>
		/// A structure to hold the RSS Feed items
		/// </summary>
		[Serializable]
		public struct Items
		{
			/// <summary>
			/// The publishing date.
			/// </summary>
			public DateTime Date;

			/// <summary>
			/// The title of the feed
			/// </summary>
			public string Title;

			/// <summary>
			/// A description of the content (or the feed itself)
			/// </summary>
			public string Description;

			/// <summary>
			/// The link to the feed
			/// </summary>
			public string Link;
		}
	}
}




Now for the interface of our reader. Below is a screen shot of my user interface, you can design your any way you like. Mine has the following controls:

  • TextBox (For entering the feed url)
  • ListBox (For displaying the feed items)
  • Multiline TextBox (For displaying the description of each item as its clicked on)
  • 3 GroupBoxes (Used for separating the different UI elements
  • Menu Strip


Attached Image


The code in my form may differ from yours, unless you follow my design to a tee. First I have my Global Variables, these are referred to throughout the form so I made them Global:


//create our FeedManager & FeedList items
RssManager reader = new RssManager();
Collection<Rss.Items> list;
ListViewItem row;




As you can see, I also create a Collection<Rss.Items> here as well, thats because my manager class will populate one here for displaying the items from the feed. The first method we'll look at if for the button's Click Event:


private void cmdGet_Click(object sender, EventArgs e)
{
	try
	{
		//execute the GetRssFeeds method in out
		//FeedManager class to retrieve the feeds
		//for the specified URL
		reader.Url = txtURL.Text;
		reader.GetFeed();
		list = reader.RssItems;
		//list = reader
		//now populate out ListBox
		//loop through the count of feed items returned
		for(int i = 0; i < list.Count;i++)
		{
			//add the title, link and public date
			//of each feed item to the ListBox
			row = new ListViewItem();
			row.Text = list[i].Title;
			row.SubItems.Add(list[i].Link);
			row.SubItems.Add(list[i].Date.ToShortDateString());
			lstNews.Items.Add(row);
		}	
	}
	catch (Exception ex)
	{
		MessageBox.Show(ex.ToString());
	}		   
}




Here, I set the Url Property of the RssManager Object to the text in the TextBox. I then call the GetFeed() method of the same object to populate my Collection object with the feed information for the specified feed. From there I loop through every item in the collection, adding them to my ListBox. Next is the ListBox's SelectedIndexChanged Event. In here we loop through all the items in the collection we populated in the buttons click event, looking for a title match for the selected ListBox item, when we find it we display the first 250 characters of the Description property of the feed:


private void lstNews_SelectedIndexChanged(object sender, EventArgs e)
{
	//check to make sure an item is selected
	if (lstNews.SelectedItems.Count == 1)
	{
		// Loop through all the items in the list
		for (int i = 0; i < list.Count; i++)
		{
			//check and see if the selected title
			//in the ListBox matches the current 
			//of the list
			if (list[i].Title == lstNews.SelectedItems[0].Text)
			{
				//set the description to the TextBox.Text
				txtContent.Text = list[i].Description.Substring(0,250);
			}
		}
	}
}



Next we will look at the DoubleClick Event of the ListBox, here we start your default web browser, and navigate to the selected feed item:


private void lstNews_DoubleClick(object sender, EventArgs e)
{
	// When double clicked open the web page
	System.Diagnostics.Process.Start(lstNews.SelectedItems[0].SubItems[1].Text);
}




That is it, that's how you create your own custom RSS Reader. I will be including the 2 class files used when creating my reader. Both class files are under the GNU General Public License, which means you can use, modify, distribute as you see fit, but you must keep the license header in tact. Thank you for reading, and I hope you found this tutorial informative and interesting.

Happy Coding :)

Attached File  PC_RSSReader.zip (13.89K)
Number of downloads: 7703

Is This A Good Question/Topic? 3
  • +

Replies To: Creating your own RSS Reader in C#

#2 Guest_Rick*


Reputation:

Posted 28 June 2010 - 04:29 AM

Hi, how do I open the file in the zip file? Whats the file type? /Rick
Was This Post Helpful? 0

#3 Guest_Mark*


Reputation:

Posted 15 July 2010 - 05:20 PM

If you are using windows, right click on the .zip folder, and select "Extract All..." (The 4th or 5th from the drop down menu), click "Next" twice, then click "Finish". A folder should appear with the same name as the .zip folder in the same location. (I.E. the .zip folder "PC_RSSReader.zip" would unzip into a folder named "PC_RSSReader")

For Macs, I'm pretty sure that all you have to do is double click on the archive and it will decompress.

As for Linux, I don't know, it probably varies with your version.

Hope I helped.
Was This Post Helpful? 0

Page 1 of 1