Unity.WebApi | Make sure that the controller has a parameterless public constructor
Asked Answered
M

6

6

I am using the Unity.WebApi NuGet package (Unity 4.0.1 and Unity.WebApi 5.2.3) in an ASP.NET WebApi solution. The issue I am facing is that when attempting to run the code, I get the error: Make sure that the controller has a parameterless public constructor. I've searched similar threads here, but I couldn't find any thread that matched my issue.

Please don't just say "Add a parameterless constructor" because it shows you obviously have no clue what IoC is and why that statement makes absolutely no sense and defeats the purpose of IoC. I say this because I saw this on a lot of the other threads I've looked at thus far.

This is my Startup.cs (I'm using Owin, so I do not have a Global.asax):

public void Configuration(IAppBuilder app) {
    var config = new HttpConfiguration();
        config.MapHttpAttributeRoutes();

        // Registering unity stuff
        UnityConfig.RegisterComponents();

        app.UseWebApi(config);
}

This is my UnityConfig.cs:

public static class UnityConfig {
    public static void RegisterComponents() {
        var container = new UnityContainer();
            // Register controller
            container.RegisterType<MyController>();

            // Register interface
            container.RegisterType<IService, Service>();

            GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
    }
}

This is my API Controller:

public class MyController : ApiController {
    private IService service

    public MyController(IService service) {
        this.service = service;
    }

    public IHttpActionResult Get() {
        return Ok("All systems go!");
    }
}

EDIT

I took the using statements out because people are having a hard time understanding that the issue occurs whether or not the using statements are there.

Misconceive answered 21/1, 2016 at 23:56 Comment(5)
Can you share details about the Service class? Are you missing to register any class that is required by the Service class?Archaize
Could it be that your container is being disposed before it is actually being used by MVC? It is not logical that it would throw this error, but maybe. Try taking the var container = new UnityContainer() out of the using block.Phytohormone
Noor There's no details to share. Assume all it does is have a method that prints "Hello World". NightOwl888 I originally did that, so that's not the case. The using came later down the line while trying to figure this issue out. I think it's something wonky going on because it's Owin based, but I'm not sure.Misconceive
@Phytohormone is correct. Take both the unity container and the http configuration out of using statements. They are both getting disposed before the first web request is received.Bevel
@Bevel The same error results whether or not the usings are there.Misconceive
U
18

In my experience there's 2 different scenarios when this occur.

1. Make sure that all parameters in the Service constructor can be resolved. Does it have any dependencies that you haven't registered?

Make sure that the controller has a parameterless public constructor in Unity

2. Make sure to register Unity with Web API. Like so:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Routes and other stuff here...

        var container = IocContainer.Instance; // Or any other way to fetch your container.
        config.DependencyResolver = new UnityDependencyResolver(container);
    }
}

Examples here:

Injecting Dependency into Web API Controller

http://codeclimber.net.nz/archive/2015/02/20/Using-Entity-Framework-within-an-Owin-hosted-Web-API-with.aspx

EDIT 1:

As @NightOwl888 mentioned in the comments, you should not dispose the container. The registrations are registered on the container, and when the container is disposed it will not know how to resolve the dependencies. It may result in the error you are seeing.

EDIT 2:

Since you're using Owin you should be able to do something like this:

    public void Configuration(IAppBuilder appBuilder) 
    { 
      // Configure Web API for self-host. 
      HttpConfiguration config = new HttpConfiguration();
      config.DependencyResolver = new UnityDependencyResolver(
          UnityConfig.GetConfiguredContainer());

      config.Routes.MapHttpRoute( 
                    name: "DefaultApi", 
                    routeTemplate: "api/{controller}/{id}", 
                    defaults: new { id = RouteParameter.Optional } 
                ); 

      appBuilder.UseWebApi(config); 
    }

And update your UnityConfig to this:

    public static class UnityConfig {
       public static IUnityContainer GetConfiguredContainer() {
            var container = new UnityContainer();
            // Register controller
            container.RegisterType<MyController>();

            // Register interface
            container.RegisterType<IService, Service>();

            //This is done in Startup instead.
            //GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
            return container;
    }
}

From this source: How to use DI container when OwinStartup

http://damienbod.com/2013/10/01/self-host-webapi-with-owin-and-unity/

In this method, the HttpConfiguration.DependencyResolver is set to a UnityDependencyResolver instance. This is required so that contructor injection can be used in the webApi controllers. The UnityDependencyResolver class is exactly the same as the Unity.WebApi.UnityDependencyResolver class. Unity.WebApi is not used because this is a self hosted OWIN application.

Unfavorable answered 25/1, 2016 at 11:26 Comment(6)
Please refer to my comments answering NightOwl's question. The using statement came AFTER these issues were happening and it was added during the process of trying to resolve the issue. It does not matter if the using is there, I still see the same issue. Also, assume the service has nothing in it and it's has an empty default constructor. Or if your imagination wants to run wild, assume it has a method that prints "Hello world" with, again, an empty default constructor. In other words, your solutions do not resolve this issue.Misconceive
I see. And you have also registered your DependencyResolver with WebApi (2)? Note that it is a different registration from the regular MVC one. In that case I'm out of ideas.Unfavorable
I've updated with an example for registering Unity for WebAPi with Owin.Unfavorable
Yea, unfortunately I've tried each of your registration methods and some others which involved extending the resolver and registering your own with no luck.Misconceive
Could you update your code with the new registrations? Here's another example for a similiar question. #29611583Unfavorable
@Unfavorable Thanks so much I was having this issue and your second edit worked perfectly for me.Guadalquivir
U
2

Set the DependencyResolver to the HttpConfiguration you created at Startup, not GlobalConfiguration.Configuration and make sure all your services constructor are public, hope this helps

Unclog answered 17/10, 2017 at 12:44 Comment(0)
P
1

Be sure that any nested types which are also injected are being resolved correctly. You will get error message on the controller level even if nested types are resolved incorrectly.

Psalm answered 4/1, 2018 at 10:10 Comment(0)
S
1

One more possible investigation path and cause for this issue. I set breakpoints on my global exception handler and looked into the nested exception property on my exception instance. I got the error does not have an accessible constructor which was true because the type I wanted to inject did have a private constructor (I was refactoring a singleton).

Sprinkle answered 26/9, 2018 at 15:23 Comment(0)
E
1

I'm using Unity of version 4.0.1 and in my case the nested dependency Repository have had two public constructors and Unity hasn't managed to choose the parameterless constructor.

Thus, I've just specified the other one as protected to quickly solve the issue.

    public Repository() : this( ... ) { ... }

    // if need to make public, make sure that the dependency injection container
    // will choose the parameterless constructor;
    // Unity has had issues with that by default
    protected Repository(DbContext context) : base() { ... }

IMO, Unity could have managed to find the "possible to call" constructor - as it had no DbContext (or any derived context) registered.

Please note that by default Unity chooses a constructor with the maximum number of arguments.

So yes, it's also possible to decorate the proper constructor with InjectionConstructorAttribute as it's described here and here - but I even don't have a Unity reference in my data access layer (and don't want to).

Please tell me if such behavior has changed in the later versions.

Extremism answered 25/10, 2018 at 15:50 Comment(0)
H
0

Unfortunately none of these answers worked for me. I had already used the method offered by smoksnes by following the steps described here: https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/dependency-injection

My issue was fixed by using the web api specific unity package (Unity.AspNet.WebApi) rather than the general .net package as described on the Microsoft guide.

Haemolysin answered 17/2, 2019 at 14:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.