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

Glimpse interferes with ExtensibleActionInvoker on MVC5 #7

Closed
tillig opened this Issue Sep 4, 2015 · 10 comments

Comments

Projects
None yet
2 participants
@tillig
Contributor

tillig commented Sep 4, 2015

From @alexmg on January 22, 2014 14:27

From travis.illig on July 23, 2013 02:14:11

When Glimpse is disabled, the ExtensibleActionInvoker is able to inject parameters into controller actions without issue. When it is enabled, injection fails.

This can be reproduced in the "Remember.Web" sample application in the Autofac solution:

  • Start the application.
  • Click the "Enable Glimpse" link.
  • Click the button to turn Glimpse on.
  • Navigate back to the home page of the demo app.
  • Go to the "ExtensibleActionInvoker Integration Tests" page.
  • Run the "Simple Controller Action Parameter Injection" tests.

An exception will appear; details below.

It appears that Glimpse is attempting to wrap/replace the action invoker as part of its debugging integration. Note the stack trace in the application never runs through Autofac the way it should if ExtensibleActionInvoker is in place.

Related: a similar issue has been reported (appended to Issue #351 ) where the AutofacFilterAttributeFilterProvider is also running into trouble, most likely for similar reasons.

Exception re: ExtensibleActionInvoker below:

Server Error in '/' Application.

Cannot create an instance of an interface.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.MissingMethodException: Cannot create an instance of an interface.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[MissingMethodException: Cannot create an instance of an interface.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +113
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +232
System.Activator.CreateInstance(Type type, Boolean nonPublic) +83
System.Activator.CreateInstance(Type type) +6
System.Web.Mvc.DefaultModelBinder.CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) +183
System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +564
System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +416
Castle.Proxies.DefaultModelBinderProxy.BindModel_callback(ControllerContext controllerContext, ModelBindingContext bindingContext) +44
Castle.Proxies.Invocations.DefaultModelBinder_BindModel.InvokeMethodOnTarget() +191
Castle.DynamicProxy.AbstractInvocation.Proceed() +117
Glimpse.Core.Extensibility.CastleInvocationToAlternateMethodContextAdapter.Proceed() +48
Glimpse.Core.Extensibility.ExecutionTimer.Time(Action action) +195
Glimpse.Core.Extensions.AlternateMethodContextExtensions.TryProceedWithTimer(IAlternateMethodContext context, TimerResult& timerResult) +198
Glimpse.Core.Extensibility.AlternateMethod.NewImplementation(IAlternateMethodContext context) +45
Glimpse.Core.Extensibility.AlternateTypeToCastleInterceptorAdapter.Intercept(IInvocation invocation) +183
Castle.DynamicProxy.AbstractInvocation.Proceed() +483
Castle.Proxies.DefaultModelBinderProxy.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +219
System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) +317
System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +117
System.Web.Mvc.Async.<>c__DisplayClass25.b__1e(AsyncCallback asyncCallback, Object asyncState) +446
System.Web.Mvc.Async.WrappedAsyncResult1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130 System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext, String actionName, AsyncCallback callback, Object state) +302 System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__17(AsyncCallback asyncCallback, Object asyncState) +30 System.Web.Mvc.Async.WrappedAsyncResult1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130
System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state) +382
System.Web.Mvc.Async.WrappedAsyncResult1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130 System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +317 System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +15 System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__2(AsyncCallback asyncCallback, Object asyncState) +71 System.Web.Mvc.Async.WrappedAsyncResult1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +249
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +50
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +301
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155


Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.18045

Original issue: http://code.google.com/p/autofac/issues/detail?id=451

Copied from original issue: autofac/Autofac#451

@tillig

This comment has been minimized.

Show comment
Hide comment
@tillig

tillig Sep 4, 2015

Contributor

From @alexmg on January 22, 2014 14:27

From travis.illig on August 08, 2013 07:52:29

Status: Started
Owner: travis.illig

Contributor

tillig commented Sep 4, 2015

From @alexmg on January 22, 2014 14:27

From travis.illig on August 08, 2013 07:52:29

Status: Started
Owner: travis.illig

@tillig

This comment has been minimized.

Show comment
Hide comment
@tillig

tillig Sep 4, 2015

Contributor

From @alexmg on January 22, 2014 14:27

From travis.illig on August 08, 2013 08:26:23

The trouble appears to be with the way Glimpse replaces the action invoker. The default mechanism to create the action invoker runs through the DependencyResolver, but with Glimpse in place it seems to be a proxy around the default version of the action invoker.

