2012-01-20 18 views
26

私はASPセッションの好奇心が強い動作に出くわしました。コントローラをユーザーのセッション外に強制することができます。これを実行して、複数の要求を同時に実行し、セッションを使用して連続して実行できるようにしたいとします。予想通り、セッション状態を無効にMVC 3+での読み取り専用セッションへの書き込み

は動作します:

[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/SetTest?value = fooに行き、実際には "foo"を返します。 〜/ Sample/SetTest?value = barと呼んでから〜/ Sample/Test私はセッションが書き込まれたことを示す "bar"を取得します。

したがって、私はSessionStateBehavior.ReadOnlyにセッションに書き込んだり、自分の価値を読み返しています。

私はこれが原因の3つのうちの1つになると思う:MVC 3では

  • [SessionState(SessionStateBehavior.ReadOnly)]は無視/壊れています。
  • [SessionState]は、セッションが書き込み可能で書き込み可能になると無効になります。
  • SessionStateBehavior.ReadOnlyは、実際に何らかの汚い/楽観的なアクセスを示します。

誰でも確認できますか?

custom session provider documentationに基づいて、最後のものが真であると思われます。実装がどのように機能するのでしょうか? 「読み取り専用」セッションへの書き込みは、並行処理エラー(すなわち、最後の書き込み勝ち)を危険にさらすか、セッションが破損し、例外が発生する危険性がありますか?

更新

これは(Microsoft's docsから)設計であるように見えます:にEnableSessionState属性は 読み取り専用としてマークされてもいること

注、同じ内の他のASP.NETページアプリケーションは セッションストアに書き込むことができるため、ロックされたデータが解放されるのを待って、ストアからの読み取り専用セッションデータ の要求がまだ終了する可能性があります。

上記の2番目のオプションのように見えますが、セッションがロックされ、モードが書き込み可能に変更されました。

答えて

9

〜/サンプル/ SetTest?値= fooの

はい、それはすべてのエラーをスローしませんが、それはまた、リクエストの終了時にセッションを保持しませんでした。設計によって、あなたがセッションに書き込むものは、要求のライフサイクルの最後に更新されます(セッションが書き込み可能な場合のみ)。

私のテスト〜/ Sample/Testでは何も返しません。

セッションが読み込み専用のときは、ここで高速に失敗しているはずです。 SetTest/_〜/サンプル呼び出す - あなたのサンプルがうーん、ここでのサンプルは私がやっている何のために単純化されたコードですが、私が書かれたセッションを取得しています

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

を書き換える必要ところで

?value = foo_そして、_〜/ Sample/Test_が私のために "foo"を返しています。実際にはエラーが発生するはずですが、そうでなければセッションを保存できないはずですが、それは間違いなく私のために保存しています。 – Keith

+0

あなたが正しいです、質問の私のサンプルは期待通りにセッションに書き込むことができません。質問はなぜ私のアプリがまだそれに書き込むことができるのですか?私は何が違うのかを知り、質問を更新します... – Keith

+0

私は上記の私の答えに言及したように、彼らはセッションが読み取り専用で、そしてあなたがそれを更新しているときには失敗しません。フレームワークはリクエストの最後にセッションの更新を無視しています。一方で、あなたはそれが好きでも、あなたはセッション構造を変更することができます。 – chandmk

関連する問題