I have been using Ninject in all of my ASP.NET MVC applications till Chris Marisic (@dotnetchris) poked me on twitter about how slow Ninject is. After a little bit of research, I changed it to Autofac which works pretty perfectly.
ASP.NET Web API has nearly the same Dependency Injection support as ASP.NET MVC. As we do not have a built in support for ASP.NET Web API in Autofac (yet), I created a simple one. The implementation is not as straight forward as Ninject and you probably saw the below error if you tried to make it work:
System.InvalidOperationException:
An error occurred when trying to create a controller of type 'TourismDictionary.APIs.Controllers.WordsController'. Make sure that the controller has a parameterless public constructor.
Let’s see how it works:
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 and sets the ServiceResolver with GlobalConfiguration.Configuration.ServiceResolver.SetResolver method which is equivalent to DependencyResolver.SetResolver method:
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(); //deal with your dependencies here builder.RegisterType<WordRepository>().As<IWordRepository>(); builder.RegisterType<MeaningRepository>().As<IMeaningRepository>(); return builder.Build(); } }
Then, initialize it at Application_Start:
public class MvcApplication : System.Web.HttpApplication { private void Configure(HttpConfiguration httpConfiguration) { httpConfiguration.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } protected void Application_Start() { Configure(GlobalConfiguration.Configuration); AutofacWebAPI.Initialize(); } }
There are different ways of doing it but I like this approach.