Autofac.WebApi2全局操作过滤器注入失败

时间:2018-05-31 23:58:25

标签: c# asp.net-web-api2 autofac

我面临的问题是AutoFac不会将预期参数注入相应的过滤器。

我有一个过滤器,用于记录所有控制器中所有方法的执行持续时间。为了完成这项任务,我创建了一个像这样的ActionFilter:

//... other usings here...
using System.Web.Http.Controllers;
using System.Web.Http.Filters;

namespace MyNamespace
{
    internal class ExecutionTimeFilter : ActionFilterAttribute
    {
        public Logger _logger { get; set; }

        public ExecutionTimeFilter(Logger logger)
        {
            _logger = logger;
        }

        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            _logger.Log("Log the starting time + controller + action + etc");
            actionContext.Request.Properties["Stopwatch"] = Stopwatch.StartNew();
        }

        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
        {
            var stopwatch = (Stopwatch)actionExecutedContext.Request.Properties["Stopwatch"];
            _logger.Log("Log the stopwatch.ElapsedMilliseconds + controller + action + etc");
        }
    }
}

我正在注册我的依赖项,如下所示:

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

    var container = new IocConfiguration().Configure(GlobalConfiguration.Configuration);
    var resolver = new AutofacWebApiDependencyResolver(container);

    GlobalConfiguration.Configuration.DependencyResolver = resolver;

    //This is the only way I can get the logger injected
    //This is what ideally I want to avoid
    GlobalConfiguration.Configuration.Filters.Add(new ExecutionTimeFilter(_logger));
}

//IocConfiguration
using Autofac;
using Autofac.Integration.WebApi;
using System.Reflection;
using System.Web.Http;
using System.Web.Mvc;

namespace MyNamespace
{
    internal class IocConfiguration
    {
        public IContainer Configure(HttpConfiguration httpConfiguration)
        {
            var builder = new ContainerBuilder();

            builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

            builder.RegisterInstance(LogManager.GetLogger("LoggerName")).As<Logger>().SingleInstance();

            builder.RegisterWebApiFilterProvider(httpConfiguration);

            return builder.Build();
        }
    }
}

如果我按照official site中描述的步骤操作,我会收到代码段后面描述的错误:

var builder = new ContainerBuilder();

builder.Register(c => new ExecutionTimeFilter(c.Resolve<Logger>()))
    .AsWebApiActionFilterFor<MyController>()
    .InstancePerRequest();
  

类型&#39; MyController&#39;必须可分配给   &#39; Autofac.Integration.WebApi.IAutofacActionFilter&#39 ;.参数名称:   注册

以下是控制器的摘录:

//...Other usings...
using System.Threading.Tasks;
using System.Web.Http;
using System;

namespace MyNamespace.Controllers
{
    public class MyController : ApiController
    {
        private readonly Logger _logger;

        public MarketoController(Logger logger)
        {
            _logger = logger;
        }
    }

    [HttpGet]
    [Route("path/{entityId}")]
    [ValidateEntityId]
    public async Task<IHttpActionResult> Get(int? entityId = null)
    {
        return Ok();
    }
}

我错过了什么?

1 个答案:

答案 0 :(得分:2)

我发现您的过滤器ExecutionTimeFilter继承自ActionFilterAttributeIf you notice in the docs Autofac过滤器机制不使用Web API操作过滤器接口

异常消息有些令人困惑,但我猜测问题是您在注册中尝试使用Web API属性过滤器,希望您使用Autofac过滤器接口。

您可能在文档中遗漏的关键步骤是第二步:

  

您的类不是从现有的Web API过滤器属性派生,而是实现集成中定义的适当过滤器接口。下面的过滤器是一个操作过滤器,实现IAutofacActionFilter而不是System.Web.Http.Filters.IActionFilter

我在那里最重要的地方添加了一些大胆的内容。

文档归结为:

  • 如果您想使用Register(...).AsWebApiActionFilterFor<T>()内容,则需要使用Autofac过滤器接口。
  • 如果您想使用标准Web API过滤器,则需要执行服务定位,因为标准Web API过滤器不会通过依赖注入。

文档中详细解释了为什么Autofac使用自定义界面以及为什么DI不能使用标准过滤器。