Exploring resources, a resource programming model, and code-based configuration.

ResourceProgrammingModel.zip

Disclaimer: Early prototype

At Oredev 2010 in Sweden (which btw is an AMAZING conference), I demonstrated a prototype of a convention-based resource programming model for our new HTTP apis. In this post I’m going to discuss a bit of background (not exhaustive) resources. Next we’ll delve into an initial cut at a resource programming model. It supports more than just resources, it also supports code-based configuration and adds support for IoC containers, something we’ve heard many folks ask for. I’ll focus mainly on the resource part, but touch on some of those capabilities as well.

First a bit of context around resources and HTTP.

Resources

Resources are at the heart of HTTP. A resource is an entity that is exposed over and accessible through HTTP. Entity in this case could literally be anything, a file, a web page, an image, a video, etc. Each resource is addressable through a URI or Uniform Resource Identifier. Resources are accessed through a standard set of HTTP methods including “GET”, “POST”, “PUT” and “DELETE” which can be used for reading or updating the resource.

There are 2 common categories of resources. An item resource refers to an individual resource like a Contact resource. A collection resource refers to a collection of child resources such as a Contacts resource. To add a contact to a contact management system exposed over HTTP for example you can POST a contact to the Contacts resource. To retrieve an individual resource however you would perform a GET on the contact resource.

Representations and Media Types

Resources have one or more representations which a client can access. The representation is not the resource rather it is a snapshot of the resource which is presented in a specific format. That format is identified through what is known as a  media type which is stored in the Content-Type header of a request or response. Examples of standard media types are application/xml, application/json, application/atom+xml, application/pdf and image/png. Some of these are markup based and some of them are not.

For example at PDC I demonstrated a resource that returns an image (image/png) representation of a contact. The resource is actually the contact which is stored in a database, while the image is just one representation that gets returned to the client.

New media types are continually created (minted) to meet specific needs. If a media type is to be consumed publically, it is standard for it to be registered in the IANA registry where potential clients can access it’s specifications.

The important takeaway here is that resources representations are not fixed. New representations can be added without affecting existing clients at all. This provides great flexibility in the maintainability of resources. It allows the resource to evolve over time.

Negotiating representations

HTTP provides several mechanisms for allowing the server to select the appropriate representation for a specific request. For example with transparent content negotiation (conneg) the client sends a list of Accept headers specifying media types they can handle along with qualifiers indicating which one they prefer. Alternatively a resource may also expose it’s specific representations as sub-resources which can be accessed through a specific uri. For example “http://contoso/contact/1.xml” and “http://consoto/contact/1.json” would both be sub-resources of “http://contoso/contact/1”.

The need for a resource programming model

Looking at the overview of resources above, we can see that there are several key characteristics that define a resource.

  • It is addressable through a URI
  • It is accessible through one or more HTTP methods
  • It has one or more representations.
  • It can be collection based or item based.

Today WCF has no real notion of an HTTP resources. In WCF HTTP, resources emerge as the result of annotating services and methods with various attributes such as WebGet, WebInvoke, etc. The model requires the developer to be very very explicit about how to do the mapping. The reason for this is because the existing functionality is designed to allow one to take a traditional service such as one that is exposed over SOAP, and expose it over raw HTTP.

What if you only care about HTTP ? In that case, you might want something more natural. You might want a model that is more implicit than explicit. With such a model, you could tell WCF, “I am building a resource” and it can make a whole bunch of assumptions based on the conventions / constraints set by HTTP. It can for example assume things like some of your methods map to HTTP methods or it can apply special rules depending on if you are a collection or an item resource. It can also potentially assume that resources relate to other resources and even provide special behavior based on those relationships.

The resource model

To understand the benefits the model brings, let’s first take a look at the ContactResource we ship today.


    [ServiceContract]
    public class ContactResource
    {
        private readonly IContactRepository repository;

        public ContactResource(IContactRepository repository)
        {
            this.repository = repository;
        }

        public ContactResource() : this(new ContactRepository())
        {
        }

        [WebGet(UriTemplate = "{id}")]
        public Contact Get(string id, HttpResponseMessage response)
        {

var contact = this.repository.Get(int.Parse(id,

CultureInfo.InvariantCulture));

            if (contact == null)
            {
                response.StatusCode = HttpStatusCode.NotFound;
                response.Content = HttpContent.Create("Contact not found");
            }

            return contact;
        }

        [WebInvoke(UriTemplate = "{id}", Method = "PUT")]

public Contact Put(string id, Contact contact,

HttpResponseMessage response)

        {
            this.Get(id, response);
            this.repository.Update(contact);
            return contact;
        }

        [WebInvoke(UriTemplate = "{id}", Method = "DELETE")]
        public Contact Delete(string id)
        {
            var intId = int.Parse(id, CultureInfo.InvariantCulture);
            dynamic deleted = this.repository.Get(intId);
            this.repository.Delete(intId);
            return deleted;
        }
    }
}

