I’ve been wanting to implement a POST protocol for my blog for a while. The urge got really bad since I’ve started using LiveWriter at my day job. It’s such a nice piece of software compared to blogging with the online HTML editor with it’s, often too smart, HTML cleanup, struggling with embedded pictures and loosing drafts. I even considered abandoning my own creation and using WordPress or some other blogging engine. Then the “not invented here” syndrome took over. I spent a few hours implementing a large part of AtomPUB, RFC-5023.
The Atom Publishing Protocol is an application-level protocol for publishing and editing web resources. The protocol is based on HTTP transfer of Atom-formatted representations. The Atom format is documented in the Atom Syndication Format, RFC-4287.
Generating Atom Feeds
My current blog implementation supports ATOM. This is done by using an asp:Repeater to which I bind a data set.
This works fine for generating feeds, but in order to consume ATOM posts I will need an object model for feed items. That’s where the “not invented here” syndrome has to stop and I am going to let Argotic do the job. First, by rewriting the above ASP.NET code in C#.
A client that creates posts must be able to find out where to POST to. This is done by creating a service document and pointing the default blog page to it. Interestingly LiveWriter is a little thick with relative URLs, the href below is actually replaced by full URI in code.
The service document describes a workspace with collections. We have two: one for posts and another for images. The one for posts includes post categories.
We now have Default.aspx that points to the service document, which points to AtomPost.aspx that can generate a feed. The rest doesn’t exist yet, but this is enough to make LiveWriter happy and allow it to register the blog. LiveWriter will automatically detect the Posts collection and, since it’s still a little thick, prompt to which image collection to post images to (we only have one).
To create a post we must at least understand a POST request to AtomPost.aspx.
The client is posting an ATOM entry that we must read.
The blog system has objects of type Post that are going to be created. Also note that the post comes with ATOM categories – here you would need to recognize which ones must be created and which ones exist as well as associate the categories with the new post. We’ll omit that code to simplify things.
The post has been created, the server must respond with 201 Created and a new location for this post.
We’ll also add metadata that describes the new post ID and location and return the post to the client.
There’s no more data to be written to the client. Note that this throws a ThreadAbortException that must be trapped in the page code.
Updating and Retrieving Posts
There’re actually four scenarios to implement in AtomPost.
GET : retrieve all posts – see Generating Atom Feeds code above.
GET with a post ID: retrieve a specific post - a subset of GET for all posts.
POST : create a post – see Creating Posts code above.
PUT with a post ID: update an existing post – see Creating Posts code above.
Images are similar to posts, except that image data is never embedded in an Atom entry. An image is simply POSTed as binary data and reused in posts with the location that the server returns.
Similarly to AtomPost, AtomImage supports GET, POST and PUT. You can see the full code here.
All the POST and PUT calls must be authenticated, but I will leave this exercise to your particular system. I use form-based authentication, so I got lazy and did basic authentication in code – it should move out to an authentication provider so that the blog system supports both form-based and basic auth.
This was pretty easy after-all. It took less time putting this code together than struggling with the HTML editor in the past. And I am now writing this in LiveWriter!