Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot Inject Dependencies into ASP.NET Web API Controller using Unity

Has anyone had any success running using an IoC container to inject dependencies into ASP.NET WebAPI controllers? I cannot seem to get it to work.

This is what I'm doing now.

In my global.ascx.cs:

    public static void RegisterRoutes(RouteCollection routes)
    {
            // code intentionally omitted 
    }

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);

        IUnityContainer container = BuildUnityContainer();

        System.Web.Http.GlobalConfiguration.Configuration.ServiceResolver.SetResolver(
            t =>
            {
                try
                {
                    return container.Resolve(t);
                }
                catch (ResolutionFailedException)
                {
                    return null;
                }
            },
            t =>
            {
                try
                {
                    return container.ResolveAll(t);
                }
                catch (ResolutionFailedException)
                {
                    return new System.Collections.Generic.List<object>();
                }
            });

        System.Web.Mvc.ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(container)); 

        BundleTable.Bundles.RegisterTemplateBundles();
    }

    private static IUnityContainer BuildUnityContainer()
    {
        var container = new UnityContainer().LoadConfiguration();

        return container;
    }

My controller factory:

public class UnityControllerFactory : DefaultControllerFactory
            {
                private IUnityContainer _container;

                public UnityControllerFactory(IUnityContainer container)
                {
                    _container = container;
                }

                public override IController CreateController(System.Web.Routing.RequestContext requestContext,
                                                    string controllerName)
                {
                    Type controllerType = base.GetControllerType(requestContext, controllerName);

                    return (IController)_container.Resolve(controllerType);
                }
            }

It never seems to look in my unity file to resolve dependencies, and I get an error like:

An error occurred when trying to create a controller of type 'PersonalShopper.Services.WebApi.Controllers.ShoppingListController'. Make sure that the controller has a parameterless public constructor.

at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpControllerContext controllerContext, Type controllerType) at System.Web.Http.Dispatcher.DefaultHttpControllerFactory.CreateInstance(HttpControllerContext controllerContext, HttpControllerDescriptor controllerDescriptor) at System.Web.Http.Dispatcher.DefaultHttpControllerFactory.CreateController(HttpControllerContext controllerContext, String controllerName) at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncInternal(HttpRequestMessage request, CancellationToken cancellationToken) at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)

Controller looks like:

public class ShoppingListController : System.Web.Http.ApiController
    {
        private Repositories.IProductListRepository _ProductListRepository;


        public ShoppingListController(Repositories.IUserRepository userRepository,
            Repositories.IProductListRepository productListRepository)
        {
            _ProductListRepository = productListRepository;
        }
}

My unity file looks like:

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
  <container>
    <register type="PersonalShopper.Repositories.IProductListRepository, PersonalShopper.Repositories" mapTo="PersonalShopper.Implementations.MongoRepositories.ProductListRepository, PersonalShopper.Implementations" />
  </container>
</unity>

Note that I don't have a registration for the controller itself because in previous versions of mvc the controller factory would figure out that the dependencies needed to be resolved.

It seems like my controller factory is never being called.

like image 901
Oved D Avatar asked Mar 02 '12 04:03

Oved D


People also ask

Does ASP NET support dependency injection?

ASP.NET Core supports the dependency injection (DI) software design pattern, which is a technique for achieving Inversion of Control (IoC) between classes and their dependencies.

Does unity use dependency injection?

Using these frameworks, you can take all the monobehaviours of your scene in one single place and let the framework pass the dependencies of these monobehaviours. Extenject Dependency Injection IOC is a very popular and widely used framework for Unity.

What is dependency injection in Web API?

“ - In software development, dependency injection is a technique where one object supplies the needs, or dependencies, of another object.


3 Answers

Figured it out.

For ApiControllers, MVC 4 uses a System.Web.Http.Dispatcher.IHttpControllerFactory and System.Web.Http.Dispatcher.IHttpControllerActivator to create the controllers. If there is no static method to register what the implementation of these they are; when they are resolved, the mvc framework looks for the implementations in the dependency resolver, and if they are not found, uses the default implementations.

I got unity resolution of controller dependencies working by doing the following:

Created a UnityHttpControllerActivator:

public class UnityHttpControllerActivator : IHttpControllerActivator
{
    private IUnityContainer _container;

    public UnityHttpControllerActivator(IUnityContainer container)
    {
        _container = container;
    }

    public IHttpController Create(HttpControllerContext controllerContext, Type controllerType)
    {
        return (IHttpController)_container.Resolve(controllerType);
    }
}

Registered that controller activator as the implementation in the unity container itself:

protected void Application_Start()
{
    // code intentionally omitted

    IUnityContainer container = BuildUnityContainer();
    container.RegisterInstance<IHttpControllerActivator>(new UnityHttpControllerActivator(container));

    ServiceResolver.SetResolver(t =>
       {
         // rest of code is the same as in question above, and is omitted.
       });
}
like image 162
Oved D Avatar answered Oct 30 '22 06:10

Oved D


There is a better solution that works correctly here

http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver

like image 38
CodeKata Avatar answered Oct 30 '22 08:10

CodeKata


You might want to take a look at the Unity.WebApi NuGet package which will sort all this out and also cater for IDisposable components.

see

http://nuget.org/packages/Unity.WebAPI

or

http://www.devtrends.co.uk/blog/introducing-the-unity.webapi-nuget-package

like image 24
Paul Hiles Avatar answered Oct 30 '22 07:10

Paul Hiles