SimpleInjector 和 Microsoft Webhook ASP.Net Webhook

SimpleInjector and Microsoft Webhook ASP.Net Webhooks

我们已经在我们的 WebAPI 2 项目中成功地使用 Microsoft ASP.Net Webhooks(特别是 Stripe)和 Ninject。最近我们迁移到 SimpleInjector 并且虽然其他一切顺利,但我们无法让这个 webhook 处理器工作。它不断抛出以下异常:System.MissingMethodException: 'No parameterless constructor defined for this object.'

相关堆栈跟踪是:

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]  

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()

我们的 global.asax 看起来像这样:

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));

我们正在像这样注册 WebHook 处理程序:

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

有没有人让它与 SimpleInjector 一起工作?或者有什么想法可能是错的?

在尝试解析具有参数构造函数但一个或多个参数尚未注册因此无法解析的依赖项时会抛出此类异常,从而导致回退到无参数构造函数在某些情况下不存在。

确认您已经注册了 WebHooks 工作所需的所有组件。

解决方案:

IWebhookHandler需要注册为一个集合,所以这样做:

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

而不是:

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

是诀窍!

我通过深入了解 Microsoft Webhook 程序集和 SimpleInjector 的源代码来解决这个问题,发现当 Webhook 程序集请求类型 IWebhookHandler 的所有实例时,SimpleInjector 在其 GetServices 实现中试图找到所有 IEnumerable<IWebhookHandler> 而不是,所以一无所获。