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.
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();
}
}
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;
}
}
}
<?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>
File: Service.svc
<%@ ServiceHost Language="C#" Service="MovieLibrary.MovieFeed" %>
<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>
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>
0 comments: