Подтвердить что ты не робот

Повторяются ли ActionFilterAttributes по потокам? Как это работает?

Я тестировал следующий код, чтобы попробовать и как работает 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);
    }
}

Когда я запускаю вышеуказанный код в двух параллельных потоках, поле _privateValue путается. Однако свойство PublicValue не путается.

Мне кажется, что ActionFilterAttributes повторно используются в потоках, но эти новые экземпляры создаются в зависимости от констант, заданных для публичных свойств. Правильно ли я?

Где я могу найти информацию об этом?

4b9b3361

Ответ 1

Это будет зависеть от версии ASP.NET MVC, но вы никогда не должны сохранять состояние экземпляра в фильтре действий, который будет повторно использоваться между различными методами. Здесь цитата, например, из одного из нарушение изменений в ASP.NET MVC 3:

В предыдущих версиях ASP.NET MVC фильтры действий создаются за запрос, за исключением нескольких случаев. Такое поведение никогда не гарантировалось но только деталь реализации и контракт на фильтры должны были рассматривать их без гражданства. В ASP.NET MVC 3 фильтры кешируется более агрессивно. Поэтому любые настраиваемые фильтры действий, которые неправильное сохранение состояния экземпляра может быть нарушено.

Это в основном означает, что один и тот же экземпляр фильтра действий может быть повторно использован для разных действий, и если вы сохранили в нем состояние экземпляра, оно, вероятно, сломается.

И с точки зрения кода это означает, что вы никогда не должны писать фильтр действий следующим образом:

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
    }
}

но вы должны написать это следующим образом:

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
    }
}