我为我打开和关闭NHibernate会话的所有控制器操作设置了全局过滤器。这些操作中有95%需要某些数据库访问权限,但5%则不需要。是否有任何简单的方法可以针对这5%禁用此全局过滤器。我可以反过来,只装饰需要数据库的操作,但这将需要更多的工作。
我为我打开和关闭NHibernate会话的所有控制器操作设置了全局过滤器。这些操作中有95%需要某些数据库访问权限,但5%则不需要。是否有任何简单的方法可以针对这5%禁用此全局过滤器。我可以反过来,只装饰需要数据库的操作,但这将需要更多的工作。
Answers:
您可以编写一个标记属性:
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
}
}
然后如果要从全局过滤器中排除某些操作,只需用marker属性装饰它即可:
[SkipMyGlobalActionFilter]
public ActionResult Index()
{
return View();
}
虽然,达林·迪米特洛夫(Darin Dimitrov)接受的答案很好,而且效果很好,但对我而言,这里建立的最简单,最有效的答案。
您只需要在逻辑开始之前向属性添加一个布尔属性并对其进行检查:
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();
}
[DataAccessAttribute(Disable=true,Order=2)]
和filters.Add(new DataAccessAttribute(), 2);
在AspNetCore中,@ darin-dimitrov接受的答案可以进行如下修改:
首先,IFilterMetadata
在marker属性上实现:
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
}
}
创建一个自定义的筛选器提供程序。写一个实现IFilterProvider的类。此IFilterProvider接口具有GetFilters方法,该方法返回需要执行的Filters。
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);
}
好吧,我认为我可以在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”方法中。
至少在今天,这很容易:从动作中排除所有动作过滤器,只需添加OverrideActionFiltersAttribute即可。
其他过滤器也有类似的属性:OverrideAuthenticationAttribute,OverrideAuthorizationAttribute和OverrideExceptionAttribute。
另请参阅https://www.strathweb.com/2013/06/overriding-filters-in-asp-net-web-api-vnext/
您可以这样更改过滤器代码:
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"})]