Search code examples
c#asp.net-mvcwebhookssimple-injector

SimpleInjector and Microsoft Webhook ASP.Net Webhooks


We had been successfully using the Microsoft ASP.Net Webhooks (specifically the Stripe one) in our WebAPI 2 project with Ninject. Recently we migrated to SimpleInjector and while everything else went well, we cannot get this webhook processor to work. It keeps throwing the following exception: System.MissingMethodException: 'No parameterless constructor defined for this object.'

The relevant stack traces are:

mscorlib.dll!System.RuntimeType.CreateInstanceSlow(bool publicOnly, bool skipCheckThis, bool fillCache, ref System.Threading.StackCrawlMark stackMark)  Unknown
mscorlib.dll!System.Activator.CreateInstance(System.Type type, bool nonPublic)  Unknown
mscorlib.dll!System.Activator.CreateInstance(System.Type type)  Unknown
Microsoft.AspNet.WebHooks.Common.dll!Microsoft.AspNet.WebHooks.Utilities.TypeUtilities.GetInstances<Microsoft.AspNet.WebHooks.IWebHookHandler>(System.Collections.Generic.IEnumerable<System.Reflection.Assembly> assemblies, System.Func<System.Type, bool> predicate) Unknown
Microsoft.AspNet.WebHooks.Receivers.dll!Microsoft.AspNet.WebHooks.ReceiverServices.GetHandlers()    Unknown
Microsoft.AspNet.WebHooks.Receivers.dll!Microsoft.AspNet.WebHooks.DependencyScopeExtensions.GetHandlers(System.Web.Http.Dependencies.IDependencyScope services = {SimpleInjector.Integration.WebApi.SimpleInjectorWebApiDependencyResolver})    Unknown
Microsoft.AspNet.WebHooks.Receivers.dll!Microsoft.AspNet.WebHooks.WebHookReceiver.ExecuteWebHookAsync(string id = "", System.Web.Http.Controllers.HttpRequestContext context = {System.Web.Http.WebHost.WebHostHttpRequestContext}, System.Net.Http.HttpRequestMessage request = {System.Net.Http.HttpRequestMessage}, System.Collections.Generic.IEnumerable<string> actions = {string[1]}, object data = {Newtonsoft.Json.Linq.JObject})  Unknown
mscorlib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.__Canon>.Start<Microsoft.AspNet.WebHooks.WebHookReceiver.<ExecuteWebHookAsync>d__22>(ref Microsoft.AspNet.WebHooks.WebHookReceiver.<ExecuteWebHookAsync>d__22 stateMachine)  Unknown
Microsoft.AspNet.WebHooks.Receivers.dll!Microsoft.AspNet.WebHooks.WebHookReceiver.ExecuteWebHookAsync(string id, System.Web.Http.Controllers.HttpRequestContext context, System.Net.Http.HttpRequestMessage request, System.Collections.Generic.IEnumerable<string> actions, object data)   Unknown
Microsoft.AspNet.WebHooks.Receivers.Stripe.dll!Microsoft.AspNet.WebHooks.StripeWebHookReceiver.ReceiveAsync(string id = "", System.Web.Http.Controllers.HttpRequestContext context = {System.Web.Http.WebHost.WebHostHttpRequestContext}, System.Net.Http.HttpRequestMessage request = {System.Net.Http.HttpRequestMessage})    Unknown
mscorlib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.__Canon>.Start<Microsoft.AspNet.WebHooks.StripeWebHookReceiver.<ReceiveAsync>d__15>(ref Microsoft.AspNet.WebHooks.StripeWebHookReceiver.<ReceiveAsync>d__15 stateMachine)    Unknown
Microsoft.AspNet.WebHooks.Receivers.Stripe.dll!Microsoft.AspNet.WebHooks.StripeWebHookReceiver.ReceiveAsync(string id, System.Web.Http.Controllers.HttpRequestContext context, System.Net.Http.HttpRequestMessage request)  Unknown
Microsoft.AspNet.WebHooks.Receivers.dll!Microsoft.AspNet.WebHooks.Controllers.WebHookReceiversController.ProcessWebHook(string webHookReceiver = "stripe", string id = "")  Unknown
mscorlib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.__Canon>.Start<Microsoft.AspNet.WebHooks.Controllers.WebHookReceiversController.<ProcessWebHook>d__3>(ref Microsoft.AspNet.WebHooks.Controllers.WebHookReceiversController.<ProcessWebHook>d__3 stateMachine)    Unknown
Microsoft.AspNet.WebHooks.Receivers.dll!Microsoft.AspNet.WebHooks.Controllers.WebHookReceiversController.ProcessWebHook(string webHookReceiver, string id)  Unknown
[Lightweight Function]  
System.Web.Http.dll!System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.GetExecutor.AnonymousMethod__8(object instance, object[] methodParameters) Unknown
System.Web.Http.dll!System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(System.Web.Http.Controllers.HttpControllerContext controllerContext, System.Collections.Generic.IDictionary<string, object> arguments, System.Threading.CancellationToken cancellationToken) Unknown
System.Web.Http.dll!System.Web.Http.Controllers.ApiControllerActionInvoker.InvokeActionAsyncCore(System.Web.Http.Controllers.HttpActionContext actionContext = {System.Web.Http.Controllers.HttpActionContext}, System.Threading.CancellationToken cancellationToken = IsCancellationRequested = false) Unknown
mscorlib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.__Canon>.Start<System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0>(ref System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0 stateMachine)  Unknown
System.Web.Http.dll!System.Web.Http.Controllers.ApiControllerActionInvoker.InvokeActionAsyncCore(System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken) Unknown
System.Web.Http.dll!System.Web.Http.Controllers.ApiControllerActionInvoker.InvokeActionAsync(System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken) Unknown
System.Web.Http.dll!System.Web.Http.Controllers.ActionFilterResult.ExecuteAsync(System.Threading.CancellationToken cancellationToken = IsCancellationRequested = false) Unknown
mscorlib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.__Canon>.Start<System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2>(ref System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2 stateMachine)    Unknown
System.Web.Http.dll!System.Web.Http.Controllers.ActionFilterResult.ExecuteAsync(System.Threading.CancellationToken cancellationToken)   Unknown
System.Web.Http.dll!System.Web.Http.ApiController.ExecuteAsync(System.Web.Http.Controllers.HttpControllerContext controllerContext, System.Threading.CancellationToken cancellationToken)   Unknown
System.Web.Http.dll!System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync(System.Net.Http.HttpRequestMessage request = {System.Net.Http.HttpRequestMessage}, System.Threading.CancellationToken cancellationToken = IsCancellationRequested = false)    Unknown
mscorlib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.__Canon>.Start<System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1>(ref System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1 stateMachine)    Unknown
System.Web.Http.dll!System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) Unknown
System.Net.Http.dll!System.Net.Http.HttpMessageInvoker.SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)  Unknown
System.Web.Http.dll!System.Web.Http.Dispatcher.HttpRoutingDispatcher.SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)    Unknown
System.Net.Http.dll!System.Net.Http.DelegatingHandler.SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)   Unknown
System.Web.Http.Cors.dll!System.Web.Http.Cors.CorsMessageHandler.SendAsync(System.Net.Http.HttpRequestMessage request = {System.Net.Http.HttpRequestMessage}, System.Threading.CancellationToken cancellationToken = IsCancellationRequested = false)   Unknown
mscorlib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.__Canon>.Start<System.Web.Http.Cors.CorsMessageHandler.<SendAsync>d__0>(ref System.Web.Http.Cors.CorsMessageHandler.<SendAsync>d__0 stateMachine)    Unknown
System.Web.Http.Cors.dll!System.Web.Http.Cors.CorsMessageHandler.SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)    Unknown
System.Net.Http.dll!System.Net.Http.DelegatingHandler.SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)   Unknown
System.Web.Http.dll!System.Web.Http.HttpServer.SendAsync(System.Net.Http.HttpRequestMessage request = {System.Net.Http.HttpRequestMessage}, System.Threading.CancellationToken cancellationToken = IsCancellationRequested = false) Unknown
mscorlib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.__Canon>.Start<System.Web.Http.HttpServer.<SendAsync>d__0>(ref System.Web.Http.HttpServer.<SendAsync>d__0 stateMachine)  Unknown
System.Web.Http.dll!System.Web.Http.HttpServer.SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)  Unknown
System.Net.Http.dll!System.Net.Http.HttpMessageInvoker.SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)  Unknown
System.Web.Http.WebHost.dll!System.Web.Http.WebHost.HttpControllerHandler.ProcessRequestAsyncCore(System.Web.HttpContextBase contextBase = {System.Web.HttpContextWrapper}) Unknown
mscorlib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start<System.Web.Http.WebHost.HttpControllerHandler.<ProcessRequestAsyncCore>d__0>(ref System.Web.Http.WebHost.HttpControllerHandler.<ProcessRequestAsyncCore>d__0 stateMachine)    Unknown
System.Web.Http.WebHost.dll!System.Web.Http.WebHost.HttpControllerHandler.ProcessRequestAsyncCore(System.Web.HttpContextBase contextBase)   Unknown
System.Web.dll!System.Web.TaskAsyncHelper.BeginTask(System.Func<System.Threading.Tasks.Task> taskFunc, System.AsyncCallback callback, object state = null)  Unknown
System.Web.dll!System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()  Unknown
System.Web.dll!System.Web.HttpApplication.ExecuteStep(System.Web.HttpApplication.IExecutionStep step = {System.Web.HttpApplication.CallHandlerExecutionStep}, ref bool completedSynchronously = false)  Unknown
System.Web.dll!System.Web.HttpApplication.PipelineStepManager.ResumeSteps(System.Exception error)   Unknown
System.Web.dll!System.Web.HttpApplication.BeginProcessRequestNotification(System.Web.HttpContext context, System.AsyncCallback cb)  Unknown
System.Web.dll!System.Web.HttpRuntime.ProcessRequestNotificationPrivate(System.Web.Hosting.IIS7WorkerRequest wr = {System.Web.Hosting.IIS7WorkerRequest}, System.Web.HttpContext context = {System.Web.HttpContext})    Unknown
System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext = 0x000002226c0521f0, System.IntPtr moduleData, int flags)    Unknown
System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags)   Unknown
[Native to Managed Transition]  
[Managed to Native Transition]  
System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags) Unknown
System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags)   Unknown
[AppDomain Transition]  

