NHibernateセッションを開いたり閉じたりするすべてのコントローラーアクションに対してグローバルフィルターを設定しました。これらのアクションの95%はデータベースアクセスが必要ですが、5%は必要ありません。 5%でこのグローバルフィルターを無効にする簡単な方法はありますか。他の方法でデータベースを必要とするアクションのみを装飾することもできますが、それははるかに手間がかかります。
マーカー属性を書くことができます:
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
を実装するだけです。
きれいな解決策と私のために素晴らしかった!
とはいえ、ダリン・ディミトロフが受け入れた答えは問題なく、うまく機能していますが、私にとっては、最も簡単で効率的な答えが here でした。
ロジックを開始する直前に、ブールプロパティを属性に追加してチェックするだけです。
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();
}
カスタムフィルタープロバイダーを作成します。 IFilterProviderを実装するクラスを作成します。このIFilterProviderインターフェイスには、実行する必要のあるFiltersを返す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);
}
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
}
}
少なくとも最近では、これは非常に簡単です。アクションからすべてのアクションフィルターを除外するには、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"})]
まあ、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」メソッドにあります。