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