Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No registration for type IEnumerable<IFilterProvider> could be found. #105

Closed
bjm3819 opened this issue Aug 27, 2015 · 19 comments
Closed

No registration for type IEnumerable<IFilterProvider> could be found. #105

bjm3819 opened this issue Aug 27, 2015 · 19 comments
Labels

Comments

@bjm3819
Copy link

bjm3819 commented Aug 27, 2015

Updated from SimpleInjector 3.0.0 to SimpleInjector 3.0.1 is breaking the MVC web site.
There are several types that are not getting registered such as IEnumerable<IFilterProvider> and IEnumerable<ModelValidatorProvider> , etc.

@dotnetjunkie
Copy link
Collaborator

Please update to the SimpleInjector.Integration.Web.Mvc NuGet package version 3.0.2.

@bjm3819
Copy link
Author

bjm3819 commented Aug 27, 2015

My configuration looked like the below after upgrading and that is when stuff broke and I rolled back.
"SimpleInjector" version="3.0.1" targetFramework="net45"
"SimpleInjector.Integration.Web" version="3.0.1" targetFramework="net45"
"SimpleInjector.Integration.Web.Mvc" version="3.0.2" targetFramework="net45"

My current working configuration is (below)
"SimpleInjector" version="3.0.0" targetFramework="net45"
"SimpleInjector.Integration.Web" version="3.0.0" targetFramework="net45"
SimpleInjector.Integration.Web.Mvc" version="3.0.0" targetFramework="net45"

so I'll try to upgrade to the SimpleInjector.Integration.Web.Mvc NuGet package version 3.0.2

@bjm3819
Copy link
Author

bjm3819 commented Aug 27, 2015

so after updating as you suggested the problem comes back to life. Image attached.
capture
Stack Trace:
at SimpleInjector.Container.ThrowMissingInstanceProducerException(Type serviceType)
at SimpleInjector.Container.GetInstanceFromProducer(InstanceProducer instanceProducer, Type serviceType)
at SimpleInjector.Container.GetInstanceForRootType(Type serviceType)
at SimpleInjector.Container.GetInstance(Type serviceType)
at SimpleInjector.Container.GetAllInstances(Type serviceType)
at PMD.Web.Http.SimpleInjectorWebApiDependencyResolver.GetServices(Type serviceType) in c:\Users\bmcgeary.PMDAUTOMATION\Desktop\PMDbTrunk\Libraries\PMD.Web\Http\SimpleInjectorWebApiDependencyResolver.cs:line 65
at System.Web.Http.Services.DefaultServices.GetServices(Type serviceType)
at System.Web.Http.ServicesExtensions.GetServices[TService](ServicesContainer services)
at System.Web.Http.ServicesExtensions.GetModelValidatorProviders(ServicesContainer services)
at System.Web.Http.HttpConfiguration.DefaultInitializer(HttpConfiguration configuration)
at System.Web.Http.HttpConfiguration.EnsureInitialized()
at System.Web.Http.HttpServer.Initialize()
at System.Web.Http.HttpServer.b__b()
at System.Threading.LazyInitializer.EnsureInitializedCore[T](T& target, Boolean& initialized, Object& syncLock, Func1 valueFactory) at System.Threading.LazyInitializer.EnsureInitialized[T](T& target, Boolean& initialized, Object& syncLock, Func1 valueFactory)
at System.Web.Http.HttpServer.EnsureInitialized()
at System.Web.Http.HttpServer.d__0.MoveNext()

@dotnetjunkie
Copy link
Collaborator

I just double checked by pulling in version 3.0.2 of the SimpleInjector.Integration.Web.Mvc NuGet package, but the problem is really solved in that version. If I roll back to 3.0.1 the problem reappears again.

