80

我已经为我打开和关闭 NHibernate 会话的所有控制器操作设置了一个全局过滤器。这些操作中的 95% 需要一些数据库访问权限,但 5% 不需要。是否有任何简单的方法可以为这 5% 禁用此全局过滤器。我可以反过来,只装饰需要数据库的操作,但这将是更多的工作。

4

7 回答 7

158

你可以写一个标记属性:

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();
}
于 2012-04-01T08:50:43.663 回答
16

虽然,达林·迪米特洛夫接受的答案很好,而且效果很好,但对我来说,这里找到了最简单和最有效的答案。

您只需要在您的逻辑开始之前向您的属性添加一个布尔属性并对其进行检查:

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();
}
于 2018-05-16T09:10:28.763 回答
8

在 AspNetCore 中,@darin-dimitrov 接受的答案可以适应如下工作:

首先,IFilterMetadata在标记属性上实现:

public class SkipMyGlobalActionFilterAttribute : Attribute, IFilterMetadata
{
}

然后在Filters属性上搜索此属性ActionExecutingContext

public class MyGlobalActionFilter : IActionFilter
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        if (context.Filters.OfType<SkipMyGlobalActionFilterAttribute>().Any())
        {
            return;
        }

        // etc
    }
}
于 2018-11-22T13:30:59.357 回答
4

至少现在,这很容易:要从一个动作中排除所有动作过滤器,只需添加OverrideActionFiltersAttribute

其他过滤器也有类似的属性:OverrideAuthenticationAttributeOverrideAuthorizationAttributeOverrideExceptionAttribute

另请参阅https://www.strathweb.com/2013/06/overriding-filters-in-asp-net-web-api-vnext/

于 2018-02-20T13:01:15.067 回答
2

创建自定义过滤器提供程序。编写一个将实现 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);
}
于 2013-06-07T15:15:35.500 回答
2

好吧,我想我已经为 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”方法中。

于 2017-09-12T11:18:43.200 回答
1

您可以像这样更改过滤器代码:

 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"})]
于 2012-04-01T15:11:46.620 回答