ASP.Net MVC에서 전역 필터를 선택적으로 비활성화하는 방법
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
.
깨끗한 솔루션과 나를 위해 잘 작동했습니다!
그러나 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();
}
사용자 지정 필터 공급자를 만듭니다. 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);
}
다음과 같이 필터 코드를 변경할 수 있습니다.
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"})]
적어도 요즘에는 매우 쉽습니다. 모든 작업 필터를 작업에서 제외하려면 OverrideActionFiltersAttribute를 추가하기 만하면 됩니다.
There are similar attributes for other filters: OverrideAuthenticationAttribute, OverrideAuthorizationAttribute and OverrideExceptionAttribute.
See also https://www.strathweb.com/2013/06/overriding-filters-in-asp-net-web-api-vnext/
In AspNetCore, the accepted answer by @darin-dimitrov can be adapted to work as follows:
First, implement IFilterMetadata
on the marker attribute:
public class SkipMyGlobalActionFilterAttribute : Attribute, IFilterMetadata
{
}
Then search the Filters
property for this attribute on the ActionExecutingContext
:
public class MyGlobalActionFilter : IActionFilter
{
public override void OnActionExecuting(ActionExecutingContext context)
{
if (context.Filters.OfType<SkipMyGlobalActionFilterAttribute>().Any())
{
return;
}
// etc
}
}
Well, I think I got it working for ASP.NET Core.
Here's the code:
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);
}
The relevant code is in the 'IsExcluded' method.
'Development Tip' 카테고리의 다른 글
웹 작업자가 할 수없는 서비스 작업자는 무엇을 할 수 있습니까? (0) | 2020.10.31 |
---|---|
DateTime 개체에서만 날짜 또는 시간 가져 오기 (0) | 2020.10.31 |
Sort 및 Pageable 모두에서 Spring 데이터 JPA를 사용하여 데이터를 즉시 쿼리하는 방법은 무엇입니까? (0) | 2020.10.31 |
AngularJS-컨트롤러에서 모듈 상수 가져 오기 (0) | 2020.10.31 |
Postgres.app으로 Mavericks에 pg gem을 설치할 수 없습니다. (0) | 2020.10.30 |