asp.net-mvc - Autofac MVC 5 RegisterWebApiFilterProvider 导致无法解析的 IOverrideFilter

标签 asp.net-mvc asp.net-web-api autofac

我有一个简单的 MVC 应用程序,我试图在其中添加异常过滤器。为此,我遵循了 Autofac WebAPI Integration documentation我相信这适用于 Autofac.WebApi2 NuGet 包。

首先,我创建了异常过滤器:

public class ErrorLoggingExceptionFilter : IAutofacExceptionFilter
{
    public void OnException(HttpActionExecutedContext context)
    {
        // do something 
    }
}

然后,我将 AutofacControllerConfiguration 属性添加到我的 API Controller 基类中,我希望将异常过滤器应用到该基类中:

[AutofacControllerConfiguration]
public class ApiControllerBase : ApiController  {}

然后我使用 Autofac注册了异常过滤器:

builder.RegisterType<ErrorLoggingExceptionFilter>()
    .AsWebApiExceptionFilterFor<ApiControllerBase>()
    .InstancePerApiRequest();

此时应用程序仍然运行良好,但异常过滤器未运行,因此我注册了 autofac 的过滤器提供程序:

builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);

添加后,我开始收到 500 错误,并出现以下错误:

None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'Autofac.Features.Metadata.Meta<code>1[System.Web.Http.Filters.IOverrideFilter]' can be invoked with the available services and parameters: Cannot resolve parameter 'System.Web.Http.Filters.IOverrideFilter value' of constructor 'Void .ctor(System.Web.Http.Filters.IOverrideFilter, System.Collections.Generic.IDictionary</code>2[System.String,System.Object])'.

我没有在这个项目中使用任何元数据,也不了解 IOverrideFilter 的任何信息。 .

我错过了什么导致我的异常过滤器无法工作?

更新和回复评论

该项目使用 ASP.NET MVC 5.1,使用以下 Autofac 和 WebApi NuGet 版本:

<package id="Autofac" version="3.2.0" targetFramework="net45" />
<package id="Autofac.Mvc5" version="3.2.0" targetFramework="net45" />
<package id="Autofac.WebApi2" version="3.2.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi" version="5.1.1" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.1.1" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.1.1" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.HelpPage" version="5.1.1" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.1.1" targetFramework="net45" />

我在 Autofac 3.3 中看到了相同的结果。

事实证明我可以通过仅调用 RegisterWebApiFilterProvider 来重现它方法,所以虽然我整理了一个完整的示例,但我没有费心包括上面的异常过滤器。可用于重现它的示例项目可在我的 Google Drive 上找到。 。

作为引用,这里是完整的堆栈跟踪:

None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'Autofac.Features.Metadata.Meta`1[System.Web.Http.Filters.IOverrideFilter]' can be invoked with the available services and parameters: Cannot resolve parameter 'System.Web.Http.Filters.IOverrideFilter value' of constructor 'Void .ctor(System.Web.Http.Filters.IOverrideFilter, System.Collections.Generic.IDictionary`2[System.String,System.Object])'.
at
Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters) at
Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters) at
Autofac.Core.Resolving.InstanceLookup.Execute() at
Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters) at
System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() at
System.Linq.Buffer`1..ctor(IEnumerable`1 source) at
System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source) at
Autofac.Features.Collections.CollectionRegistrationSource.<>c__DisplayClass4.<RegistrationsFor>b__0(IComponentContext c, IEnumerable`1 p) at
Autofac.Core.Activators.Delegate.DelegateActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters) at
Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters) at
Autofac.Core.Resolving.InstanceLookup.Execute() at
Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters) at
Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters) at
Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable`1 parameters) at
Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context, IEnumerable`1 parameters) at
Autofac.Integration.WebApi.AutofacWebApiFilterProvider.ResolveControllerScopedOverrideFilter(FilterContext filterContext, String metadataKey) at
Autofac.Integration.WebApi.AutofacWebApiFilterProvider.GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor) at
System.Linq.Enumerable.<SelectManyIterator>d__14`2.MoveNext() at
System.Linq.Buffer`1..ctor(IEnumerable`1 source) at
System.Linq.OrderedEnumerable`1.<GetEnumerator>d__0.MoveNext() at
System.Linq.Buffer`1..ctor(IEnumerable`1 source) at
System.Linq.Enumerable.<ReverseIterator>d__a0`1.MoveNext() at
System.Web.Http.Controllers.HttpActionDescriptor.<RemoveDuplicates>d__3.MoveNext() at
System.Linq.Buffer`1..ctor(IEnumerable`1 source) at
System.Linq.Enumerable.<ReverseIterator>d__a0`1.MoveNext() at
System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) at
System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source) at
System.Web.Http.Controllers.HttpActionDescriptor.InitializeFilterPipeline() at
System.Lazy`1.CreateValue() at
System.Lazy`1.LazyInitValue() at
System.Web.Http.Controllers.HttpActionDescriptor.GetFilterPipeline() at
System.Web.Http.Controllers.HttpActionDescriptor.GetFilterGrouping() at
System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken) at
System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken) at
System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__0.MoveNext()

最佳答案

我会说这是 bug?或者至少是两个 Autofac 功能之间存在意外干扰。

所以这就是正在发生的事情:

  • 因为您正在使用AnyConcreteTypeNotAlreadyRegisteredSource在您的示例中,Autofac 尝试注册并解析未在 Controller 中直接注册的每种类型

  • 调用builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);时Autofac 尝试通过调用 Resolve<IEnumerable<Meta<IOverrideFilter>>> 来定位所有过滤器以及其中已注册的 IOverrideFilters。

  • 但是如果没有IOverrideFilter注册后Autofac对待Meta<IOverrideFilter>由于无法解析,所以 AnyConcreteTypeNotAlreadyRegisteredSource kickc 其中尝试实例化 Meta<IOverrideFilter>并抛出异常。

此问题有多种解决方法:

  • 只是不要使用 AnyConcreteTypeNotAlreadyRegisteredSource尽管这可能不是您想要做的。

  • 注册至少一个过滤器覆盖

     builder.OverrideWebApiActionFilterFor<SomeController>();
    

    所以容器将包含 Meta<IOverrideFilter>所以AnyConcreteTypeNotAlreadyRegisteredSource不会运行此类型。同样,如果您没有过滤器来覆盖,这也不是一个好的解决方案。

  • 你可以告诉AnyConcreteTypeNotAlreadyRegisteredSource它应该解析哪些类型,以便您也可以知道它不应该解析 Meta<T> :

    builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource(
     t => !(t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Meta<>))));
    

关于asp.net-mvc - Autofac MVC 5 RegisterWebApiFilterProvider 导致无法解析的 IOverrideFilter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21743262/

相关文章:

javascript - 初始加载和更新之间的 SignalR

asp.net-mvc - 如何识别 cookie 是否被禁用

c# - 简单注入(inject)器无法在 Web API Controller 中注入(inject)依赖项

asp.net-web-api - 歧义引用 System.Web.Http.RouteParameter

asp.net-mvc - 修改WebApi的ActionFilterAttribute的OnActionExecuted方法中的HttpContent(actionExecutedContext.Response.Content)

c# - Autofac - 一起委托(delegate)工厂 + 类型拦截器

autofac - FxCop 间接引用 System.Core 版本 2.0.5.0

javascript - 将数据从 jQueryUI 对话框表单传递到 Controller

asp.net-mvc - 在Webgrid中将 bool 值显示为复选框

c# - Autofac 属性注入(inject)问题