Как отключить глобальный фильтр в ASP.Net MVC выборочно

Я установил глобальный фильтр для всех своих действий с контроллером, в которых я открываю и закрываю сеансы NHibernate. 95% этих действий требуют доступа к базе данных, но 5% - нет. Есть ли простой способ отключить этот глобальный фильтр для этих 5%. Я мог бы пойти наоборот и украсить только те действия, которые нужны для базы данных, но это будет гораздо больше работать.

Ответ 1

Вы можете написать атрибут маркера:

public class SkipMyGlobalActionFilterAttribute : Attribute
{
}

а затем в вашем глобальном тесте фильтра действий для присутствия этого маркера в действии:

public class MyGlobalActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.ActionDescriptor.GetCustomAttributes(typeof(SkipMyGlobalActionFilterAttribute), false).Any())
        {
            return;
        }

        // here do whatever you were intending to do
    }
}

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

[SkipMyGlobalActionFilter]
public ActionResult Index()
{
    return View();
}

Ответ 2

Вы также можете сделать то, что описано в этом замечательном сообщении:

Исключить фильтр

Просто выполните пользовательский ExcludeFilterAttribute, а затем пользовательский ExcludeFilterProvider.

Очистите решение и отлично поработали для меня!

Ответ 3

Создайте собственный поставщик фильтра. Напишите класс, который будет реализовывать IFilterProvider. Этот интерфейс IFilterProvider имеет метод GetFilters, который возвращает фильтры, которые необходимо выполнить.

public class MyFilterProvider : IFilterProvider
{
        private readonly List<Func<ControllerContext, object>> filterconditions = new List<Func<ControllerContext, object>>();
        public void Add(Func<ControllerContext, object> mycondition)
        {
            filterconditions.Add(mycondition);
        }

        public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
        {
            return from filtercondition in filterconditions
                   select filtercondition(controllerContext) into ctrlContext
                   where ctrlContext!= null
                   select new Filter(ctrlContext, FilterScope.Global);
        }
}

=============================================== ==============================
В Global.asax.cs

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            MyFilterProvider provider = new MyFilterProvider();
            provider.Add(d => d.RouteData.Values["action"].ToString() != "SkipFilterAction1 " ? new NHibernateActionFilter() : null);
            FilterProviders.Providers.Add(provider);
        }


protected void Application_Start()
{
    RegisterGlobalFilters(GlobalFilters.Filters);
}

Ответ 4

Вы можете изменить свой код фильтра следующим образом:

 public class NHibernateActionFilter : ActionFilterAttribute
    {
        public IEnumerable<string> ActionsToSkip { get; set; }

        public NHibernateActionFilter(params string[] actionsToSkip)
        {
            ActionsToSkip = actionsToSkip;
        }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (null != ActionsToSkip && ActionsToSkip.Any(a => 
String.Compare(a,  filterContext.ActionDescriptor.ActionName, true) == 0))
                {
                    return;
                }
           //here you code
        }
    }

И используйте его:

[NHibernateActionFilter(new[] { "SkipFilterAction1 ", "Action2"})]

Ответ 5

Ну, я думаю, я получил его для ASP.NET Core.
Здесь код:

public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        // Prepare the audit
        _parameters = context.ActionArguments;

        await next();

        if (IsExcluded(context))
        {
            return;
        }

        var routeData = context.RouteData;

        var controllerName = (string)routeData.Values["controller"];
        var actionName = (string)routeData.Values["action"];

        // Log action data
        var auditEntry = new AuditEntry
        {
            ActionName = actionName,
            EntityType = controllerName,
            EntityID = GetEntityId(),
            PerformedAt = DateTime.Now,
            PersonID = context.HttpContext.Session.GetCurrentUser()?.PersonId.ToString()
        };

        _auditHandler.DbContext.Audits.Add(auditEntry);
        await _auditHandler.DbContext.SaveChangesAsync();
    }

    private bool IsExcluded(ActionContext context)
    {
        var controllerActionDescriptor = (Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor)context.ActionDescriptor;

        return controllerActionDescriptor.ControllerTypeInfo.IsDefined(typeof(ExcludeFromAuditing), false) ||
               controllerActionDescriptor.MethodInfo.IsDefined(typeof(ExcludeFromAuditing), false);
    }

Соответствующий код находится в методе IsExcluded.

Ответ 6

Лучший ответ на этот вопрос предоставляется по другому вопросу:

MVC 3 GlobalFilters Exclude