私たちが知っていることから始めましょう:
説明が示すように、モデルがある場合:
モデルA:
public class A
{
public B ModelB { get; set; }
}
モデルB:
public class B : IValidatableObject
{
public string Name { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
List<ValidationResult> errors = new List<ValidationResult>();
if (string.IsNullOrEmpty(Name)) {
errors.Add(new ValidationResult("Please enter your name"));
}
return errors;
}
}
そして私たちの見解:
@model A
@Html.ValidationSummary(true)
@using (Html.BeginForm())
{
@Html.EditorFor(model => model.ModelB.Name)
<input type="submit" value="submit" />
}
次に、エディターは次の行を出力します。
<input class="text-box single-line" id="ModelB_Name" name="ModelB.Name" type="text" value="" />
ポストアクションを次のように定義している場合:
[HttpPost]
public ActionResult Index(A model)
{
if (ModelState.IsValid)
{
return RedirectToAction("NextAction");
}
return View();
}
次に、A
モデルにバインドするときに、が検索して正常にバインドするDefaultModelBinder
名前のプロパティModelB.Name
を探します。
ただし、モデルDefaultModelBinder
に対して実行されるモデル検証は、A
モデルに対して定義された検証を呼び出しますB
。この検証は、プロパティに対して定義されていないエラーメッセージを返しますが、この検証は複雑なモデルの一部であるため、「ModelB」のキーを使用してModelStateに追加されます。
が呼び出されると、ValidationSummary
空白のキーが検索されます(つまり、プロパティではなくモデルに対して定義されます)。空白キーが存在しないため、エラーは表示されません。
EditorTemplate
簡単な回避策として、B
モデルのを定義できます。
ビューを含むフォルダーで、という名前のフォルダーを定義しEditorTemplates
、この中でモデルと同じ名前のビューを作成します(B.cshtml
私の場合など)。エディタテンプレートの内容は次のように定義されます。
@model MvcApplication14.Models.B
@Html.EditorFor(m => m.Name)
次に、メインビューを次のEditorFor
ように変更します。
@Html.EditorFor(model => model.ModelB, null, "")
「」は、エディターテンプレートによって出力されるフィールドに、フィールドの前に名前が付いていないことを指定します。したがって、出力は次のようになります。
<input class="text-box single-line" id="Name" name="Name" type="text" value="" />
ただし、これによりのバインドが防止ModelB
されるため、postアクションで個別にバインドし、A
モデルに追加する必要があります。
[HttpPost]
public ActionResult Index(A modelA, B modelB)
{
modelA.ModelB = modelB;
if (ModelState.IsValid)
{
return RedirectToAction("NextAction");
}
return View();
}
これで、modelB
がバインドされると、検証メッセージがModelState
キー「」でに書き込まれます。@ValidationMessage()
したがって、これをルーチンで表示できるようになりました。
警告:上記の回避策は、modelB
がと同じフィールド名を持たないことを前提としていmodelA
ます。たとえば、modelB
との両方にフィールドmodelA
がある場合、はフィールドを正しい同等物にバインドしない可能性があります。たとえば、モデルに次の名前のフィールドもある場合は、次のようにビューに書き込む必要があります。Name
DefaultModelBinder
A
Name
@Html.EditorFor(model => model.Name, null, "modelA.Name")
正しくバインドされていることを確認します。
うまくいけば、これにより、MVC3フレームワーク内ですでに定義されているメソッドを使用して目的の結果を達成できるはずです。