24

ユーザーが実行しているいくつかのアクションの「状態」を一連の異なるASP.NetWebフォームに保存したいと思います。状態を維持するための私の選択は何ですか、そして各ソリューションの長所/短所は何ですか?

私はSessionオブジェクトを使用しており、いくつかのヘルパーメソッドを使用してオブジェクトを強く入力しています。

    public static Account GetCurrentAccount(HttpSessionState session)
    {
        return (Account)session[ACCOUNT];
    }

    public static void SetCurrentAccount(Account obj, HttpSessionState session)
    {
        session[ACCOUNT] = obj;
    }

多くの情報源から「セッションは悪だ」と言われているので、それがこの質問の根本的な原因です。あなたが「ベストプラクティス」とどう思うか、そしてその理由を知りたいです。

4

13 に答える 13

38

セッション状態には本質的に悪はありません。

ただし、心に留めておくべきことがいくつかあります。

  1. ユーザーがブラウザの戻るボタンを押すと、前のページに戻りますが、セッションの状態は元に戻りません。そのため、CurrentAccountは、ページに元々あったものとは異なる場合があります。
  2. ASP.NETプロセスはIISによってリサイクルできます。それが発生すると、次のリクエストで新しいプロセスが開始されます。デフォルトのインプロセスセッション状態を使用している場合、それはなくなります:-(
  3. ユーザーがしばらくアクティブでない場合、セッションがタイムアウトして同じ結果になることもあります。これはデフォルトで20分に設定されているので、素敵なランチで十分です。
  4. アウトプロセスセッション状態を使用するには、セッション状態に格納されているすべてのオブジェクトがシリアル化可能である必要があります。
  5. ユーザーが2番目のブラウザーウィンドウを開くと、2番目の別個のアプリケーションがあることが期待されますが、セッション状態は2つで共有される可能性があります。したがって、一方のブラウザウィンドウでCurrentAccountを変更すると、もう一方のブラウザウィンドウでも同じようになります。
于 2008-09-25T13:41:41.037 に答える
19

フォーム データを一時的に保存するための 2 つの選択肢は、1 つ目は各フォームの情報をセッション状態変数に保存すること、2 つ目は URL パラメータを使用してフォーム情報を渡すことです。Cookie を 3 番目のオプションとして使用することは、多くの訪問者が Cookie をオフにしている可能性が高いという単純な理由から、単純に機能しません (ただし、これはセッション Cookie には影響しません)。また、質問の性質上、この情報が完全にコミットされるまでデータベーステーブルに保存したくないと想定しています。

セッション変数を使用することは、この問題に対する古典的な解決策ですが、いくつかの欠点があります。これらの中には、(1) インプロセス セッション管理を使用している場合、大量のデータがサーバーの RAM を使い果たす可能性がある、(2) サーバー ファーム内の複数のサーバー間でセッション変数を共有するには、追加の考慮事項が必要である、(3) 専門的に設計されたアプリは、セッションの有効期限が切れないようにします (セッション変数をキャストして使用しないでください。セッションの有効期限が切れている場合、キャストはエラーをスローします)。ただし、大部分のアプリケーションでは、セッション変数が間違いなく最適な方法です。

別の方法は、各フォームの情報を URL で渡すことです。このアプローチの主な問題は、情報の「受け渡し」に細心の注意を払わなければならないことです。たとえば、4 つのページで情報を収集している場合、最初のページで情報を収集する必要があります。その情報を 2 番目のページに URL で渡し、そのページのビューステートに保存する必要があります。次に、3 番目のページを呼び出すときに、2 番目のページからフォーム データとビューステート変数を収集し、両方を URL にエンコードします。あなたの手に本当の混乱があるでしょう。また、すべての情報は、A) URL セーフな文字列にシリアル化され、B) 単純な URL ベースのハッキング (例: 価格を平文で入力して渡すと、誰かが価格を変更する可能性があります)。一種の「セッション マネージャ」を作成して URL 文字列を管理させることで、これらの問題の一部を軽減できることに注意してください。適切に管理されていません。

最終的に、URL 変数を使用するのは、あるページから次のページに非常に限られたデータを渡すためだけです (たとえば、そのアイテムへのリンクにエンコードされたアイテムの ID)。

それでは、組み込みのセッション機能を使用して実際にユーザーのデータを管理すると仮定しましょう。「セッションは悪だ」と誰かが言うのはなぜですか? さて、上記のメモリ負荷、サーバー ファーム、および有効期限に関する考慮事項に加えて、セッション変数は実質的に型指定されていない変数であるという主な批判があります。

幸いなことに、セッション変数を慎重に使用することで、メモリの問題を回避できます (とにかく大きな項目はデータベースに保持する必要があります)。また、サーバー ファームが必要なほど大きなサイトを実行している場合は、ASP に組み込まれている状態を共有するために利用できるメカニズムがたくさんあります。 .NET (ヒント: インプロセス ストレージは使用しません)。

Session の残りの欠点を本質的にすべて回避するために、セッション データを保持するオブジェクトといくつかの単純な Session オブジェクト管理機能を実装することをお勧めします。次に、これらを Page クラスの子孫に組み込み、この子孫 Page クラスをすべてのページに使用します。厳密に型指定された値のセットとして、ページ クラスを介してセッション データにアクセスするのは簡単なことです。オブジェクトのフィールドは、厳密に型指定された方法 (たとえば、変数ごとに 1 つのフィールド) で各「セッション変数」にアクセスする方法を提供することに注意してください。

これがあなたにとって簡単な作業なのか、それともサンプル コードが必要なのかをお知らせください。

