I'm trying to Inject a dependency into a controller which inherits from Umbraco's RenderMvcController and getting the error
No registration for type RenderMvcController could be found and an implicit registration could not be made. For the container to be able to create RenderMvcController it should have only one public constructor: it has 3. See https://simpleinjector.org/one-constructor for more information.
Below is my code to wire up the DI
var container = new Container();
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
InitializeContainer(container);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
private static void InitializeContainer(Container container)
{
container.Register<ICacheProvider, CacheProvider>(Lifestyle.Transient);
container.Register<ICacheService, CacheService>(Lifestyle.Transient);
}
This is an example of a class receiving the dependency, it inherits from a base class I wrote
public class NewsroomController : BaseRenderMvcController
{
public NewsroomController(ICacheService cacheService) : base(cacheService) { }
The base class extends RenderMvcController which is an Umbraco Controller
public class BaseRenderMvcController : RenderMvcController
{
public ICacheService CacheService { get; set; }
public BaseRenderMvcController(ICacheService cacheService)
{
CacheService = cacheService;
}
}
As you can see the base Umbraco controller does in fact have 3 different constructors
public class RenderMvcController : UmbracoController, IRenderMvcController, IRenderController, IController
{
public RenderMvcController();
public RenderMvcController(UmbracoContext umbracoContext);
public RenderMvcController(UmbracoContext umbracoContext, UmbracoHelper umbracoHelper);
I'm not sure how to get SimpleInjector to place nicely with this controller inherited from Umbraco.
Thanks in advance!
The exception message "No registration for type RenderMvcController could be found and an implicit registration could not be made" means that the RenderMvcController type is requested directly from Simple Injector, while it hasn't been registered. A controller type is usually only requested by the DefaultControllerFactory and it will only request a specific type when it gets a request that has the name of the controller in its url, as in: http:\\localhost\RenderMvc\3.
Since you stated in the comments that the RenderMvcController is only meant to be used as base controller, I find it suspicious that it is actually requested by MVC. I think you should look into that.
But it the use of this controller is really required, you can simply register it in Simple Injector like this:
container.Register<RenderMvcController>(() => new RenderMvcController());
There are ways to override Simple Injector's constructor resolution behavior, but I would advise against doing this, because it is an anti-pattern for components to have multiple constructors. It's wise to don't use a container's auto-wiring behavior on framework types (as explained here), so registering them using a lambda is the advised practice.
Related
I have a Web Api project and using Castle Windsor as the IoC. I have done this quite a few times and honestly I cannot understand why this is not working so here goes everything that I am doing:
Controller on the Web Api project:
Nothing fancy here
public class TestController : ApiController, ITestController
{
... //Currently with its default constructor.
}
Global.asax
public class WebApiApplication : System.Web.HttpApplication
{
private readonly IWindsorContainer container;
public WebApiApplication()
{
container = new WindsorContainer().Install(FromAssembly.Named("DependenciesConfiguration"));
}
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new DiControllerActivator(container));
}
}
DiControllerActivation class
This is the class that is replacing the default controller activator in the Global.asax class.
public class DiControllerActivator : IHttpControllerActivator
{
private readonly IWindsorContainer container;
public DiControllerActivator(IWindsorContainer container)
{
this.container = Argument.NotNull(container, (nameof(container)));
}
public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
//This is the line that fails saying "No component for supporting the service TestController was found.
var controller = (IHttpController)container.Resolve(controllerType);
request.RegisterForDispose(new Release(() => container.Release(controller)));
return controller;
}
}
internal class Release : IDisposable
{
private readonly Action release;
public Release(Action release)
{
this.release = release;
}
public void Dispose()
{
this.release();
}
}
And finally the Web Services Installer
public class ServicesInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes.FromAssemblyNamed("WebServices")
.Where(type => type.Name.EndsWith("Controller"))
.WithService.DefaultInterfaces()
.Configure(c => c.LifestylePerWebRequest()));
}
}
What it is really frustrating is that, like I said, I have donde this before, I went to my previous work to see if I was missing anything and I cannot find anything and this has always worked well.
When running the application after the installer runs I can see that the service is in the container and when it fails saying "No component for supporting the service TestController was found" I can still see the service within the container in the Watch Window.
I am using Castle version 4.0
Thank you for any pointers and help.
As it turns out there is a subtle but critical difference in this code from the other times I did this.. The fact that the TestController is implementing an interface and is registered as such messes up the whole thing.
Since the Create method in the DiActivator class is trying to resolve the controller based on its type and not its default interface the container cannot find it.
One solution is just to remove the interface from the controller or to add the necessary code in the Create method that gets the default interface of the received type and resolves for it.
In my app, there is one interface and two subclasses.
Two subclasses have been registered as services.
My question is how to control which one to get when i use them?
HomeController.cs
public class HomeController : Controller
{
public interface ITestDI
{
}
public class TestDIClass1: ITestDI
{
public TestDIClass1()
{
}
}
public class TestDIClass2 : ITestDI
{
public TestDIClass2()
{
}
}
ITestDI td;
public HomeController(ITestDI _td)
{
this.td = _td; // how to control which ITestDI implementation will injected with constructor injection? With the configuration below, always get TestDIClass2.
}
public IActionResult Index()
{
return View();
}
}
Startup.cs
services.AddScoped<ITestDI, TestDIClass1>();
services.AddScoped<ITestDI, TestDIClass2>(); // it seems like TestDIClass2 has overwrited the TestDIClass1.
There are a few options.
First, you can abandon Auto-Wiring and make the registration using a delegate, as follows:
services.AddScoped<TestDIClass1>();
services.AddScoped<TestDIClass2>();
services.AddTransient<HomeController>(c => new HomeController(
_td: c.GetRequiredService<TestDIClass2>());
Here you register both ITestDI by their concrete type. This allows the delegate for HomeController to request a specific implementation using GetRequiredService<T>.
Hand-wiring such object, however, can become cumbersome, especially when HomeController contains more dependencies, because it would require you to resolve all dependencies manually. So instead, you can make use of MS.DI's ActivatorUtilities.CreateInstance class. It implements a simplified form of MS.DI's Auto-Wiring abilities. The following snippet shows this:
services.AddScoped<TestDIClass1>();
services.AddScoped<TestDIClass2>();
services.AddTransient<HomeController>(c =>
ActivatorUtilities.CreateInstance<HomeController>(
c,
new object[]
{
c.GetRequiredService<TestDIClass2>(),
}));
In this example, HomeController is requested from ActivatorUtilities. The CreateInstance call is supplied an IServiceProvider instance (the c argument) and an array of instances to inject into HomeController's constructor. ActivatorUtilities will match the supplied objects to HomeController's constructor arguments and will resolve all missing arguments from the provided IServiceProvider.
The use of ActivatorUtilities.CreateInstance allows your registration to stay unchanged, even if new arguments are added to HomeController's constructor, for instance:
public HomeController(
ILogger logger, // new argument added
ITestDI td,
IProductService service // another argument added
)
ActivatorUtilities.CreateInstance will figure out that the resolved TestDIClass2 can be mapped to the td constructor argument, and it will resolve ILogger and IProductService from the IServiceProvider.
There are other options available, but these are in your case probably the most likely options, in case you don't want to change your design.
This information is an condensed version of the book Dependency Injection Principles. Practices, and Patterns. That contains a complete chapter on Microsoft.Extensions.DependencyInjection (MS.DI) and about 16 pages on Working with multiple components.
It is possible to register concrete class.
public HomeController(TestDIClass2 _td)
{
this.td = _td; //
}
Since you have registered more than one instances, you have to ask Dependency Injection framework for an IEnumerable<ITestDI> _testDis;
and then you have to iterate trough it
foreach(var instance in _testDis)
{
instance.YourMethod();
}
I am having an interface IValidator which has a generic method Validate and is intended to validate different objects across the application. For now I am validating User's profile and Login credentials. The problem is, when I try to validate profile or Login class, it always calls the method for the profile even when I try to validate Login details. Here's the code:
IValidator
public interface IValidator
{
List<Error> Validate<T>(T request);
}
UserProfileValidator
public class UserProfileValidator : IValidator
{
public List<Error> Validate<T>(T request)
{
//Code for profile validation
}
}
UserLoginValidator
public class UserLoginValidator: IValidator
{
public List<Error> Validate<T>(T request)
{
//Code for login validation
}
}
UserService
private readonly IValidator _validator;
public UserService(IValidator validator)
{
_validator = validator;
}
public async Task<Response> Login(UserDetail userDetail)
{
//this is supposed to validate login details, but validates profile instead
var errors = _validator.Validate(userDetail);
}
public async Task<Response> UpdateProfile(Profile profile)
{
var errors = _validator.Validate(profile);
}
Please guide. Thanks
I'm posting this though it may not be the solution to OP's problem.
Based on what you said you are using AutoFac.
Service:
builder.RegisterType<UserService>().As<IUserService>();
Validators:
builder.RegisterAssemblyTypes(typeof(DependencyBuilder).Assembly).Where(t => t.Name.EndsWith("Validator")).AsImplementedInterfaces().InstancePerLifetimeScope();
Looking at how you register your UserService you are not supplying a specific IValidator parameter to its constructor which I think is the reason why AutoFac keeps using the UserProfileValidator. Logically speaking how will UserService know what implementation of IValidator to use on run-time?
I often use the following to specify parameters to my constructors.
builder
.Register(r => new UserService(r.Resolve<IValidator>()))
.As<IUserService>()
.InstancePerRequest();
But the problem with this is if the DI will resolve for the IValidator it is still not specific.
I would suggest redesigning your code since I don't think your current design allows the UserService to use both UserProfileValidator and UserLoginValidator.
Probably assigning the IValidator per view model would be a better approach so that each view model has their own implementation of IValidator then you could do something like var errors = viewModel.Validate();.
You should change your interface to be:
public interface IValidator<T>
{
List<Error> Validate(T request);
}
You must be using some dependency injection registration with the default DI container or Autofac. Please provide details of how you're doing so.
Your interface is not generic, which means that your dependency injection container is registering several implementations for the same interface and when you inject it it is taking the last implementation.
Change the interface to
public interface IValidator<T>
{
List<Error> Validate(T request);
}
and inject a service IValidator<UserDetail> and another IValidator<Profile> so in essence there are different validators that use the same interface.
Using generics is ok when the implementation is generic, but in your case each validator is different therefore the DI needs to know exactly which one to use.
In autofac you should have something like
builder.RegisterType<UserLoginValidator>().As<IValidator<UserDetails>>();
builder.RegisterType<ProfileValidator>().As<IValidator<Profile>>();
Thanks all of you for the help, it did help me to solve this problem. I used Autofac's keyed services to Register both the validators as IValidator, then resolved by index as needed.
see this:
https://autofaccn.readthedocs.io/en/latest/advanced/keyed-services.html
Does anyone have any example code for getting Umbraco MVC working with the Castle Windsor dependency injection framework? The problem I'm having is getting my surface controllers to use injectable parametised constructors. I know I'm doing something wrong but not sure what.
I have followed the (non-Umbraco) tutorial here - http://docs.castleproject.org/Windsor.Windsor-tutorial-part-four-putting-it-all-together.ashx - which basically means on App_Start I'm running this code:
var container = new WindsorContainer().Install(FromAssembly.This());
var controllerFactory = new MyCustomControllerFactory(container.Kernel);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
Code for MyCustomControllerFactory is below.
Also, my implementation of IWindsorInstaller contains the following:
container.Register(Classes.FromThisAssembly()
.BasedOn<SurfaceController>()
.LifestyleTransient());
The exception I'm getting is 'No component for supporting the service Umbraco.Web.Mvc.RenderMvcController was found', thrown by the GetControllerInstance method below when I call a surface controller with a parametised constructor:
public class TestSurfaceController : SurfaceController
{
public TestSurfaceController(INameService nameService)
{
....
}
}
If anyone has some example code which works I'd really appreciate it. I've wired up Ninject with Umbraco before with no trouble, but on this project I'm tied to Castle Windsor and getting nowhere fast! Thanks in advance.
MyCustomControllerFactory.cs:
public class MyCustomControllerFactory : DefaultControllerFactory
{
private readonly IKernel kernel;
public FastStartControllerFactory(IKernel kernel)
{
this.kernel = kernel;
}
public override void ReleaseController(IController controller)
{
kernel.ReleaseComponent(controller);
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path));
}
return (IController)kernel.Resolve(controllerType);
}
}
I believe your problem is here:
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
This is replacing the controller factory for ALL controllers, including the RenderMVCController, and Castle can't find a matching component for that type.
The trick is to use the FilteredControllerFactoryResolver, which lets Umbraco decide which controller to use based on some criteria that you provide (in this case, whether your container can resolve the controller type). Composition is not as clean as in a straight MVC app (IMHO), but it works.
Here's an (Umbraco 7.x) example of a filtered controller that implements the IFilteredControllerFactory interface:
public class FilteredControllerFactory : ControllerFactory, IFilteredControllerFactory
{
public bool CanHandle(RequestContext request)
{
Type controllerType = GetControllerType(request, request.RouteData.Values["controller"].ToString());
return ApplicationStartup.Container.Kernel.HasComponent(controllerType);
}
}
And the corresponding code to set up composition (using ApplicationEventHandler):
public class ApplicationStartup : ApplicationEventHandler
{
internal static IWindsorContainer Container;
protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
base.ApplicationStarting(umbracoApplication, applicationContext);
Container = new WindsorContainer()
.Install(Configuration.FromAppConfig())
.Register(Classes.FromThisAssembly().BasedOn<IController>().LifestyleTransient());
FilteredControllerFactoriesResolver.Current.InsertType<FilteredControllerFactory>(0);
}
}
This approach should work both for route hijacking and for surface controllers.
Finally, note that if you also want to support injection into API controllers, you'll need to wire this up separately. For example:
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new CompositionRoot(Container.Kernel))
where CompositionRoot is your own Windsor composition root class.
The Gist here may also prove useful.
I've read Kristopher's answer and I've found it interesting, because I didn't know IFilteredControllerFactory and its use. Thanks for sharing.
Anyway, usually in my projects I have a lot of dll containing each its own controllers, so I prefer to register all the controllers in a more general way:
container.Register(
Classes
.FromAssemblyInDirectory(new AssemblyFilter(AssemblyDirectory))
.BasedOn<IController>()
.LifestyleTransient());
where
/// <summary>
/// Local Directory where are present all the assemblies
/// </summary>
static public string AssemblyDirectory
{
//Snippet code from: https://gist.github.com/iamkoch/2344638
get
{
var codeBase = Assembly.GetExecutingAssembly().CodeBase;
var uri = new UriBuilder(codeBase);
var path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path);
}
}
In this way also the Umbraco's RenderMVCController will be mapped and correctly resolved.
Recently I wrote a couple of articles about DI in a Umbraco app:
MVC Controller Factory
Properties Injection in MVC Filters
Hope it can help
I have an ASP.NET page that implements my view and creates the presenter in the page constuctor. Phil Haack's post providing was used as the starting point, and I'll just the examples from the post to illustrate the question.
public partial class _Default : System.Web.UI.Page, IPostEditView {
PostEditController controller;
public _Default()
{
this.controller = new PostEditController(this, new BlogDataService());
}
}
What is the best approach to inject the instance of the BlogDataService? The examples I have found use properties in the Page class for the dependency marked with an attribute which the injection framework resolves.
However, I prefer using the constructor approach for testing purposes.
Does anyone have input or perhaps links to good implementations of the above. I would prefer Ninject, but StructureMap or Windsor would be fine as long as its fluent.
Thanks for any feedback.
In our homegrown MVP-framework we had a typed base-class that all Pages inherited from. The type needed to be of type Presenter (our base presenter class)
In the base-class we then initialized the controller using the IoC-container.
Sample code:
public class EditPage : BasePage<EditController> {
}
public class EditController : Presenter {
public EditController(IService service) { }
}
public class BasePage<T> : Page where T: Presenter
{
T Presenter { get; set; }
public BasePage() {
Presenter = ObjectFactory.GetInstance<T>(); //StructureMap
}
}
Hope this helps!
If you use the Microsoft ServiceLocator, you can apply the service locator design pattern and ask the container for the service.
In your case it would look something like this:
public partial class _Default : System.Web.UI.Page, IPostEditView {
PostEditController controller;
public _Default()
{
var service = ServiceLocator.Current.GetInstance<IBlogDataService>();
this.controller = new PostEditController(this, service);
}
}
ServiceLocator has implementations for Castle Windsor and StructureMap. Not sure about Ninject, but it's trivial to create a ServiceLocator adapter for a new IoC.
I haven't seen a general purpose method for doing constructor injection on webforms. I assume it may be possible via a PageFactory implementation, but since most on the edge right now are moving to MVC rather than webforms, that may not happen.
However, autofac (a DI container I like a lot) has an integration module for ASP.NET WebForms that does property injection without attributes - your code would look like this :
public partial class _Default : System.Web.UI.Page, IPostEditView {
public IBlogDataService DataService{get;set;}
public _Default()
{
}
}
I know this doesn't specifically solve your desire to use constructor injection, but this is the closest I know of.