When Glimpse is enabled, the IActionInvoker in place at the point of Controller.BeginExecuteCore is a dynamic proxy Castle.Proxies.AsyncControllerActionInvokerProxy.

The base class for that proxy is System.Web.Mvc.Async.AsyncControllerActionInvoker and the __target on the proxy is correctly Autofac.Integration.Mvc.ExtensibleActionInvoker. There seem to also be two mixins:

  • Glimpse.Core.Framework.CastleDynamicProxyWrapper<System.Web.Mvc.Async.AsyncControllerActionInvoker>
  • Glimpse.Mvc.AlternateType.ActionInvokerStateMixin

What appears to be happening is the target of the dynamic proxy is getting bypassed in favor of calling the base AsyncControllerActionInvoker.GetParameterValue instead of the overridden one in the Autofac invoker.

Guessing this is something to do with the way the dynamic proxies in Glimpse get set up. I think I'm going to have to file something with Glimpse on this one; it doesn't appear to be something we can fix from our end.

Contributor

tillig commented Sep 4, 2015

From @alexmg on January 22, 2014 14:27

From travis.illig on August 08, 2013 08:26:23

The trouble appears to be with the way Glimpse replaces the action invoker. The default mechanism to create the action invoker runs through the DependencyResolver, but with Glimpse in place it seems to be a proxy around the default version of the action invoker.

When Glimpse is enabled, the IActionInvoker in place at the point of Controller.BeginExecuteCore is a dynamic proxy Castle.Proxies.AsyncControllerActionInvokerProxy.

The base class for that proxy is System.Web.Mvc.Async.AsyncControllerActionInvoker and the __target on the proxy is correctly Autofac.Integration.Mvc.ExtensibleActionInvoker. There seem to also be two mixins:

  • Glimpse.Core.Framework.CastleDynamicProxyWrapper<System.Web.Mvc.Async.AsyncControllerActionInvoker>
  • Glimpse.Mvc.AlternateType.ActionInvokerStateMixin

What appears to be happening is the target of the dynamic proxy is getting bypassed in favor of calling the base AsyncControllerActionInvoker.GetParameterValue instead of the overridden one in the Autofac invoker.

Guessing this is something to do with the way the dynamic proxies in Glimpse get set up. I think I'm going to have to file something with Glimpse on this one; it doesn't appear to be something we can fix from our end.

@tillig

This comment has been minimized.

Show comment
Hide comment
@tillig

tillig Sep 4, 2015

Contributor

From @alexmg on January 22, 2014 14:27

From travis.illig on August 08, 2013 08:30:54

It appears this has been an issue for a few months with Glimpse. Others have reported it - issue 328 for them: Glimpse/Glimpse#328

Contributor

tillig commented Sep 4, 2015

From @alexmg on January 22, 2014 14:27

From travis.illig on August 08, 2013 08:30:54

It appears this has been an issue for a few months with Glimpse. Others have reported it - issue 328 for them: Glimpse/Glimpse#328

@tillig

This comment has been minimized.

Show comment
Hide comment
@tillig

tillig Sep 4, 2015

Contributor

From @alexmg on January 22, 2014 14:27

From travis.illig on August 08, 2013 13:59:05

Unfortunately, it looks like it may be a while until Glimpse can get a fix for this. See here for details: Glimpse/Glimpse#328 (comment) The workaround right now is to turn off the Glimpse ActionInvoker functionality, which is outlined in that comment on the GitHub issue.

In the meantime, I'll keep this open and keep watching for a resolution, but again, there's nothing we can do from this end.

Contributor

tillig commented Sep 4, 2015

From @alexmg on January 22, 2014 14:27

From travis.illig on August 08, 2013 13:59:05

Unfortunately, it looks like it may be a while until Glimpse can get a fix for this. See here for details: Glimpse/Glimpse#328 (comment) The workaround right now is to turn off the Glimpse ActionInvoker functionality, which is outlined in that comment on the GitHub issue.

In the meantime, I'll keep this open and keep watching for a resolution, but again, there's nothing we can do from this end.

@tillig

This comment has been minimized.

Show comment
Hide comment
@tillig

tillig Sep 4, 2015

Contributor

From @alexmg on January 22, 2014 14:27

From travis.illig on November 14, 2013 09:49:35

This continues to be a problem with Glimpse 1.8.0 and Glimpse.Mvc5 1.5.1.

Summary: Glimpse interferes with ExtensibleActionInvoker on MVC5 (was: Glimpse interferes with ExtensibleActionInvoker on MVC4)

Contributor