I expect that somehow an old version is cached on your machine. Make sure that the project references version 3.0.2 (you can check this by going to properties after right clicking on the assembly in the project's references list).

@utkuerd
Copy link

utkuerd commented Aug 29, 2015

Upgrading to 3.0.3, my MVC project generated a similar error. Do you think the problem came back?

@dotnetjunkie
Copy link
Collaborator

Can you post a full stack trace of the exception and inner exceptions?

@dotnetjunkie
Copy link
Collaborator

@bjm3819, you are using your own custom IDependencyResolver implementation called PMD.Web.Http.SimpleInjectorWebApiDependencyResolver. This implementation is calling GetAllInstances. The behavior of GetAllInstances has changed in Simple Injector 3.0.

Please use the SimpleInjectorWebApiDependencyResolver class that is provided by the SimpleInjector.Integration.WebApi NuGet package, or change the GetServices method of your custom implementation to the following:

IEnumerable<object> IDependencyScope.GetServices(Type serviceType) {
    Type collectionType = typeof(IEnumerable<>).MakeGenericType(serviceType);
    var services = (IEnumerable<object>)this.ServiceProvider.GetService(collectionType);
    return services ?? Enumerable.Empty<object>();
}

@utkuerd, are you using your own custom implementation as well?

@utkuerd
Copy link

utkuerd commented Aug 29, 2015

Ok, here is some more detail for my case:

I was at 2.5.2 and upgraded it to 3.0.3. I do not have a custom IDependencyResolver implementation. I'm using SimpleInjector with ASP.NET MVC 5.2.0. (Tried upgrading it to 5.2.3 too, same result). There seems nothing related to my code in the stack trace.

I've also applied your workaround at #98 and it was a success. After inserting
container.Options.ResolveUnregisteredCollections = true; problem disapeared. But my container is not empty. I've registered some dependencies. Am I missing something?

Here is my exception details:

SimpleInjector.ActivationException occurred
Message: A first chance exception of type 'SimpleInjector.ActivationException' occurred in SimpleInjector.dll
Additional information: No registration for type IEnumerable could be found.
Stack Trace: 
[ActivationException: No registration for type IEnumerable could be found.]
   SimpleInjector.Container.ThrowMissingInstanceProducerException(Type serviceType) +202
   SimpleInjector.Container.GetInstanceFromProducer(InstanceProducer instanceProducer, Type serviceType) +48
   SimpleInjector.Container.GetInstanceForRootType(Type serviceType) +95
   SimpleInjector.Container.GetInstance(Type serviceType) +99
   SimpleInjector.Container.GetAllInstances(Type serviceType) +139
   System.Web.Mvc.DelegateBasedDependencyResolver.GetServices(Type type) +47
   System.Web.Mvc.DependencyResolverExtensions.GetServices(IDependencyResolver resolver) +116
   System.Web.Mvc.MultiServiceResolver.GetCombined(IList`1 items, IDependencyResolver resolver) +125
   System.Web.Mvc.FilterProviderCollection.get_CombinedItems() +90
   System.Web.Mvc.FilterProviderCollection.GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +194
   System.Web.Mvc.ControllerActionInvoker.GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +62
   System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext, String actionName, AsyncCallback callback, Object state) +436
   System.Web.Mvc.Controller.b__1c(AsyncCallback asyncCallback, Object asyncState, ExecuteCoreState innerState) +82
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +73
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +151
   System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object callbackState, BeginInvokeDelegate`1 beginDelegate, EndInvokeVoidDelegate`1 endDelegate, TState invokeState, Object tag, Int32 timeout, SynchronizationContext callbackSyncContext) +105
   System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state) +588
   System.Web.Mvc.Controller.b__14(AsyncCallback asyncCallback, Object callbackState, Controller controller) +47
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +65
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +151
   System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object callbackState, BeginInvokeDelegate`1 beginDelegate, EndInvokeVoidDelegate`1 endDelegate, TState invokeState, Object tag, Int32 timeout, SynchronizationContext callbackSyncContext) +139
   System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +484
   System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +50
   System.Web.Mvc.MvcHandler.b__4(AsyncCallback asyncCallback, Object asyncState, ProcessRequestState innerState) +98
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +73
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +151
   System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object callbackState, BeginInvokeDelegate`1 beginDelegate, EndInvokeVoidDelegate`1 endDelegate, TState invokeState, Object tag, Int32 timeout, SynchronizationContext callbackSyncContext) +106
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +446
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +88
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +50
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +103
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

@dotnetjunkie
Copy link
Collaborator

There seems nothing related to my code in the stack trace.

@utkuerd, there actually is something related to your code in the stack trace, but you have to know what to look for. Here is the clue:

System.Web.Mvc.DelegateBasedDependencyResolver.GetServices(Type type) +47

The DelegateBasedDependencyResolver is used everytime you register a resolver either using System.Web.Mvc.DependencyResolver.SetResolver(object) or SetResolver(Func<Type, object>, Func<Type, IEnumerable<object>>).

In other words, you are either calling:

DependencyResolver.SetResolver(((IServiceProvider)container).GetService, container.GetAllInstances)

or you are calling:

DependencyResolver.SetResolver(container);

Both are not valid in Simple Injector 3 anymore. The call SetResolver(object) expects to get supplied with a type that contains both a GetInstance and GetAllInstances method. Although Simple Injector 3 contains both methods, GetAllInstances does not match the expectations of MVC, because MVC expects that method to return an empty collection in case no collection is registered. For that same reason, SetResolver(..., container.GetAllInstances) breaks. You will have to change that call to the following:

DependencyResolver.SetResolver(((IServiceProvider)container).GetService, 
    type => (IEnumerable<object>)container.GetService(typeof(IEnumerable<>).MakeGenericType(type))
        ?? Enumerable.Empty<object>());

@utkuerd
Copy link

utkuerd commented Aug 30, 2015

Thanks for clarificaton. I had suspected something breaking down with my v 2.x style use of DelegateBasedDependencyResolver, but I couldn't have figured out how things bind together by examining stack trace. That cleared everything.

A quick question from my curiosity, any plans to provide a mechanism to automatically adapt the new behavior of Container to MVC? For example in the SimpleInjectorDependencyResolver class in MVC Integration package?

@dotnetjunkie
Copy link
Collaborator

@utkuerd: The SimpleInjectorDependencyResolver of the SimpleInjector.Integration.Web.Mvc NuGet package v3.0.2 (and up) adapts to the new behavior of the container, while adhering to the IDependencyResolver contract. So it's best to use the integration package.

@utkuerd
Copy link

utkuerd commented Aug 30, 2015

Oh great, I'll go that way. Thanks for the answers.

@dotnetjunkie
Copy link
Collaborator

Fixed in v3.0.2.

@jabreuar
Copy link

jabreuar commented Aug 25, 2016

I'm using the version 3.2.0.0 and I'm having the same error:

No registration for type IEnumerable<IFilterProvider> could be found.

Stack Trace:

[ActivationException: No registration for type IEnumerable<IFilterProvider> could be found.]
SimpleInjector.Container.ThrowMissingInstanceProducerException(Type serviceType) +151
SimpleInjector.Container.GetInstanceForRootType(Type serviceType) +110
SimpleInjector.Container.GetInstance(Type serviceType) +75
SimpleInjector.Container.GetAllInstances(Type serviceType) +98
System.Web.Mvc.DependencyResolverExtensions.GetServices(IDependencyResolver resolver) +68
System.Web.Mvc.MultiServiceResolver.GetCombined(IList`1 items, IDependencyResolver resolver) +86
System.Web.Mvc.FilterProviderCollection.get_CombinedItems() +41
System.Web.Mvc.FilterProviderCollection.GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +65
System.Web.Mvc.ControllerActionInvoker.GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +52
System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext, String actionName, AsyncCallback callback, Object state) +238
System.Web.Mvc.Controller.<BeginExecuteCore>b__1c(AsyncCallback asyncCallback, Object asyncState, ExecuteCoreState innerState) +42
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +67
System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +170
System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state) +897
System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +170
System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +711
System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__4(AsyncCallback asyncCallback, Object asyncState, ProcessRequestState innerState) +94
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +67
System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +170
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +575
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +921
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +137

