2009-08-06 31 views
5

たとえば、複雑なオブジェクトを編集するための一連のウィザードページのようなWebアプリケーションが実装されているとします。ユーザが「Finish」ボタンをクリックするまで、オブジェクトはバックエンドシステムに保存されません(要件)。その間、何らかのセッション状態のオブジェクトに関するすべての情報を保持する必要があります。ASP.NET MVC:ウィザードのようなアプリケーションでセッション状態を維持するためのベストプラクティス

また、一部のウィザードページでは、潜在的に多数のアイテムを含むコンボボックスやリストボックスを表示する必要があります。これらの項目は、Webサービスを使用してバックエンドシステムからフェッチされます。

このウィザードでは、ウィザードのページからフォームの上にあるタブのリンクを使用して自由にジャンプすることができます。そのため、単純な「次の、次の...終了」というものではありません。

追加の制約:WebアプリケーションはWebファーム上で実行され、顧客はサーバー側のセッション状態を使用しています。セッション状態のサイズを最小限に抑えたい場合(彼らは過去にこの問題を抱えていました)の最良の場合です。

だから、基本的に2つの問題がここにあります

  1. どのように/どこウィザードでユーザーが入力したデータを保持するには?
  2. バックエンドから受け取ったコンボ/リスト項目をキャッシュするかどうか、もしそうなら、どこで?

オプション私が検討している:

  1. は(HTMLページにそれをシリアル化)WebフォームのようなのViewStateでオブジェクトを格納します。これにはコンボボックスの項目も含まれます。明らかに、HTMLページが非常に大きくなり、Webアプリケーションが遅くなるという問題が生じる可能性があります。 サーバー側のセッション状態にかかわらず、顧客の要望のそれは(後半プロジェクト内の)実際のWebファーム上でテストされるまで、パフォーマンスが影響を受けることになりますか知らずにそれを保存する

私は2つの間で決めることができません。それとも別の選択肢がありますか?

+2

セッション状態のルートに移動する場合、カスタムモデルバインダーを作成し、そのオブジェクトをコントローラのアクションメソッドに渡します。 – RichardOD

+0

それは私が今遊んでいるものです。実際には、ビューモデルと同じモデルを使用してビューコードでシリアル化することを考えています。モデルバインダーを使用してそれを逆直列化します。意味がありますか? –

答えて

5

なぜキャッシュするのですか?各ページがdivまたはパネルで、タブに関連する現在のdivを表示するだけのタブ付きページを持つことができます。そうすれば、ユーザーがフォームを送信したときにすべての入力を追跡して処理する必要はありません。

+0

それは確かに一つの選択肢であり、実用的なものです。大きな欠点は、最初のページのダウンロード時間だと思います。これは問題になる場合もありませんし、プラス側ではウィザードの移行が瞬時になります。 – RichardOD

+1

OK、私は、サーバー側で多くの検証が行われていることを忘れていました。例:ユーザーが「次へ」ボタンを押すたびに。ですから、全体が単一のページとして実装されていれば、AJAXによる検証に頼らざるを得ません.AJAXを使用すると、私のケースでは設計が複雑になります。しかし、それは有効な選択肢だと私は認めている。 –

2

デイジーは言ったように、キャッシュする必要はありません。隠しフォームフィールドを使用することもできます。これらはそれぞれのコントローラーアクションで同じオブジェクトにマップできるため、連続したページから徐々にオブジェクトを構築できます。

//Here's a class we're going to use 
public class Person 
{ 
    public int Age {get;set;} 
    public string Name {get;set;} 

    public Person() 
    { 
    } 
} 

//Here's the controller 
public Controller PersonCreator 
{ 
    public ActionResult CreatePerson() 
    { 
    //Posting from this page will go to SetPersonAge, as the name will be set in here. 
    return View(); 
    } 

    public ActionResult SetPersonAge(Person person) 
    { 
    //This should now have the name and age of the person 
    return View(person); 
    } 
} 

//Here is your SetPersonAge, which contains the name in the model already: 
<%= Html.Hidden("Name", Model.Name) %> 
<%Html.TextBox("Age") %> 

これはかなりです。

+0

Yeap-別の有効なオプション。 – RichardOD

+1

実際に私の既存のデザインはこのように動作します。しかし、問題はより複雑なユーザーコントロールであり、「隠し」モードでは「可視」モードと同じ方法でマッピングすることは困難です(例:バックエンドからツリービューが表示されます)。遅かれ早かれ、バックエンドからのデータの再要求を避けたい場合は、シリアライズされたビュー状態を使用する必要があります。 –

+0

なぜマップするのがより難しいですか?あなたのツリービューの例は問題ではありません。そして、私はあなたの評価に、シリアル化されたビューステートのいくつかの形式が必要になるということには同意しません。 MVCのメリットを完全には見ていないように思えますし、ウェブフォームと密接に適合するソリューションを見つけようとしています。 –

3

ウィザードデータをデータベースの一時テーブルに保存することはできますか?ユーザーがウィザードを終了すると、データは一時表からコピーされ、削除されます。一時テーブルには、古い未完了データを削除するタイムスタンプが含まれています。

+0

おそらく、シリアル化されたLOBとしてですか? – RichardOD

+0

残念ながら、このデータベースはオプションではありません。 –

