Запись на сеанс только для чтения в MVC 3+

Я столкнулся с любопытным поведением ASP-сессий. Вы можете заставить контроллер находиться вне пользовательского сеанса - я хочу, чтобы это можно было сделать, чтобы несколько запросов могли выполняться в одно и то же время, и использование сеанса заставляет их выполнять последовательно.

Отключение состояния сеанса работает как ожидалось:

[SessionState(SessionStateBehavior.Disabled)]
public class SampleController : Controller
{
    public ActionResult Test() 
    {
        // Access to the session should be denied
        object test = Session["test"];
        return Content(test);
    }
}

Переход к ~/Sample/Test вызовет System.Web.HttpException, как и ожидалось. Однако сеансы только для чтения выглядят немного странно:

[SessionState(SessionStateBehavior.ReadOnly)]
public class SampleController : Controller
{
    public ActionResult Test() 
    {
        // Read from the session should be fine
        object test = Session["test"];
        return Content(test);
    }

    public ActionResult SetTest(string value) 
    {
        // Write to the session should fail 
        Session["test"] = value;

        // Read it back from the session
        object test = Session["test"];
        return Content(test);
    }
}

Итак, теперь я ожидаю, что ~/Sample/Test будет работать, и это произойдет. Нечетный бит состоит в том, что набор тоже: я перехожу к ~/Sample/SetTest? Value = foo, и он не генерирует исключение, на самом деле он возвращает "foo". Если я назову ~/Sample/SetTest? Value = bar, а затем ~/Sample/Test, я получаю "bar", указывая, что сеанс был записан.

Итак, в SessionStateBehavior.ReadOnly я успешно записал сессию и прочитал мое значение назад.

Я думаю, это может быть связано с одной из трех вещей:

  • В MVC 3 [SessionState(SessionStateBehavior.ReadOnly)] сломан/игнорируется.
  • [SessionState] переопределяется, когда сессия записывается и становится доступной для записи.
  • SessionStateBehavior.ReadOnly фактически указывает на какой-то грязный/оптимистический доступ.

Кто-нибудь может подтвердить?

Я подозреваю, что последнее верно, основываясь на пользовательской документации поставщика сеансов - если это так, то как работает реализация? Влияет ли запись на "только чтение" риск concurrency ошибок (т.е. Последних попыток записи) или же он рискует коррумпированными сеансами и нарушает исключения?

Обновление

Похоже, что это по дизайну (из Документов Microsoft):

Обратите внимание, что даже если атрибут EnableSessionState помечен как ReadOnly, другие страницы ASP.NET в одном приложении могут пишите в хранилище сеансов, поэтому запрос данных сеанса только для чтения из хранилища все равно может оказаться в ожидании освобождения заблокированных данных.

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

Ответ 1

~/Sample/SetTest? value = foo

Да, это не вызовет никакой ошибки, но также не сохранило сессию в конце запроса. По дизайну все, что вы пишете на сеанс, обновляется (только если сеанс доступен для записи) в самом конце жизненного цикла запроса.

В моем тесте ~/Sample/Test ничего не возвращает.

Я думаю, что они, должно быть, быстро потерпели неудачу, когда сеанс читается только.

Кстати, ваш образец должен быть перезаписан

string test = (string)this.Session["test"];