tillig commented Sep 4, 2015

From @alexmg on January 22, 2014 14:27

From travis.illig on November 14, 2013 09:49:35

This continues to be a problem with Glimpse 1.8.0 and Glimpse.Mvc5 1.5.1.

Summary: Glimpse interferes with ExtensibleActionInvoker on MVC5 (was: Glimpse interferes with ExtensibleActionInvoker on MVC4)

@tillig

This comment has been minimized.

Show comment
Hide comment
@tillig

tillig Jul 1, 2016

Contributor

It appears the Glimpse issue has rolled into a larger backlog-related issue: Glimpse/Glimpse#226

Contributor

tillig commented Jul 1, 2016

It appears the Glimpse issue has rolled into a larger backlog-related issue: Glimpse/Glimpse#226

@tillig

This comment has been minimized.

Show comment
Hide comment
@tillig

tillig Jul 18, 2016

Contributor

This may be one we just document and call good. We're going on three years on this one and there's nothing that we in Autofac-land can do about it.

I'll leave this open as a reminder to add docs.

Contributor

tillig commented Jul 18, 2016

This may be one we just document and call good. We're going on three years on this one and there's nothing that we in Autofac-land can do about it.

I'll leave this open as a reminder to add docs.

tillig pushed a commit to autofac/Documentation that referenced this issue Oct 24, 2016

@tillig

This comment has been minimized.

Show comment
Hide comment
@tillig

tillig Oct 24, 2016

Contributor

Docs added.

Contributor

tillig commented Oct 24, 2016

Docs added.

@tillig tillig closed this Oct 24, 2016

alexinea added a commit to dotnetcore-internal/autofac-doc-cn that referenced this issue Dec 29, 2016

@mwpowellhtx

This comment has been minimized.

Show comment
Hide comment
@mwpowellhtx

mwpowellhtx Aug 23, 2017

@tillig I too have been bitten by this very strange error. Not for Glimpse, per se, but in general.

Under debug mode, I see instances to my ctor-injected interfaces just fine. However, the MME occurs nonetheless. Utterly frustrating. What's exactly is the workaround, or we live with broken services? That seems like an unacceptable path forward, if you ask me. In the meantime I'll have a closer look at the documentation, however, the links in the log here are pointing to the commit, not the docs. Hopefully I've got the link correct here.

Couple of observations, from the MVC documentation:

builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>();
builder.InjectActionInvoker();

You don't InjectActionInvoker on the builder. You do so after type registration, presumably RegisterControllers(...).

Additionally, the comment "you can enable action method injection if you desire" is silly. I'm not sure what the interference is, but clearly something is interfering with a model binding expectation, which for me, as with so many others, yields the exceptions:

[MissingMethodException: Cannot create an instance of an interface.]
[MissingMethodException: Cannot create an instance of an interface. Object type 'IMyServiceInterface'.]

Apart from this, otherwise as revealed in debugger, the instances are resolved and presented to my Controller ctor just fine.

Conclusions, the key, I think is this: InjectActionInvoker. Either of the action invokers is probably fine. I am registering the ExtensibleActionInvoker, for example. After that, no MME.

Thank you!

mwpowellhtx commented Aug 23, 2017

@tillig I too have been bitten by this very strange error. Not for Glimpse, per se, but in general.

Under debug mode, I see instances to my ctor-injected interfaces just fine. However, the MME occurs nonetheless. Utterly frustrating. What's exactly is the workaround, or we live with broken services? That seems like an unacceptable path forward, if you ask me. In the meantime I'll have a closer look at the documentation, however, the links in the log here are pointing to the commit, not the docs. Hopefully I've got the link correct here.

Couple of observations, from the MVC documentation:

builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>();
builder.InjectActionInvoker();

You don't InjectActionInvoker on the builder. You do so after type registration, presumably RegisterControllers(...).

Additionally, the comment "you can enable action method injection if you desire" is silly. I'm not sure what the interference is, but clearly something is interfering with a model binding expectation, which for me, as with so many others, yields the exceptions:

[MissingMethodException: Cannot create an instance of an interface.]
[MissingMethodException: Cannot create an instance of an interface. Object type 'IMyServiceInterface'.]

Apart from this, otherwise as revealed in debugger, the instances are resolved and presented to my Controller ctor just fine.

Conclusions, the key, I think is this: InjectActionInvoker. Either of the action invokers is probably fine. I am registering the ExtensibleActionInvoker, for example. After that, no MME.

Thank you!

@tillig

This comment has been minimized.

Show comment
Hide comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment