Multiple controller constructors when injecting dependencies using Unity.Mvc5 - c#

I'm very new to dependency injection and I've just set up Unity.Mvc5 and has some success with it. But now I face the problem of multiple contructors in my controller class. I already have constructors that handle my UserManager and following tutorials I understand I need another constructor to instantiate my interface. When I do this however, I get the following error:
The type OrganisationController has multiple constructors of length 1. Unable to disambiguate.
A snippet from my controller:
private IPush _pushMessage;
// Here is the problem!
public OrganisationController(IPush pushMessage)
{
_pushMessage = pushMessage;
}
public OrganisationController()
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
{
}
public OrganisationController(UserManager<ApplicationUser> userManager)
{
UserManager = userManager;
var provider = new DpapiDataProtectionProvider("MyApp");
UserManager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(provider.Create("PasswordReset"));
}
public UserManager<ApplicationUser> UserManager { get; private set; }
And my UnityConfig.cs as follows:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<IPush, PushMessage>();
container.RegisterType<IController, OrganisationController>();
container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>();
container.RegisterType<DbContext, ApplicationDbContext>(new HierarchicalLifetimeManager());
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
I am not sure how to tell Unity that I have another constructor being used to implement an interface.

When using DI, constructors are specifically for DI. There is no reason to create alternate constructors (especially on controllers, since the only caller is the ControllerFactory which delegates the call to the DI container).
In fact, using multiple constructors with dependency injection is anti-pattern and should be avoided.
Related: Rebuttal: Constructor over-injection anti-pattern

While I agree with other answer by #NightOwl888. In some cases you may want to have multiple constructors.
Have you tried InjectionConstructor attribute?
[InjectionConstructor]
public OrganisationController(IPush pushMessage)
{
_pushMessage = pushMessage;
}

Related

Property / method injection using Autofac in filter attributes

Trying to use autofac for dependency injection by property.
The instance is always null and there is no dependency injected.
Below is class where the property needs to be injected.
public class UserAccount
{
public IAccountService AccountService { get; set; }
public string Message()
{
return AccountService.Message();
}
}
I have tried three different ways to inject the property but none was successful
Method 1 :
builder.Register(c => {
var result = new UserAccount();
var dep = c.Resolve<IAccountService>();
result.SetDependency(dep);
return result;
});
Method 2 :
builder.RegisterType<UserAccount>().PropertiesAutowired();
Method 3 :
builder.Register(c => new UserAccount { AccountService = c.Resolve<IAccountService>()});
PS : Method injection of above is welcomed.
You should prevent letting your container create data-centric objects, such as your UserAccount entity. This leads to complicated scenarios, such as the one you are in now.
In general, your DI Container should resolve only components—those are the classes in your system that contain the application's behavior, without having any interesting state. Those types of classes are typically long lived, or at least, longer lived than data-centric objects.
Data-centric objects, like entities, can best be created by hand. Not doing so would either lead to entities with big constructors, which easily causes the constructor over-injection code smell. As remedy, you might fall back on using Property Injection, but this causes a code smell of its own, caused Temporal Coupling.
Instead, a better solution is to:
Create entities by hand, opposed to using a DI Container
Supply dependencies to the entity using Method Injection, opposed to using Property Injection
With Method Injection, your UserAccount would as follows:
// This answer assumes that this class is an domain entity.
public class UserAccount
{
public Guid Id { get; set; }
public byte[] PasswordHash { get; set; }
public string Message(IAccountService accountService)
{
if (accountService == null)
throw new ArgumentNullException(nameof(accountService));
return accountService.Message();
}
}
This does move the responsibility of supplying the dependency from the Composition Root to the entity's direct consumer, though. But as discussed above, this is intentional, as the Composition Root in general, and a DI Container in particular, should not be responsible of creating entities and other data-centric, short-lived objects.
This does mean, however, that UserAccount's direct consumer should inject that dependency, and with that, know about existence of the dependency. But as that consumer would be a behavior-centric class, the typical solution is to use Constructor Injection at that stage:
public class UserService : IUserService
{
private readonly IAccountService accountService;
private readonly IUserAccountRepository repo;
public UserService(IAccountService accountService, IUserAccountRepository repo)
{
this.accountService = accountService;
this.repo = repo
}
public void DoSomething(Guid id)
{
UserAccount entity = this.repo.GetById(id);
var message = entity.Message(this.accountService);
}
}
Using method 3, you need to register AccountService, i.e.
builder.RegisterType<AccountService>().As<IAccountService>();
builder.Register(c => new UserAccount { AccountService = c.Resolve<IAccountService>()});
And when you use UserAccount, make sure it is created using Autofac.

Exception in Autofac : No parameterless constructor defined for this object

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!
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
}
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())‌​;

Unity container can't resolve my class

I am trying to implement Unity as an IoC container in a learning project I am working on. I have a layered application, UI->Service->Logic->DataAccess.
It's an MVC Application on the UI side.
In my controller, I have a constructor:
public HomeController()
{
_container = new UnityContainer();
_container.RegisterType<IUserService, UserService>();
_container.RegisterType<IUserLogic, UserLogic>();
}
I then attempt to use the IService in one of my methods:
var service = _container.Resolve<IUserService>();
ReplyDto reply = service.Login(model.Email, model.Password);
But then get this error:
Resolution of the dependency failed, type = "Services.IUserService",
name = "(none)".
I'm not sure why it's saying this. Do I maybe have an issue with MVC and the constructor? Breakpoint on the Resolve line shows that the _container does have the interface I am trying to resolve.
My UserService class has this in the constructor:
private IUserLogic _userlogic;
public UserService(IUserLogic logic)
{
_userlogic = logic;
}
The Logic layer class is defined like this:
public class UserLogic : IUserLogic
{
public ILog _logger;
public IData _data;
public UserLogic(IData data, ILog logger)
{
_data = data;
_logger = logger;
}
I am still in the process of propagating the IoC patter down through all layers.
And finally, the data access layer is defined as:
public class Data :IData
{
Log _logger = new Log();
MyEntities entities;
public Data()
{
entities = new MyEntities();
var instance = System.Data.Entity.SqlServer.SqlProviderServices.Instance;
}
My _container has reference to the IUserLogic interfaces and which concrete class to use.
UserLogic(IData data, ILog logger) - neither IData nor ILog shown as registered in container - so if code is exactly like you have in the post it is the reason why IUserLogic can't be resolved when unity tries to pass argument to UserService(IUserLogic) constructor.
Fix: register all dependencies (recursively)
To achieve that consider:
make sure types with no dependencies has constructors without arguments
register instances instead of types - if that works for your system
make constructors depend on concrete types (as all concrete types by default registered with Unity) - not testable choice...
provide parameters for all non-interface/non class arguments like int/string (How resolve a dependency with unity passing arguments in the constructor?)
You should register container in the Global.asax.cs
public class Global : HttpApplication
{
private void Application_Start(object sender, EventArgs e)
{
IUnityContainer container = new UnityContainer();
container.RegisterType<IUserService, UserService>();
container.RegisterType<IUserLogic, UserLogic>();
UnityDependencyResolver dependencyResolver = new UnityDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = dependencyResolver;
DependencyResolver.SetResolver(dependencyResolver);
}
}

Unity - How to avoid circular reference?

I'm trying to implement dependency injection in my ASP.NET MVC Project using Unity and would like some advice on how to avoid circular references.
At my work we used to implement the service locator pattern, which returned a singleton for each individual service of the application.
public class ServiceWrapper
{
private UserService _userService;
private ProductService _productService;
public UserService User
{
if(_userService == null)
{
_userService = new UserService();
}
return _userService;
}
public ProductService Product
{
if(_productService == null)
{
_productService = new ProductService();
}
return _productService;
}
}
Then in the controller, you could easily access all the services by instantiating the ServiceWrapper and calling methods, like:
private ServiceWrapper _services = new ServiceWrapper();
public ActionResult Index()
{
List<Product> products = _services.Product.GetProducts();
return View(products);
}
Setting up DI using Unity was a breeze. I created a container in Application_Start() (global.asax), like so:
var container = new UnityContainer();
container.RegisterType<IUserService, UserService>(new ContainerControlledLifetimeManager());
container.RegisterType<IProductService, ProductService>(new ContainerControlledLifetimeManager());
container.RegisterType<IServiceWrapper, ServiceWrapper>(new ContainerControlledLifetimeManager());
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
The ServiceWrapper is registered as a Singleton. And implemented constructor injection as follows:
public class ProductController: Controller
{
private IServiceWrapper _services;
public ProductController(IServiceWrapper services)
{
_services = services;
}
public ActionResult Index()
{
List<Product> products = _services.Products.GetProducts();
return View(products);
}
That worked beautifully. But then I came accross the problem.
We like every service to also have a property containing the ServiceWrapper, so that you can easily access the other services from within another, like so:
public class ProductService
{
private IServiceWrapper _services;
public ProductService(IServiceWrapper services)
{
_services = services;
}
public IServiceWrapper Services { get { return _services; } }
}
But when I implemented constructor injection of the ServiceWrapper in the individual services, it resulted in a stackoverflow exception due to circular referencing.
I read that Unity does not support circular referencing. Is there a (solid) way around this. Or should I implement a different architecture? If so, could you recommend a solution?
The way this is typically done is to declare just the services you need and have them ctor-injected. Don't inject a "ServiceWrapper" which just contains everything. Inject what you need. As the container builds up your type you don't have to worry about providing the services. They will be just there.
The development workflow often goes like this:
Add a new dependency injected field
Delete the existing ctor
Regenerate the ctor using Resharper: alt+ins, generate ctor.

Exception is: InvalidOperationException - The current type, is an interface and cannot be constructed. Are you missing a type mapping?

In my bootstrapper:
namespace Conduit.Mam.ClientServices.Common.Initizliaer
{
public static class Initializer
{
private static bool isInitialize;
private static readonly object LockObj = new object();
private static IUnityContainer defaultContainer = new UnityContainer();
static Initializer()
{
Initialize();
}
public static void Initialize()
{
if (isInitialize)
return;
lock (LockObj)
{
IUnityContainer container = defaultContainer;
//registering Unity for MVC
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
//registering Unity for web API
// GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
#region managers
container.RegisterType<ISettingsManager, SettingsManager>();
container.RegisterType<IMamDataManager, MamDataManager>();
container.RegisterType<IAppsDataManager, AppsDataManager>();
#endregion
if (!isInitialize)
{
isInitialize = true;
}
}
}
}
}
in my controller's code:
ISettingsManager sm = mUnityContainer.Resolve<ISettingsManager>();
hovering on mUnityContainer I see ISettingsManager is mapped to SettingsManager
but then I get the error:
Exception is: InvalidOperationException - The current type, is an
interface and cannot be constructed. Are you missing a type mapping?
I have also tried
ISettingsManager sm = (ISettingsManager)mUnityContainer.Resolve<>(typeof(ISettingsManager));
but no use
Just for others (like me) who might have faced the above error. The solution in simple terms.
You might have missed to register your Interface and class (which implements that inteface) registration in your code.
e.g if the error is
"The current type, xyznamespace. Imyinterfacename, is an interface and cannot be constructed. Are you missing a type mapping?"
Then you must register the class which implements the Imyinterfacename in the UnityConfig class in the Register method. using code like below
container.RegisterType<Imyinterfacename, myinterfaceimplclassname>();
You are incorrectly using Dependency Injection. The proper way is to have your controllers take the dependencies they need and leave to the dependency injection framework inject the concrete instances:
public class HomeController: Controller
{
private readonly ISettingsManager settingsManager;
public HomeController(ISettingsManager settingsManager)
{
this.settingsManager = settingsManager;
}
public ActionResult Index()
{
// you could use the this.settingsManager here
}
}
As you can see in this example the controller doesn't know anything about the container. And that's how it should be.
All the DI wiring should happen in your Bootstraper. You should never use container.Resolve<> calls in your code.
As far as your error is concerned, probably the mUnityContainer you are using inside your controller is not the same instance as the one constructed in your Bootstraper. But since you shouldn't be using any container code in your controllers, this shouldn't be a problem anymore.
In my case, I was getting this error despite registering an existing instance for the interface in question.
Turned out, it was because I was using Unity in WebForms by way of the Unity.WebForms Nuget package, and I had specified a Hierarchical Lifetime manager for the dependency I was providing an instance for, yet a Transient lifetime manager for a subsequent type that depended on the previous type - not usually an issue - but with Unity.WebForms, the lifetime managers work a little differently... your injected types seem to require a Hierarchical lifetime manager, but a new container is still created for every web request (because of the architecture of web forms I guess) as explained excellently in this post.
Anyway, I resolved it by simply not specifying a lifetime manager for the types/instances when registering them.
i.e.
container.RegisterInstance<IMapper>(MappingConfig.GetMapper(), new HierarchicalLifetimeManager());
container.RegisterType<IUserContext, UserContext>(new TransientLifetimeManager());
becomes
container.RegisterInstance<IMapper>(MappingConfig.GetMapper());
container.RegisterType<IUserContext, UserContext>();
So that IMapper can be resolved successfully here:
public class UserContext : BaseContext, IUserContext
{
public UserContext(IMapper _mapper) : base(_mapper)
{
}
...
}
In my case, I have used 2 different context with Unitofwork and Ioc container so i see this problem insistanting while service layer try to make inject second repository to DI. The reason is that exist module has containing other module instance and container supposed to gettng a call from not constractured new repository.. i write here for whome in my shooes
May be You are not registering the Controllers.
Try below code:
Step 1.
Write your own controller factory class
ControllerFactory :DefaultControllerFactory by implementing defaultcontrollerfactory
in models folder
public class ControllerFactory :DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
try
{
if (controllerType == null)
throw new ArgumentNullException("controllerType");
if (!typeof(IController).IsAssignableFrom(controllerType))
throw new ArgumentException(string.Format(
"Type requested is not a controller: {0}",
controllerType.Name),
"controllerType");
return MvcUnityContainer.Container.Resolve(controllerType) as IController;
}
catch
{
return null;
}
}
public static class MvcUnityContainer
{
public static UnityContainer Container { get; set; }
}
}
Step 2:Regigster it in BootStrap:
inBuildUnityContainer method
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
//RegisterTypes(container);
container = new UnityContainer();
container.RegisterType<IProductRepository, ProductRepository>();
MvcUnityContainer.Container = container;
return container;
}
Step 3:
In Global Asax.
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
Bootstrapper.Initialise();
ControllerBuilder.Current.SetControllerFactory(typeof(ControllerFactory));
}
And you are done
I had this problem, and the cause was that I had not added the Microsoft.Owin.Host.SystemWeb NuGet package to my project. Although the code in my startup class was correct, it was not being executed.
So if you're trying to solve this problem, put a breakpoint in the code where you do the Unity registrations. If you don't hit it, your dependency injection isn't going to work.
Below code will be helpful for you
public static IUnityContainer Initialise(IUnityContainer container = null)
{
if (container == null)
{
container = new UnityContainer();
}
container.RegisterType<ISettingsManager, SettingsManager>();
container.Resolve<SettingsManager>();
container.RegisterType<SettingsManagerController>(new InjectionProperty("_SettingManagerProvider", new ResolvedParameter<ISettingManager>()));
return container;
}

Categories