Я пытаюсь заставить ASP.NET MVC 3 генерировать формы из сложных вложенных объектов. Я обнаружил одно поведение проверки, которое было неожиданным, и я не уверен, является ли это ошибкой в DefaultModelBinder или нет.
Если у меня есть два объекта, давайте назовем «родительский» один «OuterObject», и у него есть свойство типа «InnerObject» (дочерний):
public class OuterObject : IValidatableObject
{
[Required]
public string OuterObjectName { get; set; }
public InnerObject FirstInnerObject { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (!string.IsNullOrWhiteSpace(OuterObjectName) && string.Equals(OuterObjectName, "test", StringComparison.CurrentCultureIgnoreCase))
{
yield return new ValidationResult("OuterObjectName must not be 'test'", new[] { "OuterObjectName" });
}
}
}
Вот InnerObject:
public class InnerObject : IValidatableObject
{
[Required]
public string InnerObjectName { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (!string.IsNullOrWhiteSpace(InnerObjectName) && string.Equals(InnerObjectName, "test", StringComparison.CurrentCultureIgnoreCase))
{
yield return new ValidationResult("InnerObjectName must not be 'test'", new[] { "InnerObjectName" });
}
}
}
Вы заметите валидацию, которую я поставил обоим ... просто фиктивная проверка, чтобы сказать, что какое-то значение не может быть равно "test".
Вот представление, которое будет отображаться в (Index.cshtml):
@model MvcNestedObjectTest.Models.OuterObject
@{
ViewBag.Title = "Home Page";
}
@using (Html.BeginForm()) {
<div>
<fieldset>
<legend>Using "For" Lambda</legend>
<div class="editor-label">
@Html.LabelFor(m => m.OuterObjectName)
</div>
<div class="editor-field">
@Html.TextBoxFor(m => m.OuterObjectName)
@Html.ValidationMessageFor(m => m.OuterObjectName)
</div>
<div class="editor-label">
@Html.LabelFor(m => m.FirstInnerObject.InnerObjectName)
</div>
<div class="editor-field">
@Html.TextBoxFor(m => m.FirstInnerObject.InnerObjectName)
@Html.ValidationMessageFor(m => m.FirstInnerObject.InnerObjectName)
</div>
<p>
<input type="submit" value="Test Submit" />
</p>
</fieldset>
</div>
}
.. и, наконец, вот HomeController:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new OuterObject();
model.FirstInnerObject = new InnerObject();
return View(model);
}
[HttpPost]
public ActionResult Index(OuterObject model)
{
if (ModelState.IsValid)
{
return RedirectToAction("Index");
}
return View(model);
}
}
Что вы обнаружите, так это то, что когда модель проверяется с помощью DefaultModelBinder, метод «Проверка» в «InnerObject» получает двойное попадание, но метод «Проверка» в «OuterObject» вообще не выполняется.
Если вы удалите IValidatableObject из «InnerObject», то попадет в «OuterObject».
Это ошибка, или я должен ожидать, что она будет работать таким образом? Если я ожидаю, что лучший обходной путь?