After quite a lot of time of writing applications without direct interaction with Databases, lately I’ve been working on a pretty simple ASP.NET Web API project that needs to save data on a database. Despite the simplicity of the application, I faced some interesting problems, which I’m going to write about in a few blog posts over the next weeks.
The first of the problems, which I’m going to write about in this post, is how to configure an ASP.NET Web API application to run within Owin, have its dependencies resolved with Unity, and have Entity Framework DbContext injected via IoC/DI.
Setting up ASP.NET Web API with Owin
The first thing to do is getting the right packages:
- first create a new ASP.NET Web Application, choose the Empty template, and tick the Web API option under “Add folders and core references for”: this will install all the Nuget packages needed for a Web API project, and will setup the folder structure;
- then you need to install the Owin packages and the Owin-Web API “bridge”: by installing the Microsoft.AspNet.WebApi.Owin you’ll get everything you need;
- finally, depending on where/how you want to run the Web API project, you also need the Nuget package for the Owin server you need: download Microsoft.Owin.Host.SystemWeb for starter if you want your app to run within IIS.
Once all the core dependencies are ready, you have to configure the Owin Startup class to fire up Web API: just add a OWIN Startup class from Visual Studio contextual menu and add to the Configuration method the right configuration for Web API.
public class Startup { public void Configuration(IAppBuilder app) { HttpConfiguration config = new HttpConfiguration(); // ... Configure you web api routes app.UseWebApi(config); } }
And Voilá! You have a Web API running with an Owin host.
Adding Unity to Web API within Owin
Next step is adding Unity and configuring it to correctly resolve dependencies in a Web API application. Just add the Unity.AspNet.WebApi Nuget package and all the needed packages and bootstrapping code will be added to the project: in particular it will add two important files:
- UnityConfig class, where the configuration of the Unity container should go
- UnityWebApiActivator class, which is fired up using WebActivator, that registers the unity dependency resolver for Web API (by saving into the GlobalConfiguration.Configuration object)
Unfortunately, if you run you application now (and you have already some dependencies injected into your controllers via IoC/DI) nothing will be injected, simple because the DependencyResolver is still empty, despite being set by the Start method of the UnityWebApiActivator: this works fine in a normal Web API application, but not with Owin, because of the sequence in which the various services are instantiated.
The solution to the problem is pretty easy : just delete the UnityWebApiActivator class and put the same code into the Owin configuration method:
public class Startup { public void Configuration(IAppBuilder app) { HttpConfiguration config = new HttpConfiguration(); // ... Configure you web api routes config.DependencyResolver = new UnityDependencyResolver(UnityConfig.GetConfiguredContainer()); app.UseWebApi(config); } }
For reference, the UnityConfig.GetConfiguredContainer is a static method exposed by the UnityConfig class that has been added with the Unity bootstrapper for ASP.NET Web API nuget package, and looks like the following snippet (the part within region is added by the package, the method RegisterTypes is the one we need to configure our Unity container):
/// <summary> /// Specifies the Unity configuration for the main container. /// </summary> public class UnityConfig { #region Unity Container private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() => { var container = new UnityContainer(); RegisterTypes(container); return container; }); /// <summary> /// Gets the configured Unity container. /// </summary> public static IUnityContainer GetConfiguredContainer() { return container.Value; } #endregion public static void RegisterTypes(IUnityContainer container) { container.RegisterType<IUserRepository, MyUserRepository>(); } }
And now also Unity is wired up correctly and dependencies resolved.
Having Entity Framework DbContext injected via Unity
Let’s get now to the juicy bits: how do we configure Unity to inject EF6 DbContext so that a new context is created with each request? On the internet there are a lot of samples of how to do it, as this is a very common pattern used with all “heavy” ORMs, but all of them use other IoC/DI frameworks, like Ninject, StructureMap and so on, but none with Unity.
Unity doesn’t have a InRequestScope/PerRequest object-scope as most other IoC/DI, but is has something slightly different, called HierarchicalLifetimeManager: it basically creates a “singleton” for each child Unity container created. While being kind of strange, in reality it gives a bit more of flexibility as someone could create child containers for different occasions: which exactly what the Unity bootstrapper for ASP.NET Web API does: it introduces a new kind of DependencyResolver called UnityHierarchicalDependencyResolver that creates a new child container with every begin request.
Taking into consideration all the steps considered so far, here is the final Owin configuration method:
public class Startup { public void Configuration(IAppBuilder app) { HttpConfiguration config = new HttpConfiguration(); // ... Configure you web api routes config.DependencyResolver = new UnityHierarchicalDependencyResolver(UnityConfig.GetConfiguredContainer()); app.UseWebApi(config); } }
and the Unity registration:
public static void RegisterTypes(IUnityContainer container) { container.RegisterType<IUserRepository, MyUserRepository>(); container.RegisterType<MyDBContext>(new HierarchicalLifetimeManager()); }
The last line is important, because if you forget to specify it, a new DbContext will be injected in each of your repositories/command/query objects, you'll not be able to share the context and everything will fall apart.
Wrapping up
Once you solve a few pitfalls (the GlobalConfiguration not being “seen” by the Owin-hosted Web API and the configuration of the “Per Request” scope with Unity), the setup of the infrastructure is pretty easy and is implemented in just 2 lines of code.
Hope this helps, and please let me know if you solved the problem with a different approach or if my solution misses something. And I’ll write a few more posts with my findings in the next weeks.