Aaronontheweb

Hacking .NET and Startups

Quick and Dirty Feed Parser 1.0 Released!

January 19, 2011 19:42 by Aaronontheweb in QDFeedParser // Tags: , , // Comments (4)

Without further adieu, it’s my pleasure to announce that the full 1.0 release of Quick and Dirty Feed Parser is now available to download on Codeplex.

Here are the main reasons why you should care about Quick and Dirty Feed Parser 1.01:

  1. Works on Windows Phone 7 and Silverlight 4;
  2. All IFeed objects now consume substantially less memory on average;
  3. All IFeed objects are now serializable;
  4. All IFeedFactory objects now support DI for injecting your own feed parsers; and
  5. Added an IsolatedStorageFeedFactory for working with RSS / Atom feeds in IS for all Silverlight and Windows Phone 7 developers.

Making QD Feed Parser run on Windows Phone 7 took some work – I had to rewrite the entire parsing library using LINQ-to-XML instead of XPath, but it was well worth it. The LINQ parser is now used by default in all IFeedFactory instances, but you can inject your own if you have a better way of parsing RSS or Atom.

I’ve had the pleasure of using Quick and Dirty Feed Parser 1.0 in Geeky Reads and in my new budding project, JSONify, and QD Feed Parser has performed excellently in its response time in both of those services thus far.

I’m also building a line of Windows Phone 7 applications on top of Quick and Dirty Feed Parser 1.0, and it’s made life rather easy for me in the scheme of things.

You can read the full release notes for Quick and Dirty Feed Parser 1.01 on CodePlex, and by all means please feel free to leave me feedback here if you’ve had a chance to try the project yourself.

Contributors Wanted!

We’re actively looking for contributors who want to help make Quick and Dirty Feed Parser even better. If you’re interested, feel free to ping me via CodePlex or leave a comment below!

Update: Quick and Dirty Feed Parser Added to NuGet

Quick and Dirty Feed Parser is now available on NuGet! http://nuget.codeplex.com/

If you enjoyed this post, make sure you subscribe to my RSS feed!



How to Make Any Operation Asynchronous in .NET

I’m in the middle of writing some updates to Quick and Dirty Feed Parser for use in a new personal project of mine; namely, I need to make QD Feed Parser work asynchronously so I can use it in conjunction with asynchronous controllers in ASP.NET MVC3, and eventually Silverlight + Windows Phone 7.

Asynchronous network IO is a breeze in every version of .NET since 1.1 – WebRequest and many others have supported asynchronous methods for as long as I’ve been using them. However, asynchronous disk IO, which I need to support in QD Feed Parser, is not something that comes so easily in .NET 4.0 and below.

StreamReader is the most user-friendly tool for reading files off of local disk because you don’t have to manage any buffers or do any of the sort of accounting that a class like FileStream requires1. Here’s how nice and easy life is using StreamReader, using actual code from QD Feed Parser as an example:

protected static FeedTuple DownloadXmlFromUri(Uri feeduri)
{
    string xmlContent;
    using (var reader = new StreamReader(feeduri.LocalPath))
    {
        xmlContent = reader.ReadToEnd();
    }

    return new FeedTuple{FeedContent = xmlContent, FeedUri = feeduri};
}

Given that StreamReader doesn’t have any built-in methods for making this asynchronous, what’s the best way to do this, given that the  async and await keywords coming down the pipe in .NET 5.0 aren’t fully available yet? The answer is: we’re going to wrap our disc IO operations using delegates.

Out of the box delegates have both a BeginInvoke and EndInvoke methods, which behave like any other standard asynchronous method call and you, the developer get to decide what functions are invoked on the background thread.

Here are the steps:

1. Create a delegate and a static worker method

protected delegate FeedTuple BackGroundWorker(Uri feeduri);

protected static FeedTuple DownloadXmlFromUri(Uri feeduri)
{
    string xmlContent;
    using (var reader = new StreamReader(feeduri.LocalPath))
    {
        xmlContent = reader.ReadToEnd();
    }

    return new FeedTuple { FeedContent = xmlContent, FeedUri = feeduri };
}

