Introducing the Unity.WebAPI NuGet Package

Whilst the IDependencyResolver interface in the new ASP.NET Web API is identical to its in ASP.NET MVC 3+ compatriot, it is nevertheless in a different namespace and assembly and thus, effectively a different interface. Unity.WebAPI brings the functionality of the popular Unity.Mvc3 package to WebAPI, allowing you to inject dependencies into your ApiControllers via Unity and have IDisposable components automatically disposed of at the end of the request.

There are many articles that already describe the Unity.Mvc3 NuGet package, so there is no need to repeat any of this information here. For background on the design and usage of Unity.Mvc3 (and therefore Unity.WebAPI), please take a look at the followings articles:

Shawn Wildermuth recently pointed out the fact that the new Web API framework that was released in conjunction with MVC4 (beta) introduces a second IDependencyResolver interface. The Web API functionality does not require MVC, so I imagine that the team did not want to add a dependency on an MVC specific type. So now, we have:

System.Web.Http.Services.IDependencyResolver

and

System.Web.Mvc.IDependencyResolver

The interfaces are identical:

public interface IDependencyResolver
{
    object GetService(Type serviceType);
    IEnumerable<object> GetServices(Type serviceType);
}

Unity.WebAPI is a port of the popular Unity.Mvc3 package, specifically for ASP.NET Web API scenarios. No references to any ASP.NET MVC DLLs are necessary, though if you do host your API within an MVC application, Unity.WebAPI will work in harmony with Unity.Mvc3. See below for more details.

To install the package, enter the following command in the package console:

PM> install-package Unity.WebAPI

If you do not already have a reference to Unity, it will be downloaded automatically. As an alternative to the NuGet package, you can download the dll or view the source code on the Unity.WebAPI CodePlex Site.

Unity.WebAPI works in exactly the same way as Unity.Mvc3. The NuGet package will add a boostrapper class at the root of your application. The bootstrapper should contain your Unity registration code. You do not need to add the controllers to Unity, but any other components that are used by the controllers should be added.

private static IUnityContainer BuildUnityContainer()
{
    var container = new UnityContainer();
 
    container.RegisterType<IBlahRepository, BlahRepository>();
 
    return container;
}

If you are registering any components that implement IDisposable such as Entity Framework's DbContext, you will want to make sure that these components get disposed of at the end of the request. This is achieved by registering these components with a HierarchicalLifetimeManager.

private static IUnityContainer BuildUnityContainer()
{
    var container = new UnityContainer();
 
    container
      .RegisterType<IBlahRepository, BlahRepository>()
      .RegisterType<DbContext, BlahDbContext>(new HierarchicalLifetimeManager());
 
    return container;
}

To hook up the bootstrapper, simply add a call to the initialise method from Application_Start() in your global.asax:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
 
    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
 
    BundleTable.Bundles.RegisterTemplateBundles();
 
    Bootstrapper.Initialise();
}

Under the covers, WebAPI will call the custom DependencyResolver whenever all call is made to an ApiController. The resolver will build the controller and all its dependencies and return the instantiated controller to the framework. A dynamically registered HttpModule is used to hook in to the end of the request. The module automatically disposes of all IDisposable instances that are registered as hierarchical.

Unity.WebAPI and Unity.Mvc3 in the same application

You can use Unity.WebAPI and Unity.Mvc3 in the same application but you will need to tweak the bootstrapper file that both libraries use. After installing both NuGet packages, change the Initialise method in the generated bootstrapper.cs file to the following:

public static void Initialise()
{
    var container = BuildUnityContainer();
 
    DependencyResolver.SetResolver(new Unity.Mvc3.UnityDependencyResolver(container));
    GlobalConfiguration.Configuration.ServiceResolver.SetResolver(
      new Unity.WebApi.UnityDependencyResolver(container));
}

Comments

Avatar for silverstar silverstar wrote on 23 May 2012

I am trying to use this. I have my DbContext wrapped in repository class

class Rep1 : RepBase<MyContext>, IRep1

Here MyContext inherits from DbContext and all this code is in a seperate repository assembly. My problem is when i try to register Rep1 using container.registertype<!Rep1, Rep1> im my service assembly, i get a compile error to add reference to EntityFramework which contains DbContext. If i add this reference to service, the error goes off. But i dont want any data access assemblies here.
Why Unity is insisting add this reference?
Is there any workaround for this?

Avatar for Nick Nick wrote on 08 Jun 2012

Thanks for producing this. Is this going to get updated for the RC bits?

Adding this to a new MVC4 WebApi project and tweaking the bootstrapper to allow use along side Unity.Mvc3 (as per your example above) creates the following error:

'System.Web.Http.HttpConfiguration' does not contain a definition for 'ServiceResolver' and no extension method 'ServiceResolver' accepting a first argument of type 'System.Web.Http.HttpConfiguration' could be found (are you missing a using directive or an assembly reference?)

Cheers.

Avatar for Ben Ben wrote on 16 Jun 2012

I'm having the same problem with the RC version. It's broken at the moment. Has anyone got a work-around for this?

Thanks

Avatar for Paul Hiles Paul Hiles wrote on 20 Jun 2012

The latest release (0.10) has been rewritten to work with the RC version of WebAPI. If you are upgrading from 0.9, the NuGet installer will not update the bootstrapper.cs file because it already exists so the easiest thing to do is to copy your Unity registrations somewhere and then delete the bootstrapper.cs file before updating the NuGet package. Then copy your registrations back in.

The perils of working with pre-release software :-)

Let me know if you have any issues.

Avatar for Paul Hiles Paul Hiles wrote on 20 Jun 2012

@silverstar - Yes, when using fluent Unity registrations, you compositional root will require references to all assemblies. This is the case for any IoC container using standard fluent registration rather than any scanning/reflection approach. I think the type safety of code-as-configuration outweighs the fact that you must reference assemblies all the way down the hierarchy but if you prefer, you can always use XML configuration. Also, bear in mind that your compositional root doesn't need to contain your service implementation. A common technique is to keep the compositional root to a bare minimum and move controllers etc. into another assembly.

Avatar for hatstand hatstand wrote on 04 Jul 2012

Newbie question *apologies*: How are you supposed to use the container once its installed. I've created a test project, installed and referenced unity and unity webapi. setup everything as above and registered a simple dummy class in Bootstrapper.Initialise()
e.g.

container.RegisterType<IMyRepository, MyRepository>();

but how am I to use this container to resolve MyRepository (i.e. create an instance of it) from say a controller?

Many thanks for any help.