我有一个复杂的对象,我绑定了一个表单。模型绑定器如下所示:
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var form = new MyForm();
var myObject = ...; //try to load up the object
/* logic to populate values on myObject */
form.MyObject = myObject;
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, new ValueProviderResult(form, "", CultureInfo.CurrentUICulture));
return form;
}
它正在做它应该做的事情;我从中获得了正确填充的MyForm
,并且ModelState中包含对同一MyForm实例的引用。但是,表单无法使用DataAnnotations
或我的CustomValidation
验证进行验证。为了进行验证,我必须在我的Controller中添加TryValidateModel()
调用:
[HttpPost]
public ActionResult ProcessMyForm(MyForm form)
{
//ModelState has the MyForm instance inside of it
//TryValidateModel(ModelState); //this does not work
TryValidateModel(form); //this works
if (!ModelState.IsValid)
{
return View("Complete", form);
}
return RedirectToAction("Index");
}
这不仅会调用我的自定义验证,还会更新ModelState.IsValid的值。
除了我的标题问题,这还提出了几个问题:
当TryValidateModel(ModelState)
引用ModelState
正确验证的表单的同一个实例时,TryValidateModel(form)
为什么不验证表单?
为什么TryValidateModel(form)
会导致更新ModelState.IsValid
的值?
一般来说,为什么绑定者负责更新ModelState
?
答案 0 :(得分:1)
ModelBinder的职责是将请求中的值绑定到您正在使用的模型中。
ModelState属性只是一个包含模型当前状态的字典。看看modelstate就像一个错误列表。
当您拥有自定义ModelBinder时,您将请求中的值映射到您选择的类中。这将最终成为您的行动方法的参数。
我不同意你的说法,模型绑定器负责更新ModelState,因为ModelBinder在绑定值时运行,在运行TryValidateModel之前它仍然可以具有IsValid = true。
当您稍后运行TryValidateModel(或ValidateModel)时,它将使用您拥有的任何错误更新ModelState属性。您还可以使用不同类型的验证方法(DataAnnotations,IValidatableObject ...)