1

私はさらにいくつかのオプション

  1. は、タブが表示され、クライアント側のJavaScriptを介してコンテンツを非表示にして、単一のページとして全体ウィザードを持つことを提案することができます。これにより、最初のページの読み込みに時間がかかることがあります。

  2. キャッシュアプ​​リケーションブロック(または同様のもの)を使用してサーバーでデータをキャッシュします。これにより、すべてのユーザーがすべてのセッションで複製するのではなく、このデータの1つのインスタンスを共有できます。データがより軽いので、顧客がセッションに格納することを許可するように説得することができます。

+0

2で何を意味するのか分かりません.Webアプリケーションでキャッシングアプリケーションブロックを使用する理由が分かりません。ASP.NETには完全にまともなキャッシュがあります。クライアント側のウィザードのための+1。 – RichardOD

+0

@sabri、それはウェブファームであり、このような設定でどのようにキャッシュが動作するのかわかりません。それは私がそれがOKであろうと仮定することは危険であり、私は十分に早くそれを試すことができません。 1)については、デイジーへの私の答えを見てください。 –

+1

@ RichardOD、私の間違い。あなたは正しいです;キャッシングアプリケーションブロックが必要なく、Cacheオブジェクトがはるかに優れています。 –

0

私は同じ問題を扱っていますが、私の要件は少しシンプルです(わずかな文字列の状態を維持しています)。私はこのアプローチに関する他の人の意見を聞くことにも興味があります。

私がやったことは、コントローラーでは、コントローラーのセッションプロパティに必要なデータをダンプしてから、次に必要なときに引き出します。あなたの状況については、このような何か:

//Here's the controller 
public Controller PersonCreator 
{ 
    public ActionResult CreatePerson() 
    {  
     //get the age out of the session 
     int age = (int)(Session["age"]); 
     //do something with it... 
     return View(); 
    } 
    public ActionResult SetPersonAge(Person person) 
    { 
     //put the age in the session 
     Session.Add("age", person.Age); 
     return View(person); 
    } 
} 

私はこれを好きな事、私は周りの私の見解ページに隠されたのparamsの束を配置する必要はありませんです。

+0

これは実際には機能しますが、明らかに抽象クラス/インターフェース/ global.asax /エラー処理/ベストパターンとプラクティスを持つ必要がある例です。 –

1

MVCコミュニティでは、セッションを使用することに対して多くの抵抗があります。問題は、私たちの多くの開発者が銀行のウェブサイトのようなログインシステムを構築していることです。隠されたフィールドを主張する可能性があり、それはいくつかの状況では機能しますが、セキュリティとコンプライアンスのためにユーザーをタイムアウトさせる必要があるときは、いくつかの選択肢があります。クッキーは信頼できません。 Javascriptに依存するタイマーは信頼性が低く、目標が正常に機能しなくてはならないため、508準拠ではありません。したがって、ログインの場合、セッションは良い選択です。サーバー・データベースまたはサーバー・ファイル・システムにクライアント・ブラウザーに時刻を書き込む場合は、依然としてユーザー1人あたりの時間を管理する必要があります。

したがって、セッションは控えめに使用しますが、恐れはありません。ウィザードの場合、技術的には隠しフィールドを直列化して渡すことができます。私は、必要性と範囲がはるかに大きくなり、セッションでの認証/認証の実装がアプリケーションの要点になると思う。

1

ドロップダウンとウィザードをタブ付きページに変換するための有効化のためにajaxを使用できず、html5を使用できない場合(ローカルストレージのドロップダウンキャッシュとフォーム状態の保存用に)、私はあなたが "ベストプラクティス "とあなたは悪い(または悪い)ものに頼らなければなりません。

MVCはセッションの使用に関するWebFormsの相手ですから、回避策を使用できますか?たとえば、これらの値をすべて後でクリーンアップする必要があるテンポラリデータベースレコードに格納する以外に、Windows Server用にAppFabric extensionを設定し、ドロップダウンリスト項目を格納するために使用することができます(スコープはすべてのユーザーに適用できます。システムを使用して同時にキャッシュをリフレッシュするWebサービスへの呼び出しを1つだけ必要とする)、また、ステップ間でオブジェクトを一時的に格納することができます。自動的に有効期限が切れるようにAppFabricの一時オブジェクトを設定して、クリーンアップが不要になるようにすることができます。また、Webサービス経由で別のシステムを広範囲に呼び出す場合は、システムの他の部分のスピードアップに役立つこともあります。

+0

私は今質問が2歳であるので、答えは今とは無関係で、AppFabricが1年後に導入されたのでそれは無関係です:) –

+0

+1それにもかかわらず;) –

0

この回答はSteve Sanderson's ASP.NET MVC 2/3にあり、MVC Futuresアセンブリへの参照が必要です。 Google Booksへのこのリンクはまさに​​彼がしているものです。

本質的には、ウィザードデータをビューにシリアル化します。取得されたすべての情報を格納する隠しフィールドがレンダリングされます。

コントローラーは、OnActionExecutingOnResultExecuted(リダイレクトを処理するため)を使用して、次のビューに渡すために何をすべきかを考え出すことができます。

読んでください - 彼は私よりもはるかに徹底的に説明しています。

関連する問題