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: ,

Autofac | Web Services

Comments (3) -

Martin Fabik
Martin Fabik
8 May 2010 - 8:05 AM #

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 ?

Reply

Alex Meyer-Gleaves
Alex Meyer-Gleaves
9 May 2010 - 2:19 AM #

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);

Reply

Afshar Mohebbi
Afshar Mohebbi Iran
20 December 2011 - 5:09 AM #

Hi Alex,

Your sample helped me a lot. I had a problem about debugging with my own and solved it based on your sample. I have put a modified version of your sample in the blog post:

blog.afsharm.com/.../...blem-with-autofac-wcf.html

Thanks a again

Reply

Add comment

  Country flag

biuquote
  • Comment
  • Preview
Loading

About the author

Alex Meyer-Gleaves I'm a Technical Architect 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 Shared

 

Month List

Recent Posts

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 2010