13

最近、職場で ASP.NET プロジェクトのコードに取り組んでいます。Sessionユーザー アクティビティ (ページ ヒット数など) に関する基本的なメトリックを取得するための追跡ユーティリティが必要でしSession_EndGlobal.asax

私はハッキングを始めました。最初のコードは問題なく機能し、ページの読み込みごとに DB を更新しました。Session_Endただし、各リクエストでこの DB ヒットを削除し、すべてのデータを保存することに依存したかったのです。

Tracker基本的にセッション変数をラップするプロパティを含め、すべてのトラッキング コードがクラスにカプセル化されます。

問題は、メソッドで 実行Tracker.Log()したときに、トラッカー コードの が で失敗していたことです。常に現在のリクエストに関連しているため、これは理にかなっています。もちろん、 にはリクエストはありません。Session_EndHttpContext.Current.SessionNullReferenceExceptionHttpContextSession_End

実際には正常に動作しているように見えるa を返すプロパティがあることを知ってGlobal.asaxいます(トラッカーに挿入することになりました)。SessionHttpSessionState

しかし、私は興味があります. の外部から使用されるオブジェクトへの同じ参照をどのように取得できますHttpSessionStateか?Global.asaxGlobal.asax

前もってありがとう、私は入力に感謝します。:)

4

7 に答える 7

18

元の質問によりよく答えるには:

バックグラウンド

ページ リクエストごとに新しいSessionオブジェクトが作成され、セッション ストアからインフレートされます。これを行うために、クライアントから提供された Cookie または特別なパス構造 (Cookie を使用しないセッションの場合) を使用します。このセッション識別子を使用して、セッション ストアを参照し、新しいセッション オブジェクトを逆シリアル化します (これが、InProc を除くすべてのプロバイダーが Serializable である必要がある理由です)。

InProc プロバイダーの場合HttpCache、セッション ID をキーとして格納された参照を渡すだけです。これが、がリサイクルされるときに InProc プロバイダーがセッション状態をドロップする理由ですAppDomain(また、複数の Web サーバーが InProc セッション状態を共有できない理由でもあります

この新しく作成され、膨張したオブジェクトはContext.Itemsコレクション内に保持されるため、リクエストの期間中は使用できます。

オブジェクトに加えたすべての変更Sessionは、要求の最後にシリアライズによってセッション ストアに永続化されます (または、InProc の場合はHttpCacheエントリが更新されます)。

Session_End実行中の現在のリクエストなしで発火するため、オブジェクトSessionは利用可能な情報なしで ex nilo でスピンアップされます。InProc セッション ステートを使用している場合、 の有効期限が切れるとHttpCacheイベントへのコールバック イベントがトリガーされるSession_Endため、セッション エントリは使用できますが、最後に に保存されたもののコピーのままHttpContext.Cacheです。この値はHttpApplication.Session、内部メソッド ( と呼ばれるProcessSpecialRequest) によってプロパティに対して格納され、そこで使用できるようになります。それ以外の場合はすべて、HttpContext.Current.Session値から内部的に取得されます。

あなたの答え

Session_End は常に null Context に対して発生するため、そのイベントで常に this.Session を使用し、HttpSessionState オブジェクトをトレース コードに渡す必要があります。HttpContext.Current.Session他のすべてのコンテキストでは、トレース コードから取得してから渡すことはまったく問題ありません。ただし、トレース コードがセッション コンテキストに到達しないようにしてください。

私の答え

Session_End使用しているセッション ストアが をサポートしていることがわかっている場合を除き、Session_End使用しないください。唯一のインザボックスストアはストアです。それを行うセッション ストアを作成することは可能ですが、複数のサーバーがある場合、誰が処理するかという問題は曖昧です。trueSetItemExpireCallbackInProcSessionStateSession_End

于 2009-01-23T00:08:45.247 に答える
11

Global.asax は HttpApplication を実装しています。これは、その中からこれを呼び出すときに話しているものです。

HttpApplicationの MSDN ドキュメントには、たとえば HttpHandler でそれを取得し、そのさまざまなプロパティにアクセスする方法の詳細が記載されています。

でも

アプリケーションは、並列リクエストを処理するために HttpApplication の複数のインスタンスを作成できます。これらのインスタンスは再利用できます。

私も注意事項を追加します。アプリケーションがクラッシュした場合、 session_end が呼び出されるという保証はなく、すべてのセッションですべてのデータが失われます。明らかに良いことではありません。

すべてのページにログインすることはおそらく良い考えではないことに同意しますが、非同期ログが発生している中途半端な家かもしれません.ログクラスに詳細を送信し、後で詳細をログに記録します-それでも100%ではありませんアプリがクラッシュしても安定しますが、すべてを失う可能性は低くなります。

于 2009-01-21T11:49:43.210 に答える
3

ファイルでが に設定されている場合にのみ、Session_Endイベントが発生します。セッション モードがまたはに設定されている場合、イベントは発生しません。 sessionstate modeInProcWeb.configStateServerSQLServer

Session["SessionItemKey"]セッション値を取得するために使用します。

于 2011-01-21T07:53:27.133 に答える
0

セッションは、Session_Startイベント中にGlobal.asaxファイルで使用できます。たぶん、この時点まで何かをするのを待ちますか?

于 2011-11-09T10:28:31.920 に答える
0

さて、私はセッション アクティビティを追跡するために同じ問題を抱えています。session_end イベントを使用する代わりに、IDisposable インターフェイスとデストラクタを sessiontracker クラスに実装しました。Dispose() メソッドを変更して、セッション アクティビティを DB に保存しました。ユーザーがログアウト ボタンをクリックすると、メソッド obj.Dispose() が呼び出されます。ユーザーが誤ってブラウザを閉じた場合、GC はオブジェクトのクリーニング中にデストラクタを呼び出します (すぐではありませんが、しばらくしてからこのメソッドが呼び出されることは確実です)。デストラクタ メソッドは、同じ Dispose() メソッドを内部的に実行して、セッション アクティビティを DB に保存します。

-シャン

于 2009-07-16T15:31:36.070 に答える