¿Los ActionFilterAttributes se reutilizan en los hilos? ¿Cómo funciona?

He estado haciendo algunas pruebas con el siguiente código para probar y entrenar cómo funcionan los ActionFilterAttributes:

public class TestAttribute : ActionFilterAttribute { private string _privateValue; public string PublicValue { get; set; } public override void OnActionExecuting(ActionExecutingContext filterContext) { _privateValue = DateTime.Now.ToString(); base.OnActionExecuting(filterContext); } } 

Cuando ejecuto el código anterior en dos subprocesos paralelos, el campo _privateValue se confunde. Sin embargo, la propiedad PublicValue no se confunde.

Me parece que los ActionFilterAttributes se reutilizan en los hilos, pero que las nuevas instancias se crean en función de las constantes especificadas para las propiedades públicas. ¿Estoy en lo correcto?

¿Dónde puedo encontrar información sobre esto?

Esto dependerá de la versión de ASP.NET MVC, pero nunca debe almacenar el estado de la instancia en un filtro de acción que se reutilizará entre los diferentes métodos. Aquí hay una cita, por ejemplo, de uno de los cambios más importantes en ASP.NET MVC 3:

En versiones anteriores de ASP.NET MVC, los filtros de acción se crean por solicitud, excepto en algunos casos. Este comportamiento nunca fue un comportamiento garantizado, sino simplemente un detalle de implementación y el contrato de filtros fue considerarlos sin estado. En ASP.NET MVC 3, los filtros se almacenan en caché de forma más agresiva. Por lo tanto, cualquier filtro de acción personalizado que almacene incorrectamente el estado de la instancia puede estar roto.

Esto básicamente significa que la misma instancia del filtro de acción se puede reutilizar para diferentes acciones y si ha almacenado el estado de la instancia en ella, probablemente se rompa.

Y en términos de código, esto significa que nunca debes escribir un filtro de acción como este:

 public class TestAttribute : ActionFilterAttribute { private string _privateValue; public override void OnActionExecuting(ActionExecutingContext filterContext) { _privateValue = ... some calculation } public override void OnActionExecuted(ActionExecutedContext filterContext) { // use _privateValue here } } 

pero deberías escribirlo así:

 public class TestAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { var privateValue = ... some calculation filterContext.HttpContext.Items["__private_value__"] = privateValue; } public override void OnActionExecuted(ActionExecutedContext filterContext) { var privateValue = filterContext.HttpContext.Items["__private_value__"]; // use privateValue safely here } }