2012-01-20 7 views
30

que he estado haciendo algunas pruebas con el código siguiente para tratar de entrenamiento de cómo funcionan ActionFilterAttributes:¿Los ActionFilterAttributes se reutilizan en los subprocesos? ¿Cómo funciona?

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 hilos paralelos al campo _privateValue se confunde. Sin embargo, la propiedad PublicValue no se confunde.

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

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

Respuesta

64

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. He aquí una cita, por ejemplo, de uno de los breaking changes en ASP.NET MVC 3:

En las versiones anteriores de ASP.NET MVC, filtros de acción se crean por solicitud, excepto en unos pocos casos. Este comportamiento nunca fue un comportamiento garantizado, pero solo un detalle de implementación y el contrato de los filtros los consideraron apátridas. En ASP.NET MVC 3, los filtros son almacenados en caché de manera más agresiva. Por lo tanto, cualquier filtro de acción personalizado que almacene incorrectamente el estado de la instancia podría 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 usted debe absolutamente nunca escriba un filtro de acción como esta:

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 usted debe escribir 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 
    } 
} 
+2

¿Qué pasa con las propiedades públicas de un filtro de acción (p. ej., propiedad Duración de salida de caché)? Supongo que se crea una nueva instancia si la propiedad es diferente. – cbp

+0

@cbp, ¿qué hay de ellos? No asumas nada sobre la vida útil de un filtro de acción. Como se cita en las notas de la versión, esto no es algo en lo que deba confiar. –

+1

Bien, pero ¿cómo puede OutputCache (que es un filtro de acción) tener propiedades públicas como Duration, CacheProfile, VaryByCustom, etc.? – cbp

Cuestiones relacionadas