Autofac.WebApi2 Глобальное действие FILTER FILTER не удалось - PullRequest
0 голосов
/ 01 июня 2018

Проблема, с которой я сталкиваюсь, заключается в том, что 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();
        }
    }
}

Если я выполняю шаги, описанные в официальный сайт Я получаю ошибку, описанную после фрагмента кода:

var builder = new ContainerBuilder();

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

Тип 'MyController' должен быть назначен для 'Autofac.Integration.WebApi.IAutofacActionFilter'.Имя параметра: регистрация

Вот выдержка из контроллера:

//...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 голосов
/ 01 июня 2018

Я вижу, что ваш фильтр ExecutionTimeFilter наследуется от ActionFilterAttribute. Если вы заметили в документах , механизм фильтрации автофака не использует интерфейсы фильтров действий Web API .

Сообщение об исключении несколько сбивает с толку, но я предполагаю,проблема заключается в том, что вы пытаетесь использовать фильтр атрибутов Web API в регистрации, которая предполагает использование интерфейсов фильтра Autofac.

Второй шаг, который вы, возможно, пропустили в документах, - это второй шаг.где он говорит:

Вместо того, чтобы выводить из одного из существующих атрибутов фильтра Web API, ваш класс реализует соответствующий интерфейс фильтра, определенный в интеграции.Фильтр ниже представляет собой фильтр действий, и реализует IAutofacActionFilter вместо System.Web.Http.Filters.IActionFilter.

Я добавил жирный шрифт к наиболее важному месту.

Документы сводятся к следующему:

  • Если вы хотите использовать материал Register(...).AsWebApiActionFilterFor<T>(), вам нужно использовать интерфейсы фильтра Autofac.
  • Если вы хотите использовать стандартный WebФильтры API, вам нужно определить местоположение службы, потому что стандартные фильтры Web API не запускаются через внедрение зависимостей.

В документации подробно объясняется, почему именно Autofac использует пользовательские интерфейсы и почему DIне работает со стандартными фильтрами.

...