2017-03-08 3 views
1

こんにちは、私は現在、ASP.NET MVC 4.5アプリケーションで作業しています。 作成フォームを送信するときに、私の部分ビューからメインビューモデルに入力値をマップする必要があります。私のビュー"Create.cshtml"私は"_SwotPart.cshtml"部分図を呼んでASP.NET MVC 4.5マップフォームビューのメインビューへの部分ビュー

。私はこのように、部分的なビューに私のViewModelの一部を渡す:

Create.cshtml:

@model MyCoolApp.BLL.Models.MainVm 

@foreach (var swot in Model.Swots) 
{ 
     <tr> 
      @foreach (var swotPart in swot.SwotParts) 
      { 
       @Html.Partial("~/Views/Shared/_SwotPart.cshtml", swotPart) 
      } 
     </tr> 
} 

次のように私の部分図は、_SwotPartialに見えます。 cshtml:

<td class="form-group"> 
    @Html.TextAreaFor(model => model.Label, htmlAttributes: new { Name = nameField, ID = nameField, @class = "form-control", placeholder = Model.SwotTypeId.GetLabel() }) 
</td> 

とにかく、私のフォームを提出すると、部分ビューからの値は決してコントローラに到着しません。

これを正しくマップする方法はありますか?

ありがとうございます!

答えて

0

この問題は、現在達成しようとしている方法で生成される入力名に問題があります。 Razorは、正しい入力名を生成するために、リスト全体のコンテキスト、または少なくとも項目の位置を必要とします。言い換えれば、(警告付き)あなたの問題を解決する最も簡単な方法は次のとおりです。

@for (var i = 0; i < Model.Swots.Count(); i++) 
{ 
    ... 

    @for (var j = 0; j < Model.Swots[i].SwotParts.Count(); j++) 
    { 
     if (Model.Swots[i].SwotParts[j].SwotTypeId == SwotType.InternalHelpful || Model.Swots[i].SwotParts[j].SwotTypeId == SwotType.InternalHarmful) 
     { 
      @Html.Partial("~/Views/Shared/_SwotPart.cshtml", Model.Swots[i].SwotParts[j]) 
     } 
    } 

    ... 

その後、部分的にで動作するように正しいコンテキストを持っており、あなたの入力はmodelbinderがされる、Swots[0].SwotParts[0].Labelのように名前が付けられます。一緒に働くことができます。

ただし、このリストは2つのループに分割されています。それは、モデル内のアイテムの位置の全体的なコンテキストを効果的に混乱させているので、まだ動作しません。その後

public class SwotVm 
{ 
    ... 

    public List<SwotPartVm> InternalSwotParts { get; set; } 
    public List<SwotPartVm> ExternalSwotParts { get; set; } 
} 

あなたは、単に個々のリストを反復処理することができ、かつ値:それを修正するには、あなたはあなたのビューから、このビジネスロジックを削除することができますように、とにかく優れているモデルであなたのリストを分割する必要があります自然に適切なリストに投稿されます。

特定のクラスタイプのフィールドをレンダリングするために部分的に使用しているとすれば、エディタテンプレートを作成する方が良いでしょう。あなたは、単にビューにあなたの部分のコードを移動した場合:Views\Shared\EditorTemplates\SwotPartVm.cshtml、その後、あなたのメインビューで、あなただけ行うことができます。

明らかずっときれいだし、あなたが SwotVm.cshtmlを追加することによって、さらにこの概念を取ることができ
@for (var i = 0; i < Model.Swots.Count(); i++) 
{ 
    ... 

    <tr> 
     <th class="swot-heading">Internal</th> 
     @Html.EditorFor(m => m.Swots[i].InternalSwotParts) 
    </tr> 
    <tr> 
     <th class="swot-heading">External</th> 
     @Html.EditorFor(m => m.Swots[i].ExternalSwotParts) 
    </tr> 
} 

@Html.EditorFor(m => m.Swots) 

注:あなただけで、コードのも、この少しを交換できるようにエディタテンプレートは、あなたのSwotVm.cshtmlエディタのテンプレートでは、あなただけの単一SwotVmためのコードが含まれます。言い換えれば、forステートメントは含まれません。

+0

この素晴らしいと詳細な説明のためのクリスおかげで! – TimHorton

0

アプリケーションが投稿された値を適切に解析し、それをビューモデルにバインドするために、投稿されたフォームデータの名前は、同じようにする必要があります。

SWOTS [X1] .swotParts [x2は】x1は0から各SWOTためまでの範囲の数である

を.LABEL。 ここで、x2はスワットの各スワットパーツの0以上の範囲の数値です。

今投稿すると、フォームデータ名はというラベルになります。

の代わりに:

@Html.TextAreaFor(model => model.Label, htmlAttributes: new { Name = nameField, ID = nameField, @class = "form-control", placeholder = Model.SwotTypeId.GetLabel() }) 

試してみてください。

<textarea name="swots[x1].swotParts[x2].label" class="form-control" placeholder="@Model.SwotTypeId.GetLabel()" >@Model.Label</textarea> 

が数字でX1とX2を置き換えることを忘れないでください。

コレクションへのモデルバインディングについては、こちらをご覧ください。

http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx

+0

あなたの助けと良いアイデアに感謝します! – TimHorton

関連する問題