2011-12-14 5 views
3

POSTアクションのための別のViewModel:ASP.net MVC - 私はこれに似たビューモデルを持っている私のMVCアプリケーションで

public class ComplexViewModel 
{ 
    public ComplexDetailsViewModel Details1 { get; set; } 
    public ComplexDetailsViewModel Details2 { get; set; } 
} 

public class ComplexDetailsViewModel 
{ 
    public int Id { get; set; } 
    public string DisplayValue1 { get; set; } 
    public string DisplayValue2 { get; set; } 
    // ... 
} 
私はもともと私の見解では、次のやっていた

@Html.HiddenFor(model => model.Details1.Id) 
@Html.HiddenFor(model => model.Details2.Id) 

@Html.DisplayFor(model => model.Details1.DisplayValue1) 
... 

私はコントローラにフルモデルをPOSTします:

public ActionResult Post(ComplexViewModel model) 

私は実際にComplexViewModからは何もする必要はありません同上値を除くエルので、私はデータを掲示するために特別に使用される別のビューモデルを作成することにしました:

public class PostViewModel 
{ 
    public int Details1Id { get; set; } 
    public int Details2Id { get; set; } 
} 

public ActionResult Post(PostViewModel model) 

問題は、今私の@HiddenFor(model => model.Details1.Id)が実際にPOSTされます何もないので、私のPOSTモデルにマップされないということです。

HiddenForヘルパーを使用しているときに、私のPOSTモデルと私のGETモデルに別々の構造を持たせる方法はありますか?

答えて

1

Htmlヘルパーを使用する代わりに、非表示入力のHTMLを手書きで入力してください。

<input type="hidden" id="Details1Id" value="@Model.Details1.Id"/> 
<input type="hidden" id="Details2Id" value="@Model.Details1.Id"/> 

更新

私は似た何かをすることの問題がありました。私は私の見解でフォーム関連のプロパティを平坦化してしまった。 Automapperは他のオブジェクトからビューへのマッピングを簡単にし、階層を平坦化することができます。これを行うと、新しいビューがこのようになります。

public class ComplexViewModel   
{   
    public long Details1Id { get; set; }   
    public string Details1Name { get; set; } 
    public long Details2Id { get; set; }  
    public string Details2Name { get; set; }  
} 
+0

私はこれを行うことができることを知っていましたが、私はまだヘルパーを使用する方法があることを望んでいました。しかし、これが当てはまるとは思われません。 – Dismissile

+0

これを行うには@ Html.HiddenFor()の代わりに@ Html.Hiddenを使用できます。 – hawkke

+1

はい、私はHiddenForを使うことを望んでいました。自動的に入れ子になったテンプレートのプレフィックスを追加するからです。 – Dismissile

5

POSTバージョンのすべてのデータを使用していないという理由だけで別のモデルを作成する必要はありません。それを簡単に保つのはいかがですか?

これは、それがどのように動作するかを示します。

あなたの投稿の詳細ビューが強く、特定のビューモデルに入力する必要があります。あなたのコントローラーには、たとえばPostという名前の2つのアクション結果があり、1つは[HTTPGET]属性で装飾されていて、投稿するアクションは[HTTPPOST]属性で装飾されています。さらに、getメソッドはpost idなどのパラメータを取る必要があり、postメソッドはモデルをパラメータとして取得する必要があります。 ModelState.IsValid:あなたはこのブール値を使用することができ、あなたのコントローラで今

public class ComplexDetailsViewModel 
{ 
    [Required]//Works for just the Id property 
    public int Id { get; set; } 
    public string DisplayValue1 { get; set; } 
    public string DisplayValue2 { get; set; } 
    // ... 
} 

:正しくあなたがそうのようなあなたのクラスのプロパティを飾ることができ、サーバー側の検証を強制するために

。基本的にJavaScriptがオフになっていて、モデルがIdで掲載されていない場合、モデルは無効になります。

このパターンは非常に強力で、クライアント側とサーバー側の検証を迅速に実行できます。もちろん、クライアント側の検証では、すぐにjQueryを使用してバリデータを簡単に拡張できます。あなたは非常に迅速にAJAX検証を行うこともできます。私が私のフォームを構築するとき、私はそれが正しいことをする時間が全くかからないので、検証に関してはどこでも犠牲にしません。

ビューだけ強く一つのモデルに入力することができます:あなたの元の質問には答えること

。あるモデルでビューを読み込んで別のモデルに投稿することはできません(私が知る限り)。私はあなたがそれをやろうとしているなら、あなたの問題はあなたのモデルを構築した方法にあると思います。

+0

私は、POSTモデルの単純さが好きです。なぜなら、私のバリデーターを使いやすくするからです。複雑なモデルを使う代わりに、簡単に扱える2つの整数だけを持つことができます。 – Dismissile

+0

@Dismissile IDだけで検証者を動作させる方法の例を示すために、私の答えを更新します。 –

+0

私はそれを書いた元の方法で作業しているバリデーターを持っており、私はそれらを気に入らない。私はそれをもっときれいにするためにモデルを書き直しました。私はモデルの仕方に満足しています。ヘルパーを使うことが可能かどうかを知りたかったので、彼らは別のモデルプロパティに "マップ"できます。 – Dismissile

1

モデルはより似ている必要があります。あなたの "View"モデルにはクラスプロパティがあり、 "Post"モデルにはクラスプロパティはありません。クラスプロパティの名前とプロパティが一致しない場合は、モデルバインダにバインドされません。 ViewPost間で同じモデルを使用していない大きな問題が検証され

public class ComplexViewModel 
{ 
    public ComplexDetailsViewModel Details1 { get; set; } 
    public ComplexDetailsViewModel Details2 { get; set; } 
} 

public class ComplexDetailsViewModel : PostDetailsModel 
{ 
    public string DisplayValue1 { get; set; } 
    public string DisplayValue2 { get; set; } 
} 

public class PostModel 
{ 
    public PostDetailsModel Details1 { get; set; } 
    public PostDetailsModel Details2 { get; set; } 
} 

public class PostDetailsModel 
{ 
    public int Id { get; set; } 
} 

:ような何かを試してみてください。検証を変更する場合はどうなりますか(クライアント側とサーバー側の組み込みのMVC検証を使用することを前提とします)。今は両方のモデルを変更する必要があります!ああ待って...ないあなたは...

public interface MyValidation 
{ 
    [required] 
    public int id { get; set; } 
} 

は、単にあなたのクラスにこれらの検証を追加しないでください: (たmetadataTypeは、検証に使用するためにどのようなMVCを伝えます)

[MetadataType(typeof(MyValidation))] 
public class ComplexDetailsViewModel .... 

[MetadataType(typeof(MyValidation))] 
public class PostDetailsModel .... 

これは確かだろう私は、ビューとポストバックの間に2つの異なるモデルを使用することを誰も推奨しません。この場合、私は彼らが違うべきである理由はまったくありません。

0

簡単:ビューのビューモデルをコントローラのポストモデルから継承するだけです。その後、あなたのHiddenForメソッドを使って、あなたが投稿しようとしているプロパティが基本クラス(ポストモデル)にあることを確認する必要があります。

関連する問題