同一セッションの振る舞い(2)

同一セッションでは、リクエストセーフになるという話の続編です。リクエストセーフはASP.NET独自で処理しているので、飛んできた複数のリクエストはASP.NETで一旦受けておいて、そのリクエストを直列に処理するという方法を取っているようです。この辺の詳しい仕様って、どこかに公開されているのでしょうか?

で、本題なのですが、例えば、2つのリクエストが飛んできて、最初のリクエストを処理するのに時間がかかっていて、次のリクエストが待たされている状態では、待たされているリクエストが処理されるとき、BeginRequestやAuthenticateRequestなどのパイプライン処理が省略されるみたいなのです。なので、HttpModuleを独自に実装して、スレッドローカル(スロット)に値を設定したりしてると、このパイプライン省略されたリクエストでは設定しているはずの値が入ってないということで問題になりました。(私は、ログインユーザのコンテキスト情報としてスレッドローカルに設定していたのです。)

これを回避するには、AuthenticateRequestなどでは独自のコンテキストをスレッドに設定するようなことはせず、IPrincipalに埋め込むべきということです。パイプラインは省略され、スレッドIDも違うリクエストなのですが、このプリンシパル情報はちゃんと引き継ぐようになっているのです。(でないとつかえませんよね。)

なので、結論は、AuthenticateRequestなどのパイプラインで独自のコンテキスト情報をスレッドに埋め込まない。この場合、独自のプリンシパル(IPrincipalの実装クラス)を定義してそこに設定すべきということ。そして、コンテキスト情報は、ページのOnInitイベントなどのタイミングで、独自のプリンシパル(Page.Context.Userプロパティ)から値を取得して設定すればよいでしょう。(例えば、Pageのスーパークラスなんかで。)