Dependency Injection with WebAPI, Service Fabric and Autofac

Sample code

I really like the way Azure Service Fabric exposes actors and services from the factory as nicely typed interfaces in C#. It opens up some great scenarios for dependency injection and generally improving the developer experience.

To this end I decide to try and get Autofac going with the WebAPI Visual Studio template for Service Fabric.

The end goal is being able to pass services in like any other injected dependency like this:

private readonly IStateless1 _service;

public SomeRepo(IStateless1 service)
{
    _service = service;
}

public async Task<string> GetSomething()
{
    return await _service.GetHello();
}

You will need to install the Service Fabric SDK for this stuff.

Interestingly the template that is created when you add a WebAPI project to the Service Fabric project is not your traditional WebAPI affair – in this case we rely heavily on OWIN to build a self hosted WebAPI project almost from scratch (the template does handle most of this for you though).

When I saw the template generated code I feared that Autofac would not “just slot in” – it’s quite different to the regular WebAPI. That was not the case it turns out!

Because the WebAPI template makes great use of OWIN, the standard Autofac WebAPI Owin stuff worked pretty much straight away.

The magic happens in the Startup.cs file as per usual.

First you create a new ContainerBuilder and register the controllers.

 var builder = new ContainerBuilder();
 // Register your Web API controllers.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());    

The next code is from the template – create the HttpConfiguration and set up the MVC routes.

That config is then passed in to the Autofac extension to register the filter providers (so you can inject in to filters).

builder.RegisterWebApiFilterProvider(config);    

Now the fun part – registering our own services.

I created the amazingly named Stateless1 reliable service. It exposes IStateless1 which has the following method exposed on it:

public async Task<string> GetHello()
{
     return $"This is a test {DateTime.Now}";
}

I then register this using the overload of register that allows you to run some callback code lambda style.

builder.Register((e) => ServiceProxy.Create<IStateless1>(
     new Uri("fabric:/Application3/Stateless1")))
     .As<IStateless1>();

Once that is done, build the container and you’re set!

var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
appBuilder.UseWebApi(config);

I like to separate out my services a little bit from the code, even if that code is only referencing the interfaces so I’ve placed the actual access to the IStateless1 in to a repo that is my code (controllers) will access, rather than accessing the IStateless1 interface directly. This allows centralisation of the “SDK” to a library that other parts of your code can use.

public interface ISomeRepo
{
    Task<string> GetSomething();
}

public class SomeRepo : ISomeRepo
{
    private readonly IStateless1 _service;

    public SomeRepo(IStateless1 service)
    {
        _service = service;
    }

    public async Task<string> GetSomething()
    {
        return await _service.GetHello();
    }
}

https://github.com/jakkaj/AutofacServiceFabricExample/blob/master/src/WebApi1/Model/SomeRepo.cs

Note that IStateless1 is injected here. Once that is done, register the ISomeRepo with the container back in Startup.cs

builder.RegisterType<SomeRepo>().As<ISomeRepo>();

Finally – you can inject ISomeRepo in to your controller and start to see the results!

private readonly ISomeRepo _someRepo;

public ValuesController(ISomeRepo someRepo)
{
    _someRepo = someRepo;
}
// GET api/values 
public async Task<IHttpActionResult> Get()
{
    return Ok(await _someRepo.GetSomething());
}

Here is the full Startup.cs file

public static void ConfigureApp(IAppBuilder appBuilder)
{
    var builder = new ContainerBuilder();

    // Register your Web API controllers.

    builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

    // Configure Web API for self-host. 
    HttpConfiguration config = new HttpConfiguration();    

    config.Routes.MapHttpRoute(

        name: "DefaultApi",

        routeTemplate: "api/{controller}/{id}",

        defaults: new { id = RouteParameter.Optional }
    );

    builder.RegisterWebApiFilterProvider(config);

    //Register the repo that our code will use to abstract the end code one level from the actor
    builder.RegisterType<SomeRepo>().As<ISomeRepo>();

    //Register the actor.
    builder.Register((e) => ServiceProxy.Create<IStateless1>(new Uri("fabric:/Application3/Stateless1")))
        .As<IStateless1>();

    // Set the dependency resolver to be Autofac.
    var container = builder.Build();
    config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
    appBuilder.UseWebApi(config);
}

Full listing of https://github.com/jakkaj/AutofacServiceFabricExample/blob/master/src/WebApi1/Startup.cs