5
votes

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!

1
So this RenderMvcController is a base class and is not intended to be called directly by the user, as in http://mysite/rendermvc? Who defined this RenderMvcController? You or is it part of another library (such as Umbraco itself)? - Steven
Yeah the RenderMvcController is a controller Umbraco itself provides, it's there to inherited from. - Brooklyn Web Developers
That's why I made BaseRenderMvcController, just so I can have a base I can control, but my base still has to inherit from RenderMvcController to keep Umbraco happy. - Brooklyn Web Developers
I can't really imagine that this RenderMvcController is defined in an Umbraco assembly, because in that case that controller would not have been registered in the container, since you are simply calling RegisterMvcControllers(Assembly.GetExecutingAssembly()), which simply means that only controllers that are defined in your MVC project are registered. Can you find out in what assembly that RenderMvcController lives and what causes it to get registered? - Steven
Hm yeah it's in packages\UmbracoCms.Core.7.4.1\lib\umbraco.dll That's what I get when I try to inspect RenderMvcController. The entire CMS is installed right inside of my main MVC project though. - Brooklyn Web Developers

1 Answers

5
votes

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.