Quantcast
Channel: CleanCode NZ
Viewing all articles
Browse latest Browse all 28

Use Unity container in Controller of Owin Web api 2 hosted on web

$
0
0

Just want to share a few tips about how use unity dependency resolver in a web api2 project through owin.
First tip is for parameter-less resolving, you do not have to get access of unity container at all, it is resolved automatically.
For example you want to inject a Repository to your Product Controller

public class ProductsController : ApiController
    {
        private IRepository _repository;

        public ProductsController(IRepository repository)
        {
            _repository = repository;
        }
    }

If you register the repository in unity it will be resolved automatically

  //Create the unity container

 var container = new UnityContainer();

  container.RegisterType<IRepository, Repository>();

What if you want to register and resolve types based on type names? That is there are many types that implement same interface, for example there are Cat, Dog etc all implement IAnimal, this requires both changes from Register and Resolve

So you will register them as
container.RegisterType(typeof(Cat).Name);
container.RegisterType(typeof(Dog).Name);

When resolving, these types can not be resolved automatically as Repositoy does in the previous example, you need to pass in a parameter when resolving, which is the reason it can not be resolved automatically

Then it comes another problem, how can I get access the UnityContainer within a controller?

One option will be using GlobalConfiguration to retrieve UnityContainer as someone has suggested on the internet.

var container =(IUnityContainer)GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IUnityContainer));

Then to manually resolve a type

var instance = container.Resolve<IAnimal>(typeof (Dog).Name);

Then you will find that GlobalConfiguration is not known, it is because it is from Microsoft.AspNet.WebApi.WebHost so you need to install it.

Then it comes another problem how to set it up, if not careful, most likely you will find DependencyResolver is empty from GlobalConfiguration, you will need to make sure that normal web api config is run before unity DependencyResolver is set, and use Globalconfiguration.Config(config=>{..}) to set DependencyResolver rather than GlobalConfiguation.Configuration=xxx

Setting up web api in owin first

HttpConfiguration config = new HttpConfiguration(); 
            
config.routes = ...
app.UseWebApi(config);

GlobalConfiguration.Config(config=>{
   config.DependencyResolver = new UnityDependencyResolver(container);
});

While GlobalConfiguration option is highly undesirable as it has a lot of issues, first problem is it ties your web api to web hosting, you can not self host it, the right way is still using HttpConfiguration, and let owin to push the HttpConfiguration down to the specific host method either it is web hosted or self hosted, and use ApiController.Config.DependencyResolver to retrieve it rather than hard code Globalconfiguration in controller

  var config = new HttpConfiguration();

  //Create the unity container
  var container = new UnityContainer();
            
  BuildUnityContainer(container);

  //Set the unity container as the default dependency resolver
  config.DependencyResolver = new UnityDependencyResolver(container);

  // .. set the route 
  config.MapHttpAttributeRoutes();

  app.UseWebApi(config);

To retrieve it in controller

var container = (IUnityContainer)Configuration.DependencyResolver.GetService(typeof(IUnityContainer));
var instance = container.Resolve<xxx>(name);

To sum it up, do not use GlobalConfiguration for a unity dependency resolver, use a new HttpConfiguration which is general to web api setup in owin, regardless of it host method.


Viewing all articles
Browse latest Browse all 28

Trending Articles