ASP.NET のセッションと同時実行

ASP.NET で複数リクエストからセッションを扱おうとすると困ったことになるよという話。

SPA とかだと、画面からいろんなリクエストを非同期で飛ばして、パーツごとに表示することがある。 そんなとき、たとえば認証情報をセッションから取得して、その情報で DB を見に行き、取得内容を返す、といったことが考えられる。

[HttpGet]
public ActionResult Company(string id) {
   var loginInfo = Session[id];
   var company = GetCompany(loginInfo.CompanyId);

   return Json(company, JsonRequestBehavior.AllowGet)
}

[HttpGet]
public ActionResult User(string id) {
   var loginInfo = Session[id];
   var user = GetUser(loginInfo.UserId);

   return Json(user, JsonRequestBehavior.AllowGet)
}

こんなとき AjaxCompanyUser を呼ぶと、後に呼ばれたリクエストは先に呼ばれたリクエストの response が完了するまで待たされてしまう。

これは .NET が Session をロックしているためだ。確かに同時実行中に書き換わってしまったら困るのだが、パフォーマンス的にはそれでは困る。

回避するためには、セッションに対して書き込みは行わないよ!ということを属性で明示する。

[SessionState(SessionStateBehavior.ReadOnly)]
HomeController : Controller {
   ...
}

残念なことに SessionState 属性は Action ではなく Controller 単位にしか付与できない。