Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Autofac and ASP.NET Web API ApiController

I have been using autofac with MVC 3 for a while and love it. I recently upgraded a project to MVC 4 and everything seems to be working except for Web Api ApiControllers. I am getting the following exception.

An error occurred when trying to create a controller of type 'MyNamespace.Foo.CustomApiController'. Make sure that the controller has a parameterless public constructor.

This seems to me to be an issue with DI via autofac. Am I missing something or is there something in the works. I know, MVC4 just came out and is a beta so I don't expect much but figured I could be missing something.

like image 573
Adam Carr Avatar asked Feb 26 '12 03:02

Adam Carr


2 Answers

I have released Autofac integration packages on NuGet for the Beta versions of MVC 4 and Web API. The integrations will create an Autofac lifetime scope per controller request (MVC controller or API controller depending on the integration). This means that the controller and its dependencies will be automatically disposed at the end of each call. Both packages can be installed side-by-side in the same project.

MVC 4

https://nuget.org/packages/Autofac.Mvc4

http://alexmg.com/post/2012/03/09/Autofac-ASPNET-MVC-4-(Beta)-Integration.aspx

Web API

https://nuget.org/packages/Autofac.WebApi/

http://alexmg.com/post/2012/03/09/Autofac-ASPNET-Web-API-(Beta)-Integration.aspx

Links are now fixed.

like image 109
Alex Meyer-Gleaves Avatar answered Oct 04 '22 21:10

Alex Meyer-Gleaves


I just configured this on one of my apps. There are different ways of doing it but I like this approach:

Autofac and ASP.NET Web API System.Web.Http.Services.IDependencyResolver Integration

First I created a class which implements System.Web.Http.Services.IDependencyResolver interface.

internal class AutofacWebAPIDependencyResolver : System.Web.Http.Services.IDependencyResolver {

    private readonly IContainer _container;

    public AutofacWebAPIDependencyResolver(IContainer container) {

        _container = container;
    }

    public object GetService(Type serviceType) {

        return _container.IsRegistered(serviceType) ? _container.Resolve(serviceType) : null;
    }

    public IEnumerable<object> GetServices(Type serviceType) {

        Type enumerableServiceType = typeof(IEnumerable<>).MakeGenericType(serviceType);
        object instance = _container.Resolve(enumerableServiceType);
        return ((IEnumerable)instance).Cast<object>();
    }
}

And I have another class which holds my registrations:

internal class AutofacWebAPI {

    public static void Initialize() {
        var builder = new ContainerBuilder();
        GlobalConfiguration.Configuration.ServiceResolver.SetResolver(
            new AutofacWebAPIDependencyResolver(RegisterServices(builder))
        );
    }

    private static IContainer RegisterServices(ContainerBuilder builder) {

        builder.RegisterAssemblyTypes(typeof(MvcApplication).Assembly).PropertiesAutowired();

        builder.RegisterType<WordRepository>().As<IWordRepository>();
        builder.RegisterType<MeaningRepository>().As<IMeaningRepository>();

        return
            builder.Build();
    }
}

Then, initialize it at Application_Start:

protected void Application_Start() {

    //...

    AutofacWebAPI.Initialize();

    //...
}

I hope this helps.

like image 44
tugberk Avatar answered Oct 04 '22 22:10

tugberk