A few things to note about the resource above.

  • The resource is annotated with [SeviceContract] to tell WCF it is a service.
  • Each operation is annotated with [WebGet]/[WebInvoke] and explicitly specifies the HTTP method
  • Each operation specifies a UriTemplate with an id parameter as the resource in this case is an item resource
  • The resource uses a default ctor to inject a dependency. (Not something specific to resources, it also applies to general WCF services)

Here’s how the same resource looks with the resource model.

    public class ContactResource
    {
        private readonly IContactRepository repository;

        public ContactResource(IContactRepository repository)
        {
            this.repository = repository;
        }

        public Contact Get(string id, HttpResponseMessage response)
        {
            var contact = this.repository.Get(
                int.Parse(id, CultureInfo.InvariantCulture));
            if (contact == null)
            {
                response.StatusCode = HttpStatusCode.NotFound;
                response.Content = HttpContent.Create("Contact not found");
            }

            return contact;
        }

public Contact Put(string id, Contact contact,

HttpResponseMessage response)

        {
            this.Get(id, response);
            this.repository.Update(contact);
            return contact;
        }

        public Contact Delete(string id)
        {
            var intId = int.Parse(id, CultureInfo.InvariantCulture);
            dynamic deleted = this.repository.Get(intId);
            this.repository.Delete(intId);
            return deleted;
        }
    }

What is different?

  • There are no attributes to say this is a resource, we know it’s a resource.
  • Methods are not annotated to indicated the HTTP method, instead the method is mapped conventionally by name.
  • The URI template is conventionally constructed.
  • The resource is injected with an IContactRepository which it receives through an IoC.

I mentioned above that resources have one or more representations, yet there are none specified above. The idea here is to keep the resource decoupled from it’s representations. Those are specified elsewhere through the configuration class.

Taking a look at the collection resource, it looks similar.

    public class ContactsResource
    {
        private readonly IContactRepository repository;

        public ContactsResource(IContactRepository repository)
        {
            this.repository = repository;
        }

        public List<Contact> Get()
        {
            return this.repository.GetAll();
        }

        public Contact Post(Contact contact, HttpResponseMessage response)
        {
            this.repository.Post(contact);
            response.StatusCode = HttpStatusCode.Created;
            return contact;
        }
    }

Notice the main difference is that it’s methods don’t access the id. This makes sense as it is a collection.

Configuration

In order to configure the host with the prototype resource programming model, you create a class which derives from ResourceConfiguration. This class is passed to the service host to configure it. The prototype includes an AddResourceRoute extension method for passing this in through routes. More on this in a bit. This class is used for more than just resources, it is a general way to configure parts of WCF programatically rather than through a config file. I’ll cover more on the uses later.

Let’s first take a look at the configuration class that the ContactManager uses.

    public class ContactManagerConfiguration : ResourceConfiguration
    {
        private IUnityContainer container;

        public ContactManagerConfiguration(IUnityContainer container)
        {
            this.container = container;
        }

        public override void RegisterRequestProcessorsForOperation(
            HttpOperationDescription operation, 
            IList<Processor> processors, 
            MediaTypeProcessorMode mode)
        {
            processors.Add(new JsonProcessor(operation, mode));
            processors.Add(new FormUrlEncodedProcessor(operation, mode));
        }

        public override void RegisterResponseProcessorsForOperation(
            HttpOperationDescription operation, 
            IList<Processor> processors, 
            MediaTypeProcessorMode mode)
        {
            processors.Add(new JsonProcessor(operation, mode));
            processors.Add(new PngProcessor(operation, mode));
        }

        public override object GetInstance(
            System.Type serviceType, 
            InstanceContext instanceContext, 
            Message message)
        {
            return container.Resolve(serviceType);
        }

        public override void ReleaseInstance(
            InstanceContext instanceContext, 
            object service)
        {
            container.Teardown(service);
        }
    }

