45

ASP.Net MVC 4 で記述されたコード ベースを継承しました。すべてのポスト メソッドはFormCollection. 引用符で囲まれた文字列を介して値にアクセスする必要があるという煩わしさは別として、ViewModel プロパティのModelState.IsValidや属性などを使用できないなどの欠点もあります。[AllowHtml]彼らは実際にビューごとに ViewModel クラスを作成しましたが (実際の Entity Framework Model クラスの直接ラッパーにすぎません)、GET メソッドにのみ使用されます。

FormCollection について、これが実際に良いアイデアだった理由を説明するものはありますか? デメリットしかないようです。代わりにViewModelを使用して、それを「修正」したいと思います。ViewModel には具体的なクラスではなくインターフェイスであるプロパティがあるため、これにはかなりの作業が必要です。つまり、カスタム バインダーを作成するか、ViewModel を変更する必要があります。

しかし、おそらく FormCollection を使用することが理にかなっているところに何か欠けているものがあるでしょうか?

4

11 に答える 11

52

ViewModel の代わりに FormCollection を使用する正当な理由はありますか?

いいえ、次の問題があります。

問題 - 1

が使用されている場合FormCollection...の特定のインデックスのエントリを取得している間、返される値のタイプが であるため、不必要Type Castに値に必須になります。Strongly Typed の場合、この状況は発生しません。Primitive TypeSystem.Collections.Specialized.NameValueCollectionStringView-Models

問題 - 2

フォームを送信してPostアクション メソッドに移動するとView-Model、パラメータがアクション メソッドに存在するため、投稿された値をあなたに送り返すことができますView。それ以外の場合は、コードを再度記述して、TempData/ViewData/ViewBag

ここに画像の説明を入力

View-Model は通常のクラスであり、View との間でデータをバインドするために作成されます

問題 - 3

View Modelまたはで実装できるデータ注釈がありますCustom Validations

ここに画像の説明を入力

ASP.Net MVC は、データ注釈を使用してモデルの検証を簡素化します。データ注釈は、プロパティに適用される属性です。組み込みの Validation Attribute クラスを継承することで、カスタムの検証属性を作成できます。



問題 - 4

次のHTMLがある例

<input type="text" name="textBox1" value="harsha" customAttr1 = "MyValue" />

質問: 上記から、たとえばコントローラー内から customAttr1 の値にアクセスするにはどうすればよいですか?

回答: フォームが送信されると、要素の名前と値のみがサーバーに送信されます。

代替案: 少しの jQuery を使用してカスタム属性値を取得し、それをフォーム値とともにアクション メソッドに投稿します。

別のオプションは、カスタム属性で取得したものを非表示のコントロールに配置することです




それが理由です、私は常に使用することを好みますView-Models

于 2013-06-19T23:54:37.087 に答える
7

私が考えることができる唯一の利点は、厳密に型指定される EF モデルを指定しない場合に提供される自動生成されたコントローラーを使用する場合です。その場合、作成アクションと編集アクションは FormCollection オブジェクトを使用します。これは、この目的のために使用するフレームワークの信頼できる既存のアーティファクトであるためです。おそらく、以前の開発者は、コントローラーの作成中にこのオプションを選択し、Visual Studio が何をしているかを知る必要があるため、このオプションを使い続けました :)

しかし、実際には、この数秒の有利なスタートは決してお勧めしません。ビューモデルを構築することは常に良いことです。メンテナンス目的のみであれば、その方向に進む努力を検討することをお勧めします。モデル バインディングと厳密に型指定されたビューと html ヘルパーを使用すると、マジック ストリングを変更してページが破綻するまでそれに気付かないため、実行時エラーの数を大幅に減らすことができます。

于 2013-06-18T15:57:43.187 に答える
3

はい。時には、それが役立つことがあります。次に例を示します。

データベースに " " があるとしましょうdate_and_time_field

Razor View では、2 つのフォーム フィールドを使用します。最初の「日付」(おそらくjQuery UI Datepickerを使用)。2つ目は「時」。

コントローラ アクションでは、 andを使用して「date_and_time_field」を構成します。Request.Form["Date"]Request.Form["Hour"]

他にも役立つシナリオがあります。

  • クロステーブル (Razor ビューのチェックボックス付き)

  • コレクションRequest.Unvalidated().Form(おそらくこれはあなたの質問の一部ではありません:私は話題から外れたくありません)

于 2013-06-20T15:56:46.083 に答える
3

これによりform collection、フォーム内のすべての値を取得できます。の一部ではないフォームから追加の値を渡す必要がある場合がありますview model

フォームから 10 個の隠し値を渡す例を見てみましょう。フォーム コレクションは理にかなっています。

直面する可能性のある唯一の問題は、型キャストです。取得するすべてのフォーム コレクション アイテムは文字列になります。type cast要件に基づいて必要になる場合があります。

また、モデルの状態の検証も、課題に直面する可能性がある別の領域です。

于 2013-06-24T08:03:33.100 に答える
2

フォーム コレクション プロパティはいつでもメソッド シグネチャに追加できます。それらは、対応するキーを持つフォーム値によって自動的に設定されます。

于 2013-06-20T08:27:29.900 に答える
2

タイトルの質問への回答: はい。

FormCollection使用する必要があるいくつかの状況があります。たとえば、ViewModelが 1 対 N の関係 (具体的なケースでは a TimesheetViewModelwith ICollection<TimesheetEntryViewModel>) を実装するプロパティを持ち、コントローラが時間エントリ間で検証を実行して、エントリの終了時間の間で時間の衝突が発生しないようにする必要があるとします。および次のエントリの開始時刻。関連エントリを検証エラーとしてマークするには、行インデックスを取得するにはどうすればよいですか?

デフォルトのモデル バインディングでは、コントローラ ロジックでインデックス値が失われます。幸いなことに、ビューFormControllerで使用したインデックスを保存し、より具体的な検証を行うことができます。

于 2015-12-27T22:59:18.800 に答える
2

Forms Collectionを使用すると、フォームの値を取得する簡単な方法を見つけることができます。それ以外の場合は、フォーム フィールドを模倣するクラスを作成する必要があります。人々は、あまり重要でない/めったに使用されないフォーム用のカスタム クラスを作成するのが面倒な場合があります。

いいえ、アクション パラメータとしてのカスタム クラスに対するフォーム コレクションの追加の利点 (実際には限定的) はなく、可能な限り回避する必要があります。

于 2013-06-18T10:27:43.110 に答える