Let’s jump right in to the code. I’m going to use a blog example because it’s obviously a natural fit for atom, but you can use it to publish anything you want. Let’s say we have a Post class:

1:using System;

2:

3:namespace Suteki.Blog.Model

4: {

5:publicclass Post : ModelBase

6: {

7:publicstring Title { get; set; }

8:publicstring Text { get; set; }

9:public DateTime CreatedDate { get; set; }

10:

11:publicoverridestring ToString()

12: {

13:returnstring.Format("Post Id: {0} Title: '{1}'", Id, Title);

14: }

15: }

16: }

That’s pretty much what you’d expect. Now say we have an IBlogService that allows us to add and retrieve Posts:

1:using Suteki.Blog.Model;

2:

3:namespace Suteki.Blog.Service

4: {

5:publicinterface IBlogService

6: {

7: Post[] GetPosts();

8: Post GetPost(string id);

9:void AddPost(Post post);

10: }

11: }

Now let’s create a service contract for our atom feed:

1:using System.ServiceModel;

2:using System.ServiceModel.Syndication;

3:using System.ServiceModel.Web;

4:

5:namespace Suteki.Blog.RestService.Atom

6: {

7: [ServiceContract]

8:publicinterface IAtomFeed

9: {

10: [OperationContract]

11: [WebGet(UriTemplate = "/")]

12: Atom10FeedFormatter GetPosts();

13: }

14: }

The WebGet attribute was introduced with WCF 3.5 to make it easy to create RESTful web services and uses a URI templating scheme to route URLs to service methods. Here we are routing the root URL to our GetPosts method. Note that the GetPosts method returns Atom10FeedFormatter. This class knows how to format your items as an atom feed.

So far this is all straight from WCF, we haven’t brought the WCF Facility to the party yet. To tell the WCF Facility to supply the service instance, we need to create a specific AtomFeed.svc file. My one looks like this

We tell WCF to use the WCF Facility’s host factory with its RestServiceModel. The bizarre square bracket syntax is simply the CLR notation for generics. The service is specified as ‘atomFeed’, this tells the WCF Facility to resolve the component named ‘atomFeed’ from the Windsor container.

Note that it has dependencies on both the IBlogService, that we saw above, and IPostAtomFeedMapper. IPostAtomFeedMapper is responsible for mapping the array of Post instances returned from IBlogService to a SyndicationFeed instance. SyndicationFeed is another WCF type to support feeds and is consumed by the Atom10FeedFormatter. Here is the IPostAtomFeedMapper implementation:

1:using System.Collections.Generic;

2:using System.ServiceModel.Syndication;

3:using Suteki.Blog.Model;

4:

5:namespace Suteki.Blog.RestService.Atom

6: {

7:publicclass DefaultPostAtomFeedMapper : IPostAtomFeedMapper

8: {

9:public SyndicationFeed Map(Post[] posts)

10: {

11: var items = new List<SyndicationItem>();

12:

13:foreach (var post in posts)

14: {

15: var item = new SyndicationItem

16: {

17: Id = post.Id.ToString(),

18: Title = new TextSyndicationContent(post.Title),

19: Content = new TextSyndicationContent(post.Text),

20: PublishDate = post.CreatedDate

21: };

22: items.Add(item);

23: }

24:

25:returnnew SyndicationFeed(items);

26: }

27: }

28: }

And it’s as simple as that. No need for any Web.config configuration. When I run the service and browse to its URL with Firefox I see the familiar atom feed page:

No comments:

Code Rant

Notepad, thoughts out loud, learning in public, misunderstandings, mistakes. undiluted opinions. I'm Mike Hadlow, an itinerant developer. I live (and try to work in) Brighton on the south coast of England.

All code is published under an MIT licence. You are free to take it and use it for any purpose without attribution. There is no warranty whatsoever.