3

I am getting the following exception:

No parameterless constructor defined for this object.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.MissingMethodException: No parameterless constructor defined for this object.

when the framework attempts to construct controllers that do not derive from ApiController, such as my simple HomeController below:

 public class HomeController : Controller
        {
            private IUnityContainer _unityContainer;
            public HomeController(IUnityContainer unityContainer)
            {
                _unityContainer = unityContainer;
            }
            public ActionResult Index()
            {
                return View();
            }
        }

I have the following Boostrapper.cs class defined:

     public static class Boostrapper
        {
            public static void Initialize()
            {
                var container = BuildUnityContainer();
                GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);                          
            }

            private static IUnityContainer BuildUnityContainer()
            {
                var container = new UnityContainer();
                RegisterTypes(container);
                return container;
            }
        }

and Bootstrapper.Initialize() is the last line of code executed within Application_Start of Global.asax.cs?

Exception is not thrown on controller classes that derive from ApiController. Could someone please advise on what I am missing?

Thanks.

Klaus Nji
  • 18,107
  • 29
  • 105
  • 185
  • Your constructor looks strange - why would you pass container as dependency instead of objects that controller actually depends on? (Assuming you've read http://www.asp.net/mvc/tutorials/hands-on-labs/aspnet-mvc-4-dependency-injection which describes steps to configure container and controllers/solve this particular issue) – Alexei Levenkov Nov 26 '13 at 22:36
  • Thanks for the useful link. While true that constructor looks strange, this is not the real problem. Even if, I change the signature to accept some interface, say IService, I still get this error for controllers that do not derive from ApiController. – Klaus Nji Nov 27 '13 at 15:04
  • +1 for edit. You answer (+1) makes perfect sense - I thought that your dependency where not present in container, but indeed you need to configure both dependency resolvers first. (Don't forget to accept your answer too at some point). – Alexei Levenkov Nov 27 '13 at 17:16

3 Answers3

9

Since I am mixing Web API and MVC4 within the same project, I need to also ensure that Unity.WebApi.UnityDependencyResolver and Unity.Mvc4.UnityDependencyResolver are both setup as indicated here.

My Boostrapper.cs which now looks like this:

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

      return container;
    }

 private static IUnityContainer BuildUnityContainer()
    {
      var container = new UnityContainer();
      RegisterTypes(container);
      return container;
    }

    public static void RegisterTypes(IUnityContainer container)
    {
        container.RegisterType<IAgencyResolver, AgencyByNameResolver>("ByName");
        container.RegisterType<IAgencyResolver, AgencyByCdeCodeResolver>("ByCode");
        container.RegisterType<IAgencyRepository, AgenciesRepository>();            
    }

allows both MVC and Web API controllers to be resolved successfully by Unity. To support both, I need NuGet packages Unity.Mvc4 and Unity.WebAPI. Hoping this does not bite me down the road.

Community
  • 1
  • 1
Klaus Nji
  • 18,107
  • 29
  • 105
  • 185
0

I think you need something like this...

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

    // register all your components with the container here
    container.RegisterType<Interface, ClassThatImplementsInterface>();

    return container;
}

This tells your runtime which Concrete class to use when the Interface is present.

EDIT: Based on comments

Basically, you are telling the runtime which concrete type implements your interface(s). So, if you had an interface IRepository and you had two implementations, MockRepo & EFRepo. Your tests would likely pass MockRepo to any constructors that require it, but your DI would be responsible for registering the Interface against a runtime repository, in this case, EFRepo.

Obviously, during some testing of the application (i.e. you browsing the site), you might have the registration of the interface set up to use MockRepo, and then once you're ready to deploy, you can switch back to EFRepo in one location.

Christian Phillips
  • 18,399
  • 8
  • 53
  • 82
  • I have done this for service registrations but this does not solve problem with Controller construction. – Klaus Nji Nov 27 '13 at 15:02
  • @KlausNji, where do you register `IUnityContainer`? – Christian Phillips Nov 27 '13 at 15:06
  • This line in Boostrapper.Initialize(): GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container); Interestingly, exception is not thrown for controllers that derive from ApiController. – Klaus Nji Nov 27 '13 at 15:10
  • I also added container.RegisterType("Home") to RegisterTypes method but no success. – Klaus Nji Nov 27 '13 at 15:17
  • I think I need this line DependencyResolver.SetResolver(new Unity.Mvc.UnityDependencyResolver(container)); as I am mixing WebApi and Mvc within the same project. – Klaus Nji Nov 27 '13 at 15:43
0

For me I had

Unity.WebAPI

Already installed and I was using API controllers and decided to create some views for the API, all I needed to do is

install-package Unity.Mvc

and when promoted for the UnityConfig over write I said no as my Interface to Concrete classes where already functioning as required. This worked without any other work or setup.

My Project is running .NET 4.5.1 MVC 5.1.2. Was very simple and did not effect the API functionality in any way.

leeroya
  • 485
  • 7
  • 12