@dotnetjunkie
Copy link
Collaborator

@jabreuar, what IDependencyResolver did you register? Can you show the code to reproduce?

@anakic
Copy link

anakic commented Oct 13, 2016

I'm having the same issue as @jabreuar. My registration is extremely simple:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    GlobalConfiguration.Configure(WebApiConfig.Register);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);

    //IOC
    Container container = new Container();
    container.Register<IIdentityProvider, LoggedOnUserIdentity>();
    DependencyResolver.SetResolver(container);
}

@anakic
Copy link

anakic commented Oct 13, 2016

Woops, I figured out my problem. The last line is supposed to be:

DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));

I wonder why the compiler let me pass the container object, it doesn't implement IDependencyResolver as far as I can see.

@dotnetjunkie
Copy link
Collaborator

I wonder why the compiler let me pass the container object

The MVC designers tried to be smart and implemented some sort of duck typing. When the supplied object contains a GetInstance and GetAllInstances method, MVC will simply call those methods using reflection. Yuck.

In Simple Injector v3 however, the behavior of GetAllInstances changed. We now stop returning unregistered collections, but throw an exception instead. This is why you should use the SimpleInjectorDependencyResolver instead of passing in the container object.

@anakic
Copy link

anakic commented Oct 13, 2016

Yeah, it's very strange. Global.asax, in general, has some crazy dynamic compilation magic going on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants