asp.net-mvc - globales - variable de sesion asp net mvc
Cómo deshabilitar un filtro global en ASP.Net MVC selectivamente (8)
He configurado un filtro global para todas las acciones de mi controlador en las que abro y cierro las sesiones de NHibernate. El 95% de estas acciones necesitan acceso a la base de datos, pero el 5% no. ¿Hay alguna manera fácil de desactivar este filtro global para esos 5%. Podría ir al revés y decorar solo las acciones que necesitan la base de datos, pero eso sería mucho más trabajo.
Al menos hoy en día, esto es bastante fácil: para excluir todos los filtros de acción de una acción, simplemente agregue el atributo OverrideActionFiltersAttribute .
Existen atributos similares para otros filtros: OverrideAuthenticationAttribute , OverrideAuthorizationAttribute y OverrideExceptionAttribute .
Ver también https://www.strathweb.com/2013/06/overriding-filters-in-asp-net-web-api-vnext/
Bueno, creo que lo conseguí trabajando para ASP.NET Core.
Aquí está el código:
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);
}
El código relevante está en el método ''IsExcluded''.
Crea un proveedor de filtros personalizado. Escriba una clase que implementará IFilterProvider. Esta interfaz IFilterProvider tiene un método GetFilters que devuelve los filtros que deben ejecutarse.
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);
}
}
=============================================== ========================
En 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);
}
La mejor respuesta a esto se proporciona en una pregunta diferente:
Podrías escribir un atributo de marcador:
public class SkipMyGlobalActionFilterAttribute : Attribute
{
}
y luego en su prueba de filtro de acción global para la presencia de este marcador en la acción:
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
}
}
y luego, si desea excluir alguna acción del filtro global, simplemente decore con el atributo de marcador:
[SkipMyGlobalActionFilter]
public ActionResult Index()
{
return View();
}
Puedes cambiar tu código de filtro así:
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
}
}
Y úsala:
[NHibernateActionFilter(new[] { "SkipFilterAction1 ", "Action2"})]
Sin embargo, la respuesta aceptada por Darin Dimitrov está bien y funciona bien, pero, para mí, la respuesta más simple y más eficiente fundada here .
Solo necesita agregar una propiedad booleana a su atributo y verificarlo, justo antes de que comience su lógica:
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.
}
}
Luego, con tus acciones del 5%, simplemente utilízalo así:
[DataAccessAttribute(Disable=true)]
public ActionResult Index()
{
return View();
}
También puede hacer lo que se describe en esta impresionante publicación:
Simplemente implemente un ExcludeFilterAttribute
personalizado y luego un ExcludeFilterProvider
personalizado.
¡Solución limpia y funcionó muy bien para mí!