Vanilla Yet Composable HTTP Services With WCF 4 and Windsor

Recently in my team, there’s been a lot of discussion about how we should go about implementing a service layer for various orthogonal behaviors.  At the center of the conversation is the question of whether or not we should develop this layer using MVC or WCF.  On first look, MVC paints a pretty compelling picture – particularly since the majority of our services will be consumed in a simple HTTP services fashion (Note: I’m intentionally avoiding the term RESTful service because these services will not necessarily be resource/noun focused – however, they will be plain old JSON or XML over HTTP – not something that requires a proxy in order to work with it).  Specifically, here are the some of the things that makes MVC look appealing:

  • It’s really easy – just create a controller and action method
  • Friendly URLs ala core routing
  • IIS hosted
  • JSON formatting is as simple as returning the JSON action result from the action method
  • It’s easy to leverage an IoC container – simply create/plug in a custom controller factory

So that’s a pretty good list.  However, even with all of those benefits, I kept coming back to a couple problems with using MVC as a general purpose service layer.

  • It tightly couples your service to a specific host (IIS)
  • It tightly couples your service to protocol (HTTP)
  • it tightly couples your service to an addressing scheme (URL)

Now I know that some of you are reading this and calling YAGNI on me – and that may be fair to some degree.  However, for what will be publically facing services (which implies that there needs to be some degree of longevity), I’m hesitant to take a dependency on an underlying “service platform” (in quotes since MVC wasn’t really meant to be this) that takes so many dependencies on things that I consider to be an architectural style (remember, it wasn’t that long ago that SOAP was the last thing we would ever need – and DCOM/CORBA before that).  And technically, I’m not really talking about building anything based on unknown future requirements, but on choosing a platform on which to take a dependency.

Philosophically, I’m a big fan of WCF because as one of its key characteristics, it decouples the programming model (the service definition) from both the networking stack that exposes and pipes data into the service and from the process that hosts and manages the service.  However, the initial versions of WCF provided all of this philosophical goodness at a cost – and that cost was complexity – particularly in the area of the host and network stack configuration.  And that complexity grew pretty significantly the further off the path you traveled.

That said, with each successive release of WCF, the level of complexity in configuration has been shrinking – to the point where as of WCF 4, the configuration piece has dwindled away to almost nothing.

At any rate, like I mentioned, I wanted to see whether I could build simple JSON over HTTP services in a way that leveraged all of WCF’s philosophical goodness but would give me the simplicity of development that I would find doing it in MVC.  More specifically, here’s what I was testing for:

  • Standard WCF programming model
  • JSON by configuration
  • Use of IoC to resolve the service graph
  • Hosted in IIS
  • Friendly URLs

Jumping right in, WCF has a really straightforward programming model.  It centers around the use of .NET interfaces decorated with a few attributes – these (along with some configuration around address and network stack) are exposed as WCF endpoints – and classes that implement one or more of those interfaces – these are WCF services and are the smallest units when it comes to hosting.  The big idea here is that by using plain old .NET constructs, you can completely decouple your service logic and even contracts from all the details around hosting it and exposing it to the network.  I started out in developing my service against this standard programming model.

