Запись в сеанс только для чтения в 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);
    }
}

Переход к ~ / Образец / Тест бросит 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 на самом деле указывает на какой-то грязный / оптимистичный доступ.

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

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

Обновить

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

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

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

1 ответ

~/Sample/ поставишь? Значение = Foo

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

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

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

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

string test = (string)this.Session["test"]; 
Другие вопросы по тегам