67

私はMVCフレームワークのコツをつかもうとしているので、我慢してください。

現在、セッションストアを使用しているのは、現在ログインしているユーザーを保存することだけです。私のウェブサイトはシンプルです。この例では、Person、Meeting、および File の 3 つのドメイン オブジェクトを考えます。ユーザーは、ログインしてミーティングの「メンバー専用」プロファイルを表示し、それにファイルを追加したり、ログインしていない場合はミーティングの公開「プロファイル」を表示したりできます。

そのため、ミーティングのプライベート プロファイルから、ログインしているユーザーには、「ファイルを追加」リンクがあります。このリンクは FileContoller.Add(int meetingId) にルーティングされます。このアクションから、ユーザーが会議 ID を使用してファイルを追加したい会議を取得しますが、フォームが投稿された後でも、ユーザーがファイルを追加している会議を知る必要があります。それが私の質問の場所です。TempData を介して「現在やり取りしている」ミーティングを渡す必要がありますか、それともセッション ストアに追加する必要がありますか?

これは私が現在追加アクションをセットアップしている方法ですが、機能していません:

    public ActionResult Add(int meetingId)
    {
        try
        {
            var meeting = _meetingsRepository.GetById(meetingId);
            ViewData.Model = meeting;
            TempData[TempDataKeys.CurrentMeeting] = meeting; /* add to tempdata here */
        }
        catch (Exception)
        {
            TempData[TempDataKeys.ErrorMessage] = "Unable to add files to this meeting.";
            return RedirectToRoute("MeetingsIndex");
        }

        return View();
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Add(FormCollection form)
    {
        var member = Session[SessionStateKeys.Member] as Member;
        var meeting = TempData[TempDataKeys.CurrentMeeting] as Meeting; /* meeting ends up null here */

        if (member == null)
        {
            TempData[TempDataKeys.ErrorMessage] = "You must be logged in to add files to an meeting.";
            return RedirectToRoute("LoginPage");
        }

        if (meeting == null) 
        {
            TempData[TempDataKeys.ErrorMessage] = "An error occurred. No meeting selected.";
            return RedirectToRoute("MeetingsIndex");
        }

            // add files to meeting

        TempData[TempDataKeys.Notification] = "Successfully added.";
        return RedirectToRoute("AddFiles", new {meetingId = meeting.MeetingId});
}

編集:

ほとんどの回答に基づいて、どのような種類のデータ (メッセージ以外) を TempData と Session に保存する必要があるかについて、誰かが例を提供できますか?

4

7 に答える 7

98

TempDataはセッションであるため、完全に異なるわけではありません。ただし、 TempDataはリダイレクト用であり、リダイレクトのみであるため、この区別は簡単に理解できます。したがって、TempDataにメッセージを設定してからリダイレクトすると、TempDataが正しく使用されます。

ただし、あらゆる種類のセキュリティにSessionを使用することは非常に危険です。ASP.NETでは、セッションとメンバーシップは完全に分離されています。他のユーザーからセッションを「盗む」ことができます。そうです、人々はこの方法でWebサイトを攻撃します。したがって、ユーザーがログインしているかどうかに基づいて投稿情報を選択的に停止する場合は、IsAuthenticatedを確認し、ログインしているユーザーのタイプに基づいて情報を選択的に表示する場合は、ロールプロバイダーを使用します。GETはキャッシュできるため、GETのアクションへのアクセスを選択的に許可する唯一の方法は、AuthorizeAttributeを使用することです。

編集した質問への応答の更新:質問でTempDataを使用する良い例がすでにあります。つまり、POSTが失敗した後に単純なエラーメッセージを返します。何をすべきかという点でセッションに保存される(「あまり」を超えて)、私はセッションをユーザー固有のキャッシュと考えています。非ユーザー固有のキャッシュと同様に、セキュリティ上重要な情報をそこに配置しないでください。しかし、それは調べるのに比較的高価なものを貼り付けるのに良い場所です。たとえば、Site.Masterにはユーザーのフルネームが表示されています。これはデータベースに保存されており、提供するすべてのページに対してデータベースクエリを実行する必要はありません。(私たちのアプリケーションのインストールは単一の会社で使用されているため、ユーザーのフルネームは「セキュリティに敏感」とは見なされません。)したがって、Sessionをユーザーが持っているCookieによって異なるキャッシュと考えると、次のようになります。はるかに間違っています。

于 2009-09-30T20:31:04.353 に答える
17

デフォルトの TempData プロバイダーはセッションを使用するため、TempData が次の要求の最後にクリアされることを除いて、実際には大きな違いはありません。2 つの要求間でデータを保持するだけでよい場合は、TempData を使用する必要があります。2 番目の要求は、ユーザーからの他の要求 (AJAX など) で誤ってデータを削除してしまう問題を回避するためのリダイレクトであることが望ましいです。それよりも長くデータを保持する必要がある場合は、TempData を再設定するか、Session を直接使用する必要があります。

于 2009-09-30T20:27:43.687 に答える
4

「うまくいきません」はあまり説明的ではありませんが、いくつかの提案をさせてください。

内部では、TempData は Session を使用して値を格納します。そのため、ストレージ メカニズムなどに関して大きな違いはありません。ただし、TempData は次の要求が受信されるまでしか持続しません。

ユーザーがフォーム投稿の間に ajax リクエストを行うと、TempData は失われます。どんな要求でも、TempData はクリアされます。したがって、手動リダイレクトを行っている場合にのみ信頼できます。

会議 ID をビュー フォームの非表示フィールドに単純にレンダリングできないのはなぜですか? すでにモデルに追加しています。または、パラメーターとしてルートに追加します。

于 2009-09-30T20:27:09.803 に答える
0

TempData プロパティの値は、セッション状態に格納されます。TempData の値は、読み取られるか、セッションがタイムアウトするまで保持されます。あるコントローラ ビューから別のコントローラ ビューにデータを渡したい場合は、TempData を使用する必要があります。

アプリケーション全体でデータが必要な場合は、Session を使用します。

于 2014-03-28T11:31:55.253 に答える
0

MvcContrib のソリューションをお勧めします: http://jonkruger.com/blog/2009/04/06/aspnet-mvc-pass-parameters-when-redirecting-from-one-action-to-another/

完全な MvcContrib が必要ない場合、解決策は、MvcContrib ソースから簡単に取得できる 1 つのメソッド + 1 つのクラスのみです。

于 2009-09-30T20:47:33.007 に答える
0

私はそのようなデータをページ自体に保持することを好みます。meetingID を非表示の入力としてレンダリングして、コントローラーに送信し直します。投稿を処理するコントローラーは、その会議 ID を、レンダリングされるビューに戻すことができます。これにより、meetingID は基本的に、必要な限り渡されます。

これは、値を操作するメソッドを呼び出す前にグローバル変数に値を格納することと、値をメソッドに直接渡すことの違いのようなものです。

于 2009-09-30T20:27:26.497 に答える