于 2008-09-25T13:52:45.660 に答える
10

私の知る限り、これSessionはこの情報を保存するための意図された方法です。通常、セッション状態はデフォルトでプロセスに保存されることに注意してください。複数のWebサーバーがある場合、またはIISを再起動すると、セッション状態が失われます。これは、ASP.NET State Service、またはSQLデータベースを使用してセッションを格納することで修正できます。これにより、別のWebサーバーに再ルーティングされた場合や、ワーカープロセスがリサイクルされた場合でも、セッションを確実に取り戻すことができます。

于 2008-09-25T13:17:45.167 に答える
6

「Sessionbeingevil」については...従来のASPで開発している場合は同意する必要がありますが、ASP.NET/IISの方がはるかに優れています。

本当の問題は、状態を維持するための最良の方法は何かということです。この場合、現在ログインしているユーザーに関しては、名前、電子メールアドレス、認証などで常に参照しているため、そのオブジェクトをSessionに保存します。

長期的な永続性を必要としないその他のちょっとした情報では、 Cookieとビューステートの組み合わせを使用します。

于 2008-09-25T13:17:19.800 に答える
6

その不吉な評判の理由の 1 つは、せっかちな開発者がアイテム キーとして (あなたのようなヘルパー クラスではなく) UI コードで文字列リテラルを使いすぎて、テスト不可能な乱雑な状態の大きなバッグになってしまうことです。ある種のラッパーは、悪意のないセッションを使用するためのエントリーレベルの要件です。

于 2008-09-25T13:49:00.223 に答える
5

Webアプリケーションでグローバルにアクセスできる情報を保存する場合、これを行う方法はThreadStatic属性です。これにより、のメンバーが現在のスレッドで共有されるstaticメンバーに変わりClassますが、他のスレッドでは共有されません。の利点はThreadStatic、Webコンテキストを利用可能にする必要がないことです。たとえば、を参照しないバックエンドがありSystem.Web、そこでも情報を共有したい場合はid、プロパティ内のすべてのリクエストの先頭にユーザーを設定しThreadStatic、アクセスする必要なしに依存関係でそれを参照できます。Sessionオブジェクトに。

staticスレッドは1つだけなので、他の同時訪問者がセッションに参加しないようにします。これは、リクエストごとにプロパティがリセットされることを確認する限り機能します。これにより、Cookieの理想的なコンパニオンになります。

于 2008-09-25T13:24:57.723 に答える
3

この場合、Sessionオブジェクトを使用しても問題ないと思いますが、ブラウザアクティビティが長時間ない場合、Sessionが期限切れになる可能性があることを覚えておく必要があります(HttpSessionState.Timeoutプロパティは、セッション状態プロバイダーがセッションを終了する分数を決定します)。戻る前に値の存在を確認してください。

public static Account GetCurrentAccount(HttpSessionState session)
{
    if (Session[ACCOUNT]!=null)
        return (Account)Session[ACCOUNT];
    else
        throw new Exception("Can't get current account. Session expired.");
}
于 2008-09-25T13:36:18.540 に答える
2

http://www.tigraine.at/2008/07/17/session-handling-in-aspnet/

お役に立てれば。

于 2008-09-25T13:24:35.930 に答える
1

「悪」はセッションを使いすぎたからだと思います。何かとすべてをその中に貼り付けると(すべてにグローバル変数を使用するなど)、パフォーマンスが低下し、混乱するだけです。

于 2008-09-25T13:37:29.283 に答える
1

セッションオブジェクトに入れたものはすべて、クリーンアップされない限り、セッションの間そこにとどまります。inprocとstateserverを使用して保存されたメモリの管理が不十分だと、必要以上に早くスケールアウトする必要があります。セッション/ユーザーのIDのみをセッションに格納し、ヘルパークラスを使用して必要なものをオンデマンドでキャッシュオブジェクトにロードします。そうすれば、そのデータを使用した頻度に応じて、その存続期間を微調整できます。asp.netの次のバージョンには、分散キャッシュ(噂)が含まれている可能性があります。

于 2008-09-29T20:53:39.987 に答える
1

次のリクエストまでしか存続する必要のない短期的な情報も、に保存できますViewState。これは、オブジェクトがシリアル化され、ブラウザに送信されたページに保存され、クリックイベントなどでサーバーにポストバックされることを意味します。次に、ViewStateがデコードされて再びオブジェクトに変換され、取得できるようになります。

于 2008-09-25T13:21:14.627 に答える
1

セッションは悪ではありません。ASP.NETアプリケーションで重要な機能を果たし、ユーザーの「セッション」中に複数のページ間で共有する必要のあるデータを提供します。いくつかの提案があります。可能な限りSQLセッション管理を使用し、セッションコレクションで使用しているオブジェクトが「シリアル化可能」であることを確認してください。ベストプラクティスは、ページ間で状態情報を絶対に共有する必要がある場合はセッションオブジェクトを使用し、必要のない場合は使用しないことです。情報はクライアント側では利用できません。セッションキーはCookieに保持されるか、クエリ文字列を介して、または構成方法に応じて他のメソッドを使用して保持され、セッションオブジェクトはデータベーステーブルで利用可能になります( InProcを使用しない限り、

于 2008-09-25T13:22:11.287 に答える
1

悪としてのセッション:ASP.NETにはなく、適切に構成されています。はい、可能な限りステートレスであることが理想的ですが、現実にはここからそこに到達することはできません。ただし、その影響を軽減する方法でSessionを動作させることができます(特にStateServerまたはデータベースセッション)。

于 2008-09-25T13:24:40.673 に答える