[ServiceContract(Namespace = "urn:Spikes-WCF-JSONTests:IPersonService")]
public interface IPersonService
{
    [OperationContract]
    [WebGet(UriTemplate = "Find/{firstName}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
    Person FindPerson(string firstName);
}

As you can see, I’ve got a standard service contract with one operation.  The WebGetAttribute allows me to specify a URI template with parameter placeholders.  It’s worth noting here that this doesn’t give us complete MVC-ish friendly URLs – this is still relative to the service address, which if it’s hosted in IIS is that *.svc file.  However, as I’ll show in a second, WCF 4 helps us remedy this little bit of trailing ugliness.  Additionally, I’ve declared my message formatting in the WebGetAttribute class.  I suspect that this can actually be externalized to config, but I haven’t figured out how to do this yet, and and attribute is still less invasive than returning a JsonActionResult in MVC – so for now, that’s what I’m going with.

The service itself is a pretty straightforward implementation of this interface – with one exception..

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class PersonService : IPersonService
{
    readonly IPersonRepository _personRepository;

    public PersonService(IPersonRepository personRepository) {
        _personRepository = personRepository;
    }

    public Person FindPerson(string firstName) {
        return _personRepository.GetPeople().FirstOrDefault(p => p.FirstName == firstName);
    }
}

Notice that I have added a parameter to my constructor which declares that my service has a dependency on a concrete implementation of IPersonRepository.  One of the things that I love about MVC is how straightforward it is to create a custom ControllerFactory that can use an IoC container to resolve a controller’s entire dependency graph.  As such, I wanted to make sure that I could do the same thing in WCF.  Early on in my searching, I was very fortunate to come across a 2 part blog series on doing just this.  I have adapted the source just a bit to use Windsor and to account for a thing or 2 in WCF 4, but the bulk of the code (and my sincerest thanks) go to Fabio Cozzolino.

In short, the ControllerFactory equivalent in WCF is called the instance provider, and it’s any class that implements IInstanceProvider.  Here’s an instance provider that’s built to use a Windsor container:

class WindorInstanceProvider : IInstanceProvider
{
    readonly WindsorContainer _container;
    readonly Type _contractType;

    public WindorInstanceProvider(WindsorContainer container, Type contractType) {
        _container = container;
        _contractType = contractType;
    }

    public object GetInstance(InstanceContext instanceContext) {
        return GetInstance(instanceContext, null);
    }

    public object GetInstance(InstanceContext instanceContext, Message message) {
        return _container.Resolve(_contractType);
    }

    public void ReleaseInstance(InstanceContext instanceContext, object instance) {
        _container.Release(instance);
    }
}

I would elaborate, but there’s just not that much of interest going on here.  The instance provider is constructed with the container itself and the service type.  When asked, it turns around and asks the container to resolve the dependency graph and create an instance of the service type.  What’s more interesting is how the instance provider gets plugged in so that it can do its thing.

In the same way that ASP.NET (and MVC by extension) has a request pipeline, WCF has a channel stack.  However, unlike the case of ASP.NET, the WCF channel stack was meant to work across a myriad number of protocols and network topologies – as such, it’s a great deal more extensible – and that extensibility can sometimes bring with it some additional complexity.  In this case, that complexity exists in the form of a couple extra points of indirection – the first of which is a service behavior.

public class WindsorServiceBehavior : IServiceBehavior
{
    readonly WindsorContainer _container;

    public WindsorServiceBehavior(WindsorContainer container) {
        _container = container;
    }

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) {}

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase,
                                     Collection<ServiceEndpoint> endpoints,
                                     BindingParameterCollection bindingParameters) {}

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) {
        foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
            foreach (var endpointDispatcher in channelDispatcher.Endpoints) {
                if (endpointDispatcher.ContractName == "IMetadataExchange" || endpointDispatcher.ContractName == "IHttpGetHelpPageAndMetadataContract")
                    return;
                string contractName = endpointDispatcher.ContractName;
                ServiceEndpoint serviceEndpoint =
                    serviceDescription.Endpoints.FirstOrDefault(e => e.Contract.Name == contractName);
                endpointDispatcher.DispatchRuntime.InstanceProvider =
                    new WindorInstanceProvider(_container, serviceEndpoint.Contract.ContractType);
            }
    }
}

The purpose of my service behavior is simply to iterate through each endpoint in my service and set the endpoint’s instance provider to a new instance of my WindsorInstanceProvider, passing it an instance of my container (which I supply in the behavior’s constructor).  I’m only doing this for custom endpoints – not for the metadata endpoint sometimes added somewhat transparently by a different behavior.  It’s also worth pointing out that with WCF 4, I need to add a second type of metadata endpoint, IHttpGetHelpPageAndMetadataContract (I fully expect that we’ll see interface names that are complete sentences before long), to the exclusions list.

So you can now see where the instance provider comes from, but what about the container itself?  And where is the behavior wired up.  Enter the custom service host and custom service host factory  First the factory:

public class WindsorServiceHostFactory : WebServiceHostFactory
{
    readonly WindsorContainer _container;

    public WindsorServiceHostFactory() {
        _container = new WindsorContainer(new XmlInterpreter(new ConfigResource("castle")));
    }

    public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses) {
        //ctor string is the qualified serviceType name 
        var t = Type.GetType(constructorString);
        if (t == null)
            throw new ArgumentNullException("Could not resolve type '" + constructorString + "'");
        return CreateServiceHost(t, baseAddresses);
    }

    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) {
        var serviceHost = new WindsorServiceHost(_container, serviceType, baseAddresses);
        return serviceHost;
    }
}

As you can see, this is the point at which I’m actually creating the container.  When asked to create the service host, I simply create and return an instance of my custom service host and pass my container to it.  My service host, then, takes care of wiring up the behavior and you already know the rest of that story.

public class WindsorServiceHost : WebServiceHost
{
    readonly WindsorContainer _container;

    public WindsorServiceHost(WindsorContainer container, Type serviceType, params Uri[] baseAddresses)
        : base(serviceType, baseAddresses) {
        _container = container;
    }

    protected override void OnOpening() {
        if (Description.Behaviors.Find<WindsorServiceBehavior>() == null)
            Description.Behaviors.Add(new WindsorServiceBehavior(_container));

        base.OnOpening();
    }
}

So, the chief complaint that I’ve heard about WCF is how painful the XML configuration is – here’s the great part – in WCF 4, the configuration is insanely straightforward – here’s the configuration to get this all up and going (keep in mind that I would actually like to externalize more of my current sample into configuration – but this should give you a pretty good sense of how much has been improved in this area).

<system.serviceModel>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
  <standardEndpoints>
    <webHttpEndpoint>
      <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"/>
    </webHttpEndpoint>
  </standardEndpoints>
</system.serviceModel>

 

So deploying to IIS is as simple as building this into an *.svc file and writing a directive to point to my custom service host factory.  But then I still end up with odd-looking URLs like http://localhost/SimpleWCFTestHost/PersonService.svc/Find/Howard.  It would be even better if I could just drop that *.svc file and have completely clean URLs – just like I can do with MVC.  Firstly, remember that MVC doesn’t actually give you clean URLs – it simply plugs into the new core routing engine that’s backed into ASP.NET 4.  And that’s exactly the capability that WCF 4 gives you as well.  To light this up, all I had to do was add this to my global.asax.cs file.

public class Global : HttpApplication<br />{
    protected void Application_Start(object sender, EventArgs e) {
        RegisterRoutes(RouteTable.Routes);
    }

    static void RegisterRoutes(RouteCollection routes) {
        routes.Add(new ServiceRoute("", new WindsorServiceHostFactory(), typeof(PersonService)));
    }
}

This simple entry and I now have the ability to address my service as http://localhost/SimpleWCFTestHost/Find/Howard.   Had I wanted to give the service its own path segment, I could have specified my desired segment name as the first parameter to the ServiceRoute constructor.

After this experiment, WCF is at this point in time the more natural choice in my mind for building a general service layer.  Note – I’m not saying that you shouldn’t use MVC to create services for the AJAX components on your pages.  Just that if those services grow in scope such that they have other clients than your view, it might be time to look at a truer service platform – with WCF 4, it’s not *that* much more complicated.

Finally, I stumbled across a multi-part series that’s currently being developed on this topic over at The .NET Endpoint – It looks like they are just on part 4 of 12, so that’s only around the first 30 minutes of the movie – there’s still plenty of great stuff to come!

About Howard Dierking

