web-dev-qa-db-ja.com

複雑なモデルと部分ビュー-ASP.NET MVC 3のモデルバインディングの問題

サンプルMVC 3アプリケーションには、以下に示すSimpleModelComplexModelの2つのモデルがあります。

public class SimpleModel
{
    public string Status { get; set; }
}

public class ComplexModel
{
    public ComplexModel()
    {
        Simple = new SimpleModel();
    }

    public SimpleModel Simple{ get; set; }
}

このモデルのビューを定義しました:

_SimplePartial.cshtml

@model SimpleModel

@Html.LabelFor(model => model.Status)
@Html.EditorFor(model => model.Status)

およびComplex.cshtml

@model ComplexModel

@using (Html.BeginForm()) {

    @Html.Partial("_SimplePartial", Model.Simple)
    <input type="submit" value="Save" />
}

Statusフィールドにランダムな値を入力してフォームを送信すると、値はモデルにバインドされません。コントローラーアクションでモデルをチェックしているとき、StatusフィールドはNULLです。

[HttpPost]
public ActionResult Complex(ComplexModel model)
{
    // model.Simple.Status is NULL, why ?
}

なぜバインドされていないのですか?モデルを継承したくありません。このような単純なケースでは、カスタムモデルバインダーを作成する必要がありますか?

よろしく。

44
jwaliszko

の代わりに:

@Html.Partial("_SimplePartial", Model.Simple)

Editorテンプレートを使用することをお勧めします。

@model ComplexModel
@using (Html.BeginForm()) 
{
    @Html.EditorFor(x => x.Simple)
    <input type="submit" value="Save" />
}

~/Views/Shared/EditorTemplates/SimpleModel.cshtmlまたは~/Views/Home/EditorTemplates/SimpleModel.cshtml内に単純なパーシャルを配置します。ここで、Homeはコントローラーの名前です。

@model SimpleModel
@Html.LabelFor(model => model.Status)
@Html.EditorFor(model => model.Status)

もちろん、パーシャルをいくつかの特別な場所に置き、慣例に従わない場合(なぜですか?)、場所を指定できます。

@Html.EditorFor(x => x.Simple, "~/Views/SomeUnexpectedLocation/_SimplePartial.cshtml")

その後、すべてが期待どおりに配置されます。

61
Darin Dimitrov

ダニエルホールが彼のブログで提案しているようにViewDataDictionaryTemplateInfoを渡します。ここで、HtmlFieldPrefixはSimpleModelプロパティの名前に設定されます。

 @Html.Partial("_SimplePartial", Model.Simple, new ViewDataDictionary(ViewData)
    {
        TemplateInfo = new System.Web.Mvc.TemplateInfo
        {
            HtmlFieldPrefix = "Simple"
        }
    })
26
toralux