70-562 - WCF and Syndication Feed

Filed under: , , , , , by:

When I was studying for my 70-503 exam (MCTS WCF 3.5), I only used 2 books plus MSDN of course. Those books were: Programming WCF Services and Learning WCF: A Hands-on Guide. They are great books and a great resource when preparing to either 70-503 exam or 70-562. However, when I was watching some webcasts and reading MSDN, I found out that there were a few important WCF concepts that they did't mention, and one of them was Syndication Feed. Therefore, this post will demonstrate that creating syndication feed in .NET doesn't have to cumbersome if one knows how to use WCF.
Visual Studio 2008 has a template "Syndication Service Library" in WCF project type.


Once opened, it creates a solution with service contract (IFeed1), service class (Feed1) with defined web methods  (operation contracts) and configuration.

Even though there is no ServiceHost, the project can be run  as it will be hosted by WcfSvcHost. Of course for production purpose a hosting application will have to be created, which most of the time will be a WCF Service Application. Below is an example of WCF service that uses Syndication Library to create a web site  with RSS feeds that show tiles of movies along with director name and release date, which information is retrieved from XML file "movie.xml" (which has been added to Resources.rex file).
Project: WcfSyndication
File: IMovieFeed.cs

namespace MovieLibrary
{
[ServiceContract(Namespace="MoviesFeed.org")]
[ServiceKnownType(typeof(Atom10FeedFormatter))]
[ServiceKnownType(typeof(Rss20FeedFormatter))]
public interface IMovieFeed
{
[OperationContract]
[WebGet(UriTemplate = "*", BodyStyle = WebMessageBodyStyle.Bare)]
SyndicationFeedFormatter CreateFeed();
 }
}
File: MovieFeed.cs
namespace MovieLibrary
{
public class MovieFeed : IMovieFeed
{
public SyndicationFeedFormatter CreateFeed()
{
SyndicationFeed feed = new SyndicationFeed("Movie Feed", "A WCF Syndication Feed with Movies", null);
var items = from element in XDocument.Parse(Resource.movies).Root.Descendants("Movie")
select new SyndicationItem(
element.Element("Title").Value,
"Director: " + element.Element("Director").Value + 
" Realse date: " + element.Element("ReleaseDate").Value,
null);
feed.Items = items;
string query = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.QueryParameters["format"];
SyndicationFeedFormatter formatter = null;
if (query == "atom")
{
formatter = new Atom10FeedFormatter(feed);
}
else
{
formatter = new Rss20FeedFormatter(feed);
}
 
return formatter;
}
}
}
File: movie.xml (part of file for brevity)
<?xml version="1.0" encoding="utf-8" ?>
<Movies>
<Movie>
<Title>Shrek</Title>
<Director>Andrew Adamson</Director>
<Genre>0</Genre>
<ReleaseDate>5/16/2001</ReleaseDate>
<RunTime>89</RunTime>
</Movie>
<Movie>
<Title>Fletch</Title>
<Director>Michael Ritchie</Director>
<Genre>0</Genre>
<ReleaseDate>5/31/1985</ReleaseDate>
<RunTime>96</RunTime>
</Movie>
</Movies>
Project: WcfServiceHost
File: Service.svc
<%@ ServiceHost Language="C#" Service="MovieLibrary.MovieFeed" %>
File: web.config (for brevity only servicemodel configuration)
<system.serviceModel>
<bindings />
<services>
<service name="MovieLibrary.MovieFeed" behaviorConfiguration="ServiceBehavior">
<endpoint address="" behaviorConfiguration="SyndicationLibrary.MovieFeedBehavior"
binding="webHttpBinding" contract="MovieLibrary.IMovieFeed" />
<endpoint address="mex" contract="IMetadataExchange" binding="mexHttpBinding"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:2500/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="SyndicationLibrary.MovieFeedBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
And here is the result of our service that creates syndication feeds.

Here are a few important and hopefully interesting aspects of this project, which I couldn't find in the aforementioned books.
  • returned feed is of type SyndicationFeedFormatter (base class for Rss20FeedFormatter and AtomFeedFormatter) rather than XML
  • operation contract method of the service has WebGet attribute which means that a method can be called by Web programming model - Http Get verb and response will be XML and JSON rather than SOAP - this model is also called REST or RESTful and service is called a REST service
  • in order to work a WebGet attribute requires WebHttpBehavior ( in this example by adding <webHttp/> to EndpointBehaviors in a config file) and WebHtppBinding
  • Operation method is using WebGet attribute that specifies UriTemplate, which defines how a REST service can be called from a Web Browser - in our example any path, where regular WCF service would return information of missing endpoint for address other than specified by endpoints
  • If we specify the given query "?format=atom" in path, a response will be in Atom format, where without the specified format it is RSS
  • Self-hosting this service would require WebServiceHost and/or WebServiceHostFactory classes
  • Accessing REST service on clients would require WebChannelFactory<IMovieFeed>
I hope this simple example demonstrated how simple it is to create a WCF RESTful service providing syndication feeds. I hope it showed what classes are required to self-host it and consume on a client. I don't know why but it seems this concept is still fairly uncommon and not many books on WCF give a good and thorough explanation of WCF REST services. In next post I'll show how to make ASP.NET, Ajax, Java Script and WCF RESTful services work together to create POWERful ASP.NET 3.5 applications.

    0 comments: