Self-Hosting WCF Services with the Autofac WCF Integration

by Alex Meyer-Gleaves 7 May 2010 - 12:14 AM

A question came up recently in the Autofac group about how to use the WCF Integration when self-hosting WCF Services. This post provides a quick demonstration of how to handle the self-hosting scenario and should be enough to get you started. The example is a rather unimaginative web service that echoes back a message.

First declare the interface and implementation for a logger that the WCF Service will take as a dependency in its constructor. This is a simple logger that will log the message sent to the WCF Service out to the console.

public interface ILogger
{
    void Write(string message);
}

public class Logger : ILogger
{
    public void Write(string message)
    {
        Console.WriteLine(message);
    }
}

Next you need to define the contract and implementation for the WCF Service. Nothing interesting here other than our dependency being requested through the constructor of the WCF Service implementation.

[ServiceContract]
public interface IEchoService
{
    [OperationContract]
    string Echo(string message);
}

public class EchoService : IEchoService
{
    private readonly ILogger _logger;

    public EchoService(ILogger logger)
    {
        _logger = logger;
    }

    public string Echo(string message)
    {
        _logger.Write(message);
        return message;
    }
}

Now we can create a Console Application that will configure the container and host our WCF Service.

ContainerBuilder builder = new ContainerBuilder();
builder.Register(c => new Logger()).As<ILogger>();
builder.Register(c => new EchoService(c.Resolve<ILogger>())).As<IEchoService>();

using (IContainer container = builder.Build())
{
    Uri address = new Uri("http://localhost:8080/EchoService");
    ServiceHost host = new ServiceHost(typeof(EchoService), address);
    host.AddServiceEndpoint(typeof(IEchoService), new BasicHttpBinding(), string.Empty);

    IComponentRegistration registration;
    if (!container.ComponentRegistry.TryGetRegistration(new TypedService(typeof(IEchoService)), out registration))
    {
        Console.WriteLine("The service contract has not been registered in the container.");
        Console.ReadLine();
        Environment.Exit(-1);
    }

    host.Description.Behaviors.Add(new AutofacDependencyInjectionServiceBehavior(container, typeof(EchoService), registration));
    host.Description.Behaviors.Add(new ServiceMetadataBehavior {HttpGetEnabled = true, HttpGetUrl = address});
    host.Open();
    
    Console.WriteLine("The host has been opened.");
    Console.ReadLine();

    host.Close();
    Environment.Exit(0);
}

Here we have added an IServiceBehavior called AutofacDependencyInjectionServiceBehavior that will add a custom IInstanceProvider to the DispatchRuntime of each endpoint’s EndpointDispatcher. That is a bit of a mouth full but basically means that Autofac will use the WCF extensibility points to provide WCF Service instances that have their dependencies injected.

In this example the WCF Service is exposed on an endpoint that uses the BasicHttpBinding but you can use any type of endpoint that you like. I have added a ServiceMetadataBehavior in this example that exposes the WSDL for the WCF Service at http://localhost:8080/EchoService?wsdl. You can use this address to create a client proxy and send test messages that are hopefully more creative than my example.

Tags: ,

Categories: Autofac | Web Services

Comments

5/8/2010 8:05:12 AM #

Martin Fabik

When the service has ServiceBehavior set to InstanceContextMode.Single, you'll get the following exception:

The service type provided could not be loaded as a service because it does not have a default (parameter-less) constructor. To fix the problem, add a default constructor to the type, or pass an instance of the type to the host.

I guess an workaround would be to call the SingleInstance() method on the particular type, wouldn't it ?

Martin Fabik Czech Republic |

5/9/2010 2:19:49 AM #

Alex Meyer-Gleaves

When the InstanceContextMode of your WCF Service is set to Single, the ServiceHost will attempt to create a singleton instance for you in its constructor. That instance will then be used to service all requests. You could avoid the exception by configuring the Autofac registration to be SingleInstance and leaving the InstanceContextMode at its default value of PerSession. The downside is that your WCF configuration would be in contradiction with the actual lifetime behaviour of your WCF Service.

The ServiceHost has a constructor that accepts a singleton instance. You could keep your service configured with InstanceContextMode.Single, and then resolve your SingleInstance service from the container and pass it into the constructor of the ServiceHost. This way the lifetime defined in your WCF configuration will match the lifetime configured in the Autofac container.

IEchoService echoService = container.Resolve<IEchoService>();
Uri address = new Uri("http://localhost:8080/EchoService");
ServiceHost host = new ServiceHost(echoService, address);

Alex Meyer-Gleaves Australia |

5/17/2010 11:54:38 AM #

pingback

Pingback from topsy.com

Twitter Trackbacks for
        
        Alex Meyer-Gleaves | Self-Hosting WCF Services with the Autofac WCF Integration
        [alexmg.com]
        on Topsy.com

topsy.com |

Comments are closed

About the author

Alex Meyer-Gleaves I'm a software developer living in Australia (that island like continent in the southern hemisphere). I love Microsoft .NET and C#. I hate early mornings, slow drivers and Lotus Notes.

Google Reader Clips

SpringWidgets
RSS Reader
This widget is the staple of our platform. Read all your feeds right here with thisone widget - Supported feeds are OPML, RSS, RDF, ATOM. Watch your favorite Podcastin the embedded Video Player on the Desktop or publish your own video playlist toyour site for others to view!

Recent Comments

Comment RSS

Links

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in  anyway.

© Copyright 2008