Давайте начнем с того, что мы знаем:
Как следует из описания, если у нас есть наши модели:
Модель 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
. Эта проверка вернет сообщение об ошибке, которое не определено для свойства, но поскольку эта проверка является частью сложной модели, она добавляется в ModelState с ключом «ModelB».
Когда вызывается 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
, поэтому его нужно будет отдельно связать в пост-действии и добавить к нашей 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.