August 15, 2011

Creating a StructureMap Resource Factory for WCF Web API

Note: This code uses preview 4 of WCF API (available on nuget).

One area that was always challenging with WCF (aside from WCF itself :p) was how to handle dependency injection. Since there was no easy way of hooking into the WCF pipeline we couldn’t take control of how our services (or resources) were created. Typically this led to poor man’s DI either directly, or via a factory of some sort.

WCF Web API changed all that. .NET developers will certainly have noticed the change in Microsoft’s developer wing, with greater community collaboration, shipping releases faster and producing some real great tools like asp.net mvc, nuget and of course, wcf web api.

WCF Web API provides loads of extensibility points that allow us to hook into the WCF pipeline. One of these is controlling how our resources (services) are created.

Traditionally you may have had a resource like so:

[ServiceContract]
public class ContactsResource
{
    private readonly IContactRepository contactRepo;
   	
    public ContactsResource()
    {
        this.contactRepo = ObjectFactory.GetInstance<IContactRepository>;
    }
	
    [WebGet(UriTemplate = "")]
    public List<Contact> Get()
    {
        return contactRepo.GetContacts().ToList();
    }
}

Note the direct reference to our DI tool (StructureMap).

With WCF Web Api we can create a custom IResourceFactory that is responsible for creating our resources (go figure). Here’s one for StructureMap:

public class StructureMapResourceFactory : IResourceFactory
{
    private readonly IContainer container;

    public StructureMapResourceFactory(IContainer container)
    {
        this.container = container;
    }
    
    public object GetInstance(Type serviceType, InstanceContext instanceContext, HttpRequestMessage request)
    {
        return container.GetInstance(serviceType);
    }

    public void ReleaseInstance(InstanceContext instanceContext, object service)
    {
        
    }
}

I asked Glenn Block (Web API Wonderman) about ReleaseInstance. He said:

Not having a release is something we’ve heard folks raise about DR in MVC. It means there is a clean way to clean up.

This is a valid point. There may be additional clean up tasks you want to perform once you’ve finished with a service. Of course with StructureMap you could just implement IDisposable and Dispose() will be executed automatically for you, but I suppose they need to cater for other DI/DR tools.

You could also use ReleaseInstance to commit transactions, or persist state that may have been collected through the lifetime of your resource, such as logs.

To register the factory we execute the following when our application starts (after you’ve configured StructureMap):

var config = HttpHostConfiguration.Create()
    .SetResourceFactory(new StructureMapResourceFactory(ObjectFactory.Container));

This config is the HttpHostConfiguration that we include when registering our routes:

RouteTable.Routes.MapServiceRoute<ContactsResource>("contacts", config);

Now we can update our original resource to make use of constructor injection (how it should be done):

[ServiceContract]
public class ContactsResource
{
    private readonly IContactRepository contactRepo;

    public ContactsResource(IContactRepository contactRepo)
    {
        this.contactRepo = contactRepo;
    }
	
    [WebGet(UriTemplate = "")]
    public List<Contact> Get()
    {
        return contactRepo.GetContacts().ToList();
    }
}

© 2020 Ben Foster