3
votes

I'm building a very simple set of controllers that I would like to inject dependencies into.

My Web Api project is using .net 4.5.1 (vs2015) and I am using Unity for dependency injection (really really new to Unity).

Here's what I've done:

  1. New Project > ASP.Net web appliction > Web Api Project (no auth)
  2. Tools > Nuget Package Manager > Manage Packages for solution... Search for "Unity.MVC" and install package.
  3. I created the following interface and classes:

    public interface IExample
    {
        void DoWork();
    }
    
    public class ServiceA : IExample
    {
        public void DoWork()
        {
            Console.Write("A");
        }
    }
    
    public class ServiceB : IExample
    {
        public void DoWork()
        {
            Console.Write("B");
        }
    }
    

In my simple controller, I implemented this:

    public class HomeController : Controller
    {
        IExample instance;

        public HomeController(IExample injected)
        {
            instance = injected;
        }

        public ActionResult Index()
        {
            ViewBag.Title = "Home Page";

            return View();
        }
    }

I have these two newly added files from Unity:

enter image description here

I add the following code to the UnityConfig.cs:

    public static void RegisterTypes(IUnityContainer container)
    {
        // NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
        // container.LoadConfiguration();

        // TODO: Register your types here
        //container.RegisterType<IProductRepository, ProductRepository>();

        container.RegisterType<IExample, ServiceA>();
    }

So far - ALL GOOD! I get the DI into the view as expected. Now I want to do the same for my web api controller, like so:

Run - and get this error:

An error occurred when trying to create a controller of type 'ItemController'. Make sure that the controller has a parameterless public constructor.

What have I done wrong? Full exception:

{
   "Message": "An error has occurred.",
   "ExceptionMessage": "An error occurred when trying to create a controller of type 'ItemController'. Make sure that the controller has a parameterless public constructor.",
   "ExceptionType": "System.InvalidOperationException",
   "StackTrace": "   at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)\r\n   at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()",
   "InnerException":    {
      "Message": "An error has occurred.",
      "ExceptionMessage": "Type 'WebApplication2.Controllers.ItemController' does not have a default constructor",
      "ExceptionType": "System.ArgumentException",
      "StackTrace": "   at System.Linq.Expressions.Expression.New(Type type)\r\n   at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType)\r\n   at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator)\r\n   at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)"
   }
}

Thanks in advance!

2
For some reason your edit is marked as committed by anonymous user and it doesn't show up unless approved by one more user.haim770
According to your (still proposed) update, you only installed Unity.Mvc which takes care of integration with MVC's DependecyResolver. For WebApi, you'll have to install the Unity.WebAPI package: nuget.org/packages/Unity.WebAPIhaim770
Show your WebApiConfig.cs and UnityMvcActivator.cs along with any new file that the latest package installation has added.haim770
This actually worked - I had to put the registration of the type code back in when I downloaded the new package! Great!!!! Thanks! :-))))Rob McCabe

2 Answers

4
votes

The ControllerActivator cannot instantiate your HomeController because its constructor is not marked as public (hence it's actually private).

When you are not providing any constructor at all, the compiler automatically creates a public one for you, but since you are providing one (that is not public) you're ending up with no public constructor.

Try this:

public HomeController(IExample injected)
{
    instance = injected;
}

Update:

As per your edit, for integrating Unity with API controllers, you'll have to install the Unity.WebAPI package as well.

More on WebAPI inegration: http://www.asp.net/web-api/overview/advanced/dependency-injection

-1
votes

For using Dependency Injection with unity in web API use below steps.

  1. Install Unity package in your Web API Project. Go to Package manager console paste below command for install Unity

      Install-Package Unity.WebAPI -Version 5.3.0
    
  2. After installing Unity, In the APP_Start folder of Web API, one file added named as UnitConfig.cs, register your service interface and service logic class in that file.

     public static class UnityConfig
      {
        public static void RegisterComponents()
         {
           var container = BuildUnityContainer();
           GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
         }
       private static IUnityContainer BuildUnityContainer()
        {
          var container = new UnityContainer();                    
          container.RegisterType<ICategoryService, CategoryService> ().RegisterType<UnitOfWork>(new HierarchicalLifetimeManager());
          return container;
         }  
      }
    
  3. Register above RegisterComponents() mehod in Application_Start() mehod of Global.asax file of Web API

       protected void Application_Start()
       {
        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        UnityConfig.RegisterComponents();
       }
    
  4. The last step is to inject service interface into the web AIP controller constructor.

      public CategoryController(ICategoryService Iinject)
      {
        this._categoryServices= Iinject;
      }