我将尝试让ASP.NET MVC 3从复杂的嵌套对象中生成表单。我发现了一种意外的验证行为,我不确定它是否是DefaultModelBinder中的错误。
如果我有两个对象,我们称之为“父”对象“OuterObject”,并且它有一个类型为“InnerObject”的属性(子对象):
您会发现,当模型被DefaultModelBinder验证时,“InnerObject”中的“Validate”方法会被调用两次,但“OuterObject”中的“Validate”方法根本不会被调用。
如果您从“InnerObject”中删除IValidatableObject,则“OuterObject”上的IValidatableObject将被调用。
这是一个bug吗?还是我应该期望它以这种方式工作?如果我应该期望它,有什么最好的解决方法?
如果我有两个对象,我们称之为“父”对象“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”中的“Validate”方法会被调用两次,但“OuterObject”中的“Validate”方法根本不会被调用。
如果您从“InnerObject”中删除IValidatableObject,则“OuterObject”上的IValidatableObject将被调用。
这是一个bug吗?还是我应该期望它以这种方式工作?如果我应该期望它,有什么最好的解决方法?