web-dev-qa-db-ja.com

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

ASP.Net MVC 4で記述されたコードベースを継承しました。すべてのpostメソッドはFormCollectionを取ります。引用符で囲まれた文字列を介して値にアクセスしなければならないという面倒さの他に、ModelState.IsValid、または[AllowHtml] ViewModelプロパティの属性。実際には、ビューごとにViewModelクラスを作成しましたが(実際のEntity Framework Modelクラスの単なる単なるラッパーにすぎませんが)、GETメソッドにのみ使用されます。

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

しかし、おそらくFormCollectionを使用するのが理にかなっているのに、私が見逃しているものがありますか?

43
GendoIkari

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

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

問題-1

FormCollectionが使用されている場合... Type Castの特定のインデックスのエントリを取得している間、Primitive Typeを不必要にSystem.Collections.Specialized.NameValueCollectionすることが必須になります。返される値はString型です。この状況は、厳密に型指定されたView-Modelsの場合には発生しません。

問題-2

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

enter image description here

ビューモデルは通常のクラスであり、ビューとデータをバインドするために作成されます

問題-

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

enter image description here

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



問題-4

例は次のとおりです[〜#〜] html [〜#〜]

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

Question:上記からcustomAttr1の値にアクセスするには、たとえば内部からコントローラー

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

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

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




それが理由です。私はいつもView-Modelsを使用することを好みます

44
Imad Alazani

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

しかし、実際には、この数秒のヘッドスタートはお勧めしません。常にビューモデルを構築する方が良いでしょう。メンテナンスの目的でのみ、その方向に移動する努力を検討することをお勧めします。モデルバインディングと厳密に型指定されたビューおよびhtmlヘルパーを使用すると、マジックストリングを変更し、ページが爆発するまで認識されないため、実行時エラーの数を減らすことができます。

7
Mister Epic

OK別の観点を提供するために、POSTアクションでコントローラーに渡されるformcollectionを使用することが好きでした。 TryUpdateModelには、更新を許可するモデルのプロパティをホワイトリストに登録できるオーバーロードもあります。

if (TryUpdateModel(viewModel, new string[] { "Name" }))
{
    //Do something
}

必要なすべてのモデルバインディングを引き続き許可しますが、ビューモデルの「Name」プロパティ以外のものが更新されないようにするのに役立ちます。

TryUpdateModelメソッドの詳細については、こちらをご覧ください。

http://msdn.Microsoft.com/en-us/library/system.web.mvc.controller.tryupdatemodel(v = vs.108).aspx

6
RollemIra

はい。時には、役に立つ場合があります。次に例を示します。

Db "_date_and_time_field_"にあるとしましょう。

Razorビューでは、2つのフォームフィールドを使用します。最初の「日付」(jQuery UI Datepickerを使用する場合があります)。 2番目の「時間」。

コントローラーアクションでは、_compose "date_and_time_field"を_Request.Form["Date"]_および_Request.Form["Hour"]_を使用して実行します。

役に立つ他のシナリオがあります:

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

  • コレクションRequest.Unvalidated().Form(これはあなたの質問の一部ではないかもしれません:トピックから外れたくありません)

3
Fabio S

デフォルトのモデルバインダーは、必要なほぼすべてのことを行います。 FormCollectionを1回使用しました。後でViewModelの要素の配列をコレクションにバインドする方法を見つけ出すためだけです。

ただ行くViewModel。列挙されているあらゆる理由で、すべての方が優れています。

3
Chris Holmes

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

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

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

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

3

常にFormCollectionから抜け出すための回避策がありますlol ..フォームのビューモデル変数にバインドされた非表示フィールドを心ゆくまで持つことができます。

フォームコレクションは、ほとんどがビューモデルの作成の怠fromさから生まれますが、それでもコントローラーで値を取得する方法を理解しようとして時間がかかります:P

非常にシンプルなフォームを持つときに強く型付けされたビューを使用する代わりに、MVCの最初の段階で作成されただけだと思います-誰もがViewBagを使用していた頃:)...それと同じくらい簡単にそれを取り出します。

ビューに複数のフォーム入力がないことを絶対に確信している場合は、使用できますか?おそらくまだ悪い考え..

フォームコレクションの利点について述べている最近の記事は見つかりません。強く型付けされたビューはどこにでもあります。

3
krilovich

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

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

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

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

2

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

アクションパラメーターとしてのカスタムクラスを超えるフォームコレクションの追加の利点は(実際には制限されていません)、可能な限り避ける必要があります。

2