jvance.com

.net, c#, asp.net, linq, htpc, woodworking

Jarrett's Tech Blog - For August 2008

  1. New BlogSvc Release 0.2

    This release includes an implementation of Atom Publishing Protocol on WCF 3.5.  In the words of Tim Bray:

    An Atompub implementation lets you create, retrieve, update, and delete (CRUD) Web Resources. ... Atompub starts with a Service Document, which contains one or more named Workspaces, which contain Collections, which are what you actually POST to in order to start up the CRUD process.  So the idea is simple; have a collection that when you POST to it, creates a new publication.

    The object model is based off of the Atom Syndication Format and the AtomPub specs.  All of the objects are based off of Xml or the new XElement.  Propeties are used to support strongly typed access to the data.

    Atom Syndication Format Atom Publishing Protocol
    AtomCategory AppCategories
    AtomContent AppCollection
    AtomEntry* AppControl
    AtomFeed AppService
    AtomGenerator AppWorkspace
    AtomLink*  
    AtomPerson Atom Threading Extension
    AtomSource ThreadInReplyTo
    AtomText * Extended

     

    This release should work in IIS6 or IIS7 with .NET 3.5.  Also the SVC handler must support all verbs.  Since AtomPub is RESTful, you'll need PUT and DELETE to go along with the usual GET and POST verbs.

    The WCF service is built using the new Web Programming Model available in 3.5.  However, it is designed to support normal web services as well (more on this in a future post).  A neat WCF feature with this release is the support of media entries allowing a user to post images to a collection.  I found the trick to supporting raw data on Carlos' blog.  However, there is a catch. Anytime you want to accept unknown content types and known content types, you must only deal with Stream objects.  For example, although CreateEntry will always return an AtomEntry document you must specify a Stream because the input could be an AtomEntry or say a JPG image.

    [ServiceContract]
    public interface IAtomPub
    {
        [WebGet(BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "{workspaceName}/{collectionName}/{entryName}/media")]
        Stream RetrieveMedia(string workspaceName, string collectionName, string entryName);
        
        [WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "{workspaceName}/{collectionName}")]
        Stream CreateEntry(string workspaceName, string collectionName, Stream stream);
    
        [WebGet(UriTemplate = "{workspaceName}/{collectionName}/{entryName}")]
        Stream RetrieveEntry(string workspaceName, string collectionName, string entryName);
    
        [WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "{workspaceName}/{collectionName}/{entryName}", Method = "PUT")]
        Stream UpdateEntry(string workspaceName, string collectionName, string entryName, Stream stream);
    
        [WebInvoke(UriTemplate = "{workspaceName}/{collectionName}/{entryName}", Method = "DELETE")]
        void DeleteEntry(string workspaceName, string collectionName, string entryName);
    
        [OperationContract]
        [WebGet(UriTemplate = "service")]
        AppService RetrieveService();
    
        [WebGet(UriTemplate = "{workspaceName}/{collectionName}/category?scheme={scheme}")]
        AppCategories RetrieveCategories(string workspaceName, string collectionName, string scheme);
    
        [WebGet(UriTemplate = "{workspaceName}/{collectionName}")]
        AtomFeed RetrieveFeed(string workspaceName, string collectionName);
    }

    You can direct it to a strongly typed implementation by checking the content type.

    public Stream CreateEntry(string workspaceName, string collectionName, Stream stream)
    {
        string contentType = WebOperationContext.Current.IncomingRequest.ContentType;
        AtomEntry entry;
        if (contentType == Atom.ContentType || contentType == Atom.ContentTypeEntry)
        {
            entry = new AtomEntry();
            XmlReader reader = new XmlTextReader(stream);
            entry.Xml = XElement.Load(reader);
            entry = CreateEntry(workspaceName, collectionName, entry);
        }
        else entry = CreateMedia(workspaceName, collectionName, stream);
        return GetStream(entry);
    }

     

    IDs and Hrefs

    • Blog.svc WCF Service
    • UriTemplates
    • Handling Entry or Media Resources
    • WebLinks
    • Object Model over .Net 3.5 SP1 Object Model

    Test AtomPub and Atom and Threading auto links.

    Posted by Jarrett on August 04 at 8:30 PM

© Copyright 2024