I like technology...a lot...
This entry was posted in architecture, IoC, WCF, Windsor. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Søren

    Yeah, I can see what you mean… though it’s a bit annoying that you have to have the exact class available at compile time… So I’ve played a bit around with it… 
    I created an implementation of AbstractFacility, and adding my routes here, this way I can avoid having the service class available at compile time….

    void KernelComponentRegistered(string key, Castle.MicroKernel.IHandler handler)
    {
    if (!typeof(IRESTService).IsAssignableFrom(handler.ComponentModel.Implementation)) return;
    RouteTable.Routes.Add(new ServiceRoute(GetRoutePrefix(handler.ComponentModel.Implementation), factory, handler.ComponentModel.Implementation));
    }
    where the GetRoutePrefix is an Attribute that I annotate my service with.

  • Anonymous

    @ Søren – yes, trying to pass IPersonService to ServiceRoute doesn’t work – and it goes back to WCF’s expectations around the difference between services and contracts (e.g. services are classes and services can implement 0 or more contracts, or interfaces (0 would actually be 1 as the class would be acting as the implicit contract)).  Because you’ve got your own instance provider, it shouldn’t matter.  However, one of the jobs of the service host is to create the service description (your custom host delegates that job to its base class) – and in the ServiceDescription constructor, there’s the following gate:

    if (!serviceType.IsClass){  throw new ArgumentException(SR.GetString(“SFxServiceHostNeedsClass”));}
    The funny thing is that if you have multiple service classes that implement your interface, you can provide any one of them to ServiceRoute (thus satisfying ServiceDescription) and your instance provider + container will still override that with the correct concrete type at runtime.

  • Søren

    Hi

    In your example, you’re adding a route to ‘PersonService’:
    routes.Add(new ServiceRoute(“”, new WindsorServiceHostFactory(), typeof(PersonService)));

    but in order to really use Windsor Castle, you should add a route IPersonService, and have Windsor resolve it to PersonService … however changing typeof(PersonService) to typeof(IPersonService) doesn’t seem to work….
    How would you do that?

    TIA

    Søren

  • Ales

    Thanks a lot for taking the time to write the excellent post. It works like a charm. The only thing I changed was WindsorServiceHostFactory constructor accepting an instance of WindsorContainer – since that would typically be instantiated in Global.

  • Vince

    Upon trying to resolve IPersonService I’m getting an exception. No component for supporting the service IPersonService was found. I have my castle node setup in my web.config with a component node specifying my repository. Any ideas?

  • Wil

    What is the WebServiceHost and WebServiceHostFactory? Do I need it for hosting in WAS? Can I just extend ServiceHostFactory and ServiceHost?

  • Ed Blackburn

    If you’re evaluating options, take a look at http://openrasta.com

  • http://colinjack.blogspot.com Colin Jack

    @Dean
    Yeah WCF can be a real pain, the WCF Facility is great but there’s still a lot of friction and I’m not really sure how useful 90%+ of the WCF “features” are for this sort of service.

    Just on running on a transport protocol other than TCP/IP, remember HTTP and TCP/IP are not the same thing, but yeah I agree with your point. It is unlikely you’ll have to move from HTTP, in addition if you do its likely to be an architectural change such as embracing EDA, and even if that isn’t the case the WCF approach isn’t isolating you effectively. The key thing is to ensure key business logic/workflow is kept outside the layer that is coupled to HTTP, but I think thats good design anyway.

  • http://www.infovark.com Dean Thrasher

    I haven’t begun working with WCF 4, but I’ve found MVC to be many times more productive an environment than WCF.

    Besides, what are the chances that someone will ask you to make your service layer run on something _other_ than TCP/IP in the next five years?

  • http://colinjack.blogspot.com Colin Jack

    On our project we are using WCF for a RESTful Web Services layer and MVC for our Web apps. We needed that architecture and tech choices were made early on, but my point is I’ve done a good bit of work with them both.

    So on to your discussion advantages of WCF, first is protocol independence. The question is whether its useful, http://www.markbaker.ca/blog/2004/10/protocol-independence/.

    Some questions I’d have on it are:

    * Is your IPersonService really independent of URIs and HTTP? If you did decide to move from HTTP/URI would that interface stay or would you need to rethink?
    * How about the implementation, the code inside the PersonService? To keep it independent of the application protocol we’d need to consider abstracting the request/response headers, the HTTP status codes, all the caching functionality. Is that sensible?
    * How about linking (and HATEOAS), which involves URIs, do we skip that?
    * And then there’s the fact that if we want to take advantage of features of HTTP, such as its great caching support, then we have to be prepared to have it influence our resource/service design directly. Do we skip that because we might want to expose this service in a different way in the future?

    Personally I don’t want to skip key features of REST/HTTP, they are too useful. Same goes for messaging/EDA, when using them I think you are better using something like NServiceBus which embraces that style.

    The question then becomes is building RESTful services on top of WCF a joy, the answer is no. You end up putting in ridiculous amounts of work (http://colinjack.blogspot.com/2009/09/wcf-and-rest.html) just to get simple things working. I’m slightly hopeful about WCF4 though, fingers crossed they’ve made the right choices this time.

    On the extensibility story, other frameworks do seem to be setting out for a good extensibility story these days and anyway we’ve found the WCF extensibility approach a bit clunky and inappropriate in some cases.

  • http://kozmic.pl Krzysztof Kozmic

    I just clicked to mention WCF Facility, but I guess there’s no need at this point.

    It has poor documentation, I admit, but in the following days I set of to improve it so keep looking here: http://using.castleproject.org/display/IoC/Windsor+WCF+integration+facility

    There will hopefully be a lot of useful content here quite soon.

  • http://www.kenegozi.com/blog Ken Egozi

    ha ha ha
    I was just about to link to Mike Hadlow’s post series on the WCF Facility :)

  • http://mikehadlow.blogspot.com/ Mike Hadlow

    You might want to check out the Windsor WCF Facility. It integrates WCF with Windsor and provides an elegant fluent API for WCF configuration. The documentation is limited, but it’s a really nice piece of work.

    I’ve written a series of posts about it:
    http://mikehadlow.blogspot.com/2009/05/multi-tenanted-services-with-windsor.html