Key things to note:

  • The configuration class derives from ResourceConfiguration. This turns on the conventions we discussed earlier.
  • RegisterRequestProcessorsForOperation / RegisterResponseProcessorsForOperation are where representations are configured. In this case you can see that the request supports Json and FormUrlEncoded while the response supports Json and Png. Media type formatting is just one of the many things that you can do with processors. More on that in another post.
  • An IoC container is specified for constructing the resource. In this case, the configuration class accepts a unity container passed in during construction. The GetInstance and ReleaseInstance methods are then overridden and hand off to the IoC for constructing/releasing. This is a very simplistic usage with a single global container, however through the instance context, you can create and store per-request level containers. I am not going to delve into the how of that now. Smile

The code that actually configures the host in the global.asax is below:

    protected void Application_Start(object sender, EventArgs e)
    {
        IUnityContainer container = new UnityContainer();
        container.RegisterType(typeof(ContactResource));
        container.RegisterType(typeof(ContactsResource));
        container.RegisterType(
            typeof(IContactRepository), 
            typeof(ContactRepository),
            new ContainerControlledLifetimeManager());

        var configuration = new ContactManagerConfiguration(container);
        RouteTable.Routes.AddResourceRoute<ContactResource>(
            "contact", configuration);
        RouteTable.Routes.AddResourceRoute<ContactsResource>(
            "contacts", configuration);
    }

 

First I am creating a Unity container and configuring the types. Then the configuration class is constructed passing the container. Finally AddResourceRoute is called passing in the resources, base uri and the configuration class.

Uri templates and hosting on IIS / self-host?

For those of you that are familiar with our WCF HTTP model you might be wondering how the URI template is constructed. Currently it is constructed by default based on a bunch of assumptions, however they can be overridden.

  • By default the resource is assumed to be registered through a ServiceRoute that supplies it’s uri. Thus the UriTemplate does not contain the name of the resource i.e. contact, contacts, etc.
  • If the class name does not end with “s” then the resource is assumed to be an item resource. In this case the UriTemplate is set to {id} based on the assumption that the last uri segment will be an id pointing to the resource i.e. contact/1.

This is definitely simplistic, however the model supports specifying it yourself for example pulling from a configuration file or through an FI. The configuration class contains a protected method called GetUriTemplate. If you override it, you can take the URIs into your own hands. In the current prototype you need to do this if you want to self-host or host on IIS. I wouldn’t’ expect that to be the long term solution…

Code-based configuration

As I mentioned above, the configuration class above is addressing more than just resources and representations. It also provides richer ways to configure WCF through code. This sample doesn’t illustrate that, but if you look there are two protected methods ApplyConfiguration and ConfigureOperation.

  • ApplyConfiguration gives you the opportunity to configure things on the host that normally would be configured through web.config. It is called once when the host is created.
  • ConfigureOperation is called for each operation. It gives you the opportunity to programmatically in a centrally managed way rather than annotating each operation.

It’s a prototype Smile

I’ve said prototype over and over throughout this blog. The reason I did that is to set proper expectations as it’s very likely some of your scenarios are not supported. I am putting this out there to get feedback on if this is a direction you think we should pursue.

Code is attached. We look forward to your feedback (good or bad),

This entry was posted in HTTP, Oredev, REST, WCF. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Anonymous

    Ok so I’ve had a play with this for a couple of days now and on the whole I’m really positive about the direction you guys are taking with this. Now as you mentioned, its a prototype, but I do have a few concerns with the current implementation.

    First of all, nested resources? its quite common to have things like “http://www.foo.com/{username}/contact/{contactid}” I dont really think theres an elegant way to solve that with the current prototype. Maybe something like its done in mvc with MapRoute

    Second: UriTemplates, I know I can override GetUriTemplate on the ResourceConfiguration, but if you have multiple/nested resources this is going to get complicated real fast. Maybe having a simple UriTemplate attribute would do the trick?

    Third: Async, to be honest I’ve not really looked into this much, since theres seems to be couple of different ways to do this now, but if I have domain model underneath exposing async methods (begin/end) the current model does not really seem to lend itself well to this (but I might just be missing something obvious here)

    Anyways, good work so far, I’m really looking forward to seeing where you take it from here.

  • http://blogs.msdn.com/gblock Glenn Block

    It is now :-) The site was recently migrated to WordPress and there was an issue with attachments.

    Just i case you didn’t see it in my web apis roundup post the resource model binaries are also available as a nuget pack, WcfResource.

    Have fun!

  • Jason

    Yes as nicolai mentioned, can’t seem to find attached code link..

  • Anonymous

    It might just be me? but where is the code attached?

  • http://www.2geeks1rant.com rafek

    You’re right.. Øredev was amazing, indeed! Actually I kinda regret going to Deep Dive into HTML5 session instead of yours. ;)