我正在尝试让 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" });
}
}
}
这是内部对象:
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" });
}
}
}
您会注意到我对两者都进行了验证.. 只是一些虚拟验证说某些值不能等于“测试”。
这是将在 (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”中的“Validate”方法会被命中两次,但“OuterObject”中的“Validate”方法根本不会被命中。
如果你从“InnerObject”中取出 IValidatableObject,那么“OuterObject”上的那个就会被击中。
这是一个错误,还是我应该期望它以这种方式工作?如果我应该期望它,最好的解决方法是什么?