And

System.MissingMethodException: No parameterless constructor defined for this object.
at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
at System.Activator.CreateInstance(Type type, Boolean nonPublic)
at System.Activator.CreateInstance(Type type)
at Microsoft.AspNet.WebHooks.Utilities.TypeUtilities.GetInstances[T](IEnumerable`1 assemblies, Func`2 predicate)
at Microsoft.AspNet.WebHooks.ReceiverServices.GetHandlers()
at Microsoft.AspNet.WebHooks.DependencyScopeExtensions.GetHandlers(IDependencyScope services)
at Microsoft.AspNet.WebHooks.WebHookReceiver.<ExecuteWebHookAsync>d__22.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.WebHooks.StripeWebHookReceiver.<ReceiveAsync>d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.WebHooks.Controllers.WebHookReceiversController.<ProcessWebHook>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Threading.Tasks.TaskHelpersExtensions.<CastToObject>d__3`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()

Our global.asax looks like this:

var container = new Container();
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
container.Options.PropertySelectionBehavior = new 
InjectPropertySelectionBehavior();

// Register our stuff

container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.RegisterWebApiControllers(GlobalConfiguration.Configuration);

container.Verify();

GlobalConfiguration.Configuration.DependencyResolver = new 
SimpleInjectorWebApiDependencyResolver(container);
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));

we're registering the WebHook handler like this:

container.Register<IWebHookHandler, StripeWebhookHandler>(Lifestyle.Singleton);

Has anyone gotten this to work with SimpleInjector? Or have any ideas what might be wrong?


Solution

  • Solution:

    IWebhookHandler needs registered as a collection, so doing this:

    container.Collection.Append(typeof(IWebHookHandler), typeof(StripeWebhookHandler));

    instead of:

    container.Register<IWebHookHandler, StripeWebhookHandler>(Lifestyle.Singleton);

    was the trick!

    I figured this out by stepping into the source of both the Microsoft Webhook assembly and SimpleInjector and found that when the Webhook assembly asked for all instances of type IWebhookHandler, SimpleInjector, in its GetServices implementation was trying to find all IEnumerable<IWebhookHandler> instead and so was coming up with nothing.