4

Here is my class where dependencies are resolved

namespace TestProj
{
    public static class Bootstrapper
    {
        public static void Run()
        {
            SetAutofacWebAPI();
        }

        private static void SetAutofacWebAPI()
        {
            var builder = new ContainerBuilder();

            builder.RegisterType<UserService>().As<IUserService>().InstancePerRequest();
            builder.RegisterType<Encryption>().As<IEncryption>().InstancePerRequest();

            DependencyResolver.SetResolver(new AutofacDependencyResolver(builder.Build()));
        }
    }
}

In the Global.asax, I have this : Bootstrapper.Run();


Here is my UserService class:

public class UserService : IUserService
{
    private readonly IEncryption _Encryption;

    public UserService(Encryption Encryption)
    {
        _Encryption = Encryption;
    }
    //Rest of the service here
}

the Encryption class is a similar one.


And the controller is here :

public class UserController : Controller
{
    private readonly IUserService _UserService;
    public AccountController(UserService UserService)
    {
        _UserService = UserService;
    }

    public JsonResult GetLoginLogs(int Id)
    {
        var Logs = _UserService.GetLoginLogById(Id);
        return Json(Logs, JsonRequestBehavior.AllowGet);
    }
    //The rest of the controller
}

here is the version info:

Autofac : 3.5.2
MVC : 4.0.40804.0
DOTNET : 4

And then, when try localhost:5000/Account/GetLoginLogs/1 this exception comes up:

No parameterless constructor defined for this object.

Someone please help. I am in seriously in trouble!

4
  • 1
    I think you are confusing how to explicitly inject into the classes. use the interfaces instead of the concrete classes when injecting into the dependent classes Commented Aug 23, 2017 at 15:51
  • 3
    You registered UserService as IUserService. You also failed to register your MVC controllers. Commented Aug 23, 2017 at 15:52
  • 1
    Check, the link, on same lines as Amy above Commented Aug 23, 2017 at 16:27
  • thanks @Amy Your comment was so helpful! Commented Aug 24, 2017 at 6:12

2 Answers 2

4

I think you are confusing how you registered the dependencies.

Update from comments by @Amy:

You also failed to register your MVC controllers

// You can register controllers all at once using assembly scanning...
builder.RegisterControllers(Assembly.GetExecutingAssembly());

Source: documentation

Also use the interfaces instead of the concrete classes when explicitly injecting into the dependent classes as that is what you registered with the container.

public class UserService : IUserService {
    private readonly IEncryption _Encryption;

    public UserService(IEncryption Encryption) {
        _Encryption = Encryption;
    }
    //Rest of the service here
}

public class UserController : Controller {
    private readonly IUserService _UserService;

    public AccountController(IUserService UserService) {
        _UserService = UserService;
    }

    public JsonResult GetLoginLogs(int Id) {
        var Logs = _UserService.GetLoginLogById(Id);
        return Json(Logs, JsonRequestBehavior.AllowGet);
    }
    //The rest of the controller
}
Sign up to request clarification or add additional context in comments.

5 Comments

@PrashanthBenny That is a standard misleading error that the framework throws when it cannot initialize the controller. I agree it is a weird error message.
That's great help Nkosi. Anyway, it's late night In my place. Let me try your solution tomorrow!
It looks like you use MVC, not Web API (controller inherits from Controller, not ApiController), so you should register your controllers with builder.RegisterControllers(Assembly.GetExecutingAssembly());, not builder.RegisterApiControllers(Assembly.GetExecutingAssembly());.
@tdragon you are correct. I copied it from documentation and overlooked that detail. thanks. will update.
Thank you so much... all of you! you save my life this time :)
1

Actually, I believe the exception you get is not misleading if you get deeper into it and analyze the exception message and stack trace. You would find exactly which service could not be found and created by the container - in this case it would be UserService in AccountController (and later, Encryption in UserService as well). The exception with "no parameterless contructor found" simply says that in existing contructor with parameters there is one or more parameters which cannot be resolved by the container, and, because the parameterless constructor is missing, required type cannot be created.

It can also mean you forgot to register your controllers in the container, so the Autofac has no idea it should inject any dependecies into the controllers.

Going further - Autofac is very explicit with the registrations - you can only inject/resolve what you registered at the start up of the application. If you simply use builder.RegisterType<UserService>() - without any As<> you can only inject UserService directly. But when you add .As<>: builder.RegisterType<UserService>().As<IUserService>(), you cannot inject UserService anymore, but IUserService. To keep the possibility to inject UserService you would have to use AsSelf(): builder.RegisterType<UserService>().As<IUserService>().AsSelf(). Then, you can inject both IUserService and UserService. Keep in mind Autofac registration API is fluent, you can amend as many As<> as you want.

In Dependecy Injection world we do not like tidly coupled components, so injecting concrete classes, instead of interfaces - like you did - is not recommended - you should use interfaces wherever it is possible. So your registrations are correct, but you should inject IUserService instead of UserService and IEncryption instead of Encryption in your components. It would ease potential unit testing of these components, allowing you mocking up dependencies easily.

Also, you should register your controllers as well:

builder.RegisterControllers(Assembly.GetExecutingAssembly())‌​;

2 Comments

I just copied the style from nopcommerce project of using the constructor injection.
Thanks for the paragraph explaining about registrations and the use of "As....". It was very helpful.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.