The delegate and the static worker method need to have the same signatures.

2. Define your own Begin[Operation] and End[Operation] methods

For Quick and Dirty Feed Parser, here is what I created, minus some integrity checks in order to make the code more readable:

public override IAsyncResult BeginDownloadXml(Uri feeduri, AsyncCallback callback)
{
    return FeedWorkerDelegate.BeginInvoke(feeduri, callback, 
		new FeedTuple());

}

public override FeedTuple EndDownloadXml(IAsyncResult asyncResult)
{
    var result = FeedWorkerDelegate.EndInvoke(asyncResult);
    return result;
}

Your begin method should return the IAsyncResult from your delegate – this way your caller can pass the asynchronous result back to the End[Operation] method and return your result. You can also use the IAsyncResult’s WaitHandle to put a block a calling thread if you wanted.

When dealing with delegates you have to be careful with your accounting – for every BeginInvoke there should be exactly one EndInvoke.

3. Calling the asynchronous methods

Here’s a quick unit test I wrote for testing this method in Quick and Dirty Feed Parser.

[Test, TestCaseSource("TestCases")]
public void CanDownloadXmlStreamAsync(string rsslocation)
{
    var feeduri = new Uri(rsslocation);
    var result = Factory.BeginDownloadXml(feeduri, null);
    var resultantTuple = Factory.EndDownloadXml(result);

    Assert.IsNotNull(resultantTuple);
    Assert.That(resultantTuple.FeedContent != String.Empty);
    Assert.AreEqual(feeduri, resultantTuple.FeedUri);
}

You should note that I’m effectively blocking the calling thread until the asynchronous worker thread returns a result in this method, and that’s because it’s easier to write unit tests this way.

The best practice for taking advantage of asynchronous method calls is to utilize a callback function, which you can do like so:

public void DownloadXmlStreamAsync(string rsslocation)
{
    var feeduri = new Uri(rsslocation);
    var result = Factory.BeginDownloadXml(feeduri, async => 
	{
		var callbackTuple = Factory.EndDownloadXml(async);
		Dispatcher.BeginInvoke(() => { 
		//... Do some client-side stuff with the data...		
		});
	});
}

And that’s it!


1It should be noted that FileStream does support asynchronous operations out of the box, but they’re a pain in the ass to use due to the reasons I just described.

If you enjoyed this post, make sure you subscribe to my RSS feed!



Quick and Dirty Feed Parser 0.3 Now Available

December 25, 2010 05:33 by Aaronontheweb in QDFeedParser // Tags: , // Comments (0)

My Christmas gift to the developer community: Quick and Dirty Feed Parser 0.3 is now available on CodePlex!

The big feature added in this release is the ability to perform IFeedFactory.CreateFeed operations asynchronously both for disc IO and network IO. I added this to QD Feed Parser primarily to support the use of asynchronous controllers in ASP.NET MVC3, and to support Silverlight and Windows Phone 7 eventually.

All classes which implement the IFeedFactory interface now have some new members:

IAsyncResult BeginCreateFeed(Uri feeduri, AsyncCallback callback);

IFeed EndCreateFeed(IAsyncResult asyncResult);

IAsyncResult BeginDownloadXml(Uri feeduri, AsyncCallback callback);

FeedTuple EndDownloadXml(IAsyncResult asyncResult);

If you’re at all familiar with the Begin[Procedure] End[Procedure] asynchronous programming pattern in .NET, then the purpose of these functions should be self-evident. Internally, BeginCreateFeed and EndCreateFeed are dependent upon the output of BeginDownloadXml and EndDownloadXml, but should a developer want to be able to work strictly with just the XML content itself then that’s why the [Begin/End]DownloadXml methods are publicly exposed.

Here’s a quick example which shows how you can use these functions to quickly and asynchronously parse RSS and Atom feeds:

Uri feeduri;
IFeedFactory factory;
if (UseFileSys)
{
    feeduri = new Uri(Path.GetFullPath(strFeedUri));
    factory = new FileSystemFeedFactory();
}
else
{
    feeduri = new Uri(strFeedUri);
    factory = new HttpFeedFactory();
}

factory.BeginCreateFeed(feeduri, async =>
{
    var feed = factory.EndCreateFeed(async);
    foreach (var feedItem in feed.Items)
    {
        Console.WriteLine("{0} {1}",
			feedItem.DatePublished, feedItem.Title);
        Console.WriteLine(feedItem.Link);
    }
});

If you’d like to play with this example of using Quick and Dirty Feed Parser asynchronously you can download the source from Github or the full release from CodePlex.

Originally I developed Quick and Dirty Feed Parser to support legacy NET 2.0 projects that wanted functionality that you could find using the System.ServiceModel.Syndication namespace. I’m developing it going forward because I think it’s easier to use than the ServiceModel classes and I’m using it on my own projects going forward.

If you’re interested in contributing to the project, we’d love to have you. Check out our issues list or come up with your own feature ideas that aren’t in it yet!

If you enjoyed this post, make sure you subscribe to my RSS feed!



Announcing the Release of Quick and Dirty Feed Parser

June 30, 2010 18:47 by Aaronontheweb in .NET, QDFeedParser // Tags: , , , // Comments (0)

Alternate headline: "never see XML again."

Ok, that may be a bit of a stretch. Regardless, I'm quite pleased to announce the launch of Quick and Dirty Feed Parser, a library for people who want a seamless way to use Atom and RSS feeds in their .NET 2.0+ applications without having to deal with the XML.

"Does the world really need another RSS/Atom parser," you ask? I'll let my source code speak for itself:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using QDFeedParser;

namespace QDFeedParserCMD
{
    class Program
    {
        private static readonly string DefaultFeedUri = "http://www.aaronstannard.com/syndication.axd";

        static void Main(string[] args)
        {
            try
            {
                string strFeedUri = args.Length == 0 ? DefaultFeedUri 
                    : args[0];

                Uri feeduri = new Uri(strFeedUri);
                IFeedFactory factory = new HttpFeedFactory();
                IFeed feed = factory.CreateFeed(feeduri);

                foreach(var feedItem in feed.Items)
                {
                    Console.WriteLine("{0} {1}", feedItem.DatePublished,
                        feedItem.Title);
                    Console.WriteLine(feedItem.Link);
                }
                //Just to prevent the window from instantly bailing out.
                Console.ReadKey(); 
            }
            catch(Exception ex)
            {
                Console.WriteLine("Exception: {0}", ex);
            }

        }
    }
}

That's about as complicated as it gets, folks. And feel free to download this QDFeedParser example from CodePlex

I wrote Quick and Dirty Feed Parser largely because I wanted to incorporate a really straightforward RSS/Atom parsing tool into a number of BlogEngine.NET modifications I have in mind in the near future, and I wanted a standard interface for dealing with RSS/Atom feeds that was available to me in .NET 2.0.

Quick and Dirty Feed Parser is my first OSS project so I would love your feedback, contributions, and most awesomely - examples of it actually being used! Check out the QDFeedParser project on CodePlex if you want to get involved!

QD Feed Parser in Action - The Great Wall of Geeks

No project worth it's salt would be complete without some sort of frivolous example, right? Well that's exactly why I created The Great Wall of Geeks.

Feel like your geeky blog belongs on the wall? Leave a comment below!

If you enjoyed this post, make sure you subscribe to my RSS feed!



Search

About

My name is Aaron, I'm an entrepreneur and a .NET developer who develops web, cloud, and mobile applications.

I left Microsoft recently to start my own company, MarkedUp - we provide analytics for desktop developers, focusing initially on Windows 8 developers.

You can find me on Twitter or on Github!

Recent Comments

Comment RSS

Sign in