c# .net asp.net-mvc

c# - ¿Cómo puedo comprobar la presencia de un filtro de acción con argumentos de constructor?



.net asp.net-mvc (3)

Bueno, ha dado un buen primer paso al reconocer que Web.config es solo otra dependencia y envolverlo en un ConfigProvider para inyectar es una excelente solución.

Pero se está tropezando con uno de los problemas de diseño de MVC: a saber, para que sea compatible con DI, los atributos solo deberían proporcionar metadatos, pero nunca definir realmente el comportamiento . Este no es un problema con su enfoque de prueba, es un problema con el enfoque del diseño del filtro.

Como se señaló en la publicación, puede solucionar este problema dividiendo su atributo de filtro de acción en 2 partes.

  1. Un atributo que no contiene ningún comportamiento para marcar sus controladores y métodos de acción.
  2. Una clase IActionFilter DI que implementa IActionFilter y contiene el comportamiento deseado.

El enfoque es utilizar el IActionFilter para probar la presencia del atributo y luego ejecutar el comportamiento deseado. El filtro de acción puede suministrarse con todas las dependencias y luego inyectarse cuando la aplicación está compuesta.

IConfigProvider provider = new WebConfigProvider(); IActionFilter filter = new MaxLengthActionFilter(provider); GlobalFilters.Filters.Add(filter);

NOTA: Si necesita que cualquiera de las dependencias del filtro tenga una vida útil más corta que singleton, deberá usar un GlobalFilterProvider como en esta respuesta .

La implementación de MaxLengthActionFilter se vería así:

public class MaxLengthActionFilter : IActionFilter { public readonly IConfigProvider configProvider; public MaxLengthActionFilter(IConfigProvider configProvider) { if (configProvider == null) throw new ArgumentNullException("configProvider"); this.configProvider = configProvider; } public void OnActionExecuted(ActionExecutedContext filterContext) { var attribute = this.GetMaxLengthAttribute(filterContext.ActionDescriptor); if (attribute != null) { var maxLength = attribute.MaxLength; // Execute your behavior here, and use the configProvider as needed } } public void OnActionExecuting(ActionExecutingContext filterContext) { var attribute = this.GetMaxLengthAttribute(filterContext.ActionDescriptor); if (attribute != null) { var maxLength = attribute.MaxLength; // Execute your behavior here, and use the configProvider as needed } } public MaxLengthAttribute GetMaxLengthAttribute(ActionDescriptor actionDescriptor) { MaxLengthAttribute result = null; // Check if the attribute exists on the controller result = (MaxLengthAttribute)actionDescriptor .ControllerDescriptor .GetCustomAttributes(typeof(MaxLengthAttribute), false) .SingleOrDefault(); if (result != null) { return result; } // NOTE: You might need some additional logic to determine // which attribute applies (or both apply) // Check if the attribute exists on the action method result = (MaxLengthAttribute)actionDescriptor .GetCustomAttributes(typeof(MaxLengthAttribute), false) .SingleOrDefault(); return result; } }

Y, su atributo que no debe contener ningún comportamiento debería verse así:

// This attribute should contain no behavior. No behavior, nothing needs to be injected. [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)] public class MaxLengthAttribute : Attribute { public MaxLengthAttribute(int maxLength) { this.MaxLength = maxLength; } public int MaxLength { get; private set; } }

Con un diseño más débilmente acoplado, probar la existencia del atributo es mucho más sencillo.

[TestMethod] public void Base_controller_must_have_MaxLengthFilter_attribute() { var att = typeof(BaseController).GetCustomAttribute<MaxLengthAttribute>(); Assert.IsNotNull(att); }

Estoy tratando de probar que mi controlador base está decorado con un cierto filtro de acción. Debido a que el constructor de este filtro busca web.config , mi primer intento de prueba falla porque el proyecto de prueba no tiene un archivo de configuración válido. Continuando, utilicé un TestConfigProvider que TestConfigProvider en el constructor del filtro, pero la siguiente prueba falla porque el proveedor de configuración no se pasa al constructor. ¿De qué otra forma puedo probar si se aplica este filtro?

[TestMethod] public void Base_controller_must_have_MaxLengthFilter_attribute() { var att = typeof(BaseController).GetCustomAttribute<MaxLengthFilter>(); Assert.IsNotNull(att); }


Quizás pueda agregar el archivo de configuración válido a su proyecto de prueba a través de "agregar archivo como enlace"


Recientemente he aquí más y más preguntas sobre los "problemas" de configuración. Todos tienen una base común: tiene varios proyectos, servidores y servicios que necesitan usar la misma configuración. Mi consejo para usted: deje de usar Web.config.

¡Coloque toda su configuración en la base de datos! Agregue una tabla (o quizás varias tablas) con todas sus claves de configuración y valores y léalas cuando se inicie la aplicación (global.asax).

De esta manera, no necesita preocuparse por hacer frente a su configuración para cada proyecto o inyectarla a diferentes constructores.