Как отключить глобальный фильтр в ASP.Net MVC выборочно
Я настроил глобальный фильтр для всех моих действий контроллера, в которых я открываю и закрываю сеансы NHibernate. 95% из этих действий нужен доступ к базе данных, но 5% нет. Есть ли простой способ отключить этот глобальный фильтр для тех 5%. Я мог бы пойти другим путем и украсить только те действия, которые нуждаются в базе данных, но это было бы гораздо больше работы.
8 ответов:
вы можете написать атрибут маркера:
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(); }
вы также можете сделать то, что описано в этом удивительном посте:
просто реализовать пользовательский
ExcludeFilterAttribute
а потом обычайExcludeFilterProvider
.чистое решение и отлично работало для меня!
создать пользовательский поставщик фильтр. Напишите класс, который будет реализовывать 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); } }
=============================================================================
В Глобальном.асакс.cspublic 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); }
хотя принятый ответ Дарина Димитрова прекрасен и работает хорошо, но для меня самый простой и эффективный ответ основан здесь.
вам просто нужно добавить логическое свойство к вашему атрибуту и проверить его, как раз перед началом вашей логики:
public class DataAccessAttribute: ActionFilterAttribute { public bool Disable { get; set; } public override void OnActionExecuting(ActionExecutingContext filterContext) { if (Disable) return; // Your original logic for your 95% actions goes here. } }
тогда при ваших 5% действиях просто используйте его так:
[DataAccessAttribute(Disable=true)] public ActionResult Index() { return View(); }
вы можете изменить код фильтра следующим образом:
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"})]
Ну, я думаю, что у меня это работает ASP.NET ядро.
Вот код: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'.
по крайней мере, в настоящее время это довольно просто: чтобы исключить все фильтры действий из действия, просто добавьте OverrideActionFiltersAttribute.
есть аналогичные атрибуты для других фильтров: OverrideAuthenticationAttribute,OverrideAuthorizationAttribute и OverrideExceptionAttribute.
Смотрите также https://www.strathweb.com/2013/06/overriding-filters-in-asp-net-web-api-vnext/