Вопросы по времени жизни созданных Ninject фильтров действий в MVC 3 - PullRequest
5 голосов
/ 15 сентября 2011

Я хотел бы использовать фильтр действий глобальной области действия в моем приложении MVC 3 с использованием Ninject;Тем не менее, я пытаюсь понять время существования этого фильтра, его зависимости и как представить варианты его зависимостей, украшая мои контроллеры и / или методы действия.

Я бы хотел иметь свой тип фильтразависит от объектов, время жизни которых связано с областью запроса, поэтому что-то вроде этого:

public sealed class MyGlobalActionFilter : IActionFilter
{
    public MyGlobalActionFilter(IService1 svc1, IService2 svc2, RequestType reqType)
    {
        // code here
    }

    // IActionFilter implementation here...
}

... и в конфигурации модуля ...

Bind<IService1>().To<ConcreteService1>().InRequestScope()
Bind<IService2>().To<ConcreteService2>().InRequestScope()
BindFilter<MyGlobalActionFilter>(FilterScope.Global, null)
    .WhenControllerHas<RequestTypeAttribute>()
    .WithConstructorArgumentFromControllerAttribute<RequestTypeAttribute>(
        "reqType", 
        x => x.RequestType
    );
BindFilter<MyGlobalActionFilter>(FilterScope.Global, null)
    .WhenActionMethodHas<RequestTypeAttribute>()
    .WithConstructorArgumentFromActionAttribute<RequestTypeAttribute>(
        "reqType", 
        x => x.RequestType
    );
BindFilter<MyGlobalActionFilter>(FilterScope.Global)
    .When(x => true)
    .WithConstructorArgument("reqType", RequestType.Undefined)

И атрибут наконтроллеры и / или методы действия для представления специфичного для приложения «типа запроса»:

[RequestType(RequestType.Type1)]
public sealed class SomeController : Controller { /* code here*/ }

Правильно ли я понимаю, как это должно работать?Будет ли новый экземпляр MyGlobalActionFilter вращаться и вводиться при каждом HTTP-запросе?Если это не сработает, что я упускаю, и что может быть лучше для этой работы?

Кроме того, с введением RequestType синтаксис BindFilter здесь представляется излишне многословным, яЯ не уверен, работает ли он так, как я ожидал, и, похоже, был бы лучший способ внедрить значение по умолчанию RequestType в фильтр действий, если RequestTypeAttribute отсутствует на контроллере или в методе действий.

Пожалуйста, просветите меня!

Ответы [ 2 ]

4 голосов
/ 16 сентября 2011

Я не видел официальной документации от Microsoft, когда и как часто вызывается IFilterProvider.Но, судя по моим наблюдениям, он вызывается один раз для каждого запроса.Это означает, что временные фильтры-привязки в основном связаны с InRequestScope, с той разницей, что они не удаляются Ninject в конце запроса.

Существуют некоторые изменения, которые вы должны сделать:

  • Не наследуйте от ActionFilterAttribute, но вместо этого реализуйте IActionFilter, чтобы предотвратить его случайное использование в качестве атрибута.
  • Переосмыслите использование FilterScope.Global для всех привязок.Я считаю плохой практикой иметь фильтры для действий / контроллеров, работающих с глобальным приоритетом.

Также следует помнить, что фильтр для каждой соответствующей привязки создается и выполняется.Это означает, что в настоящее время один запрос с RequestType.Undefined выполняется для каждого запроса независимо от того, есть ли атрибут в действии или контроллере.Кроме того, для действий и контроллеров выполняются, если на них есть атрибут.

0 голосов
/ 16 сентября 2011

если «System.Web.Mvc.GlobalFilters.Filters» означает то, что вы подразумеваете под «глобальным фильтром действий», то эти фильтры должны создаваться один раз за цикл запуска / остановки приложения, и я сомневаюсь, что контейнер IoC может любого использования здесь. как я вижу из вашего примера кода, вам нужно несколько контроллеров / фильтров действий для изменения свойств глобальных фильтров ... как насчет создания базового фильтра и производных фильтров с изменяющейся логикой?

public abstract class BaseFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        //user some service locator to retrieve IService1, IService2

        //some logic based on RequestType
    }

    protected RequestType { get; set; }
}

public class SomeFilter : BaseFilter
{
    public SomeFilter(RequestType requestType)
    {
        RequestType = requestType;
    }
}
...