我可以在自定义模型活页夹内自动触发模型验证吗?
我有一个复杂的对象,我绑定了一个窗体。模型绑定器如下所示:我可以在自定义模型活页夹内自动触发模型验证吗?
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
验证进行验证。为了使该验证,我要在我的控制器中添加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
?
ModelBinder的责任是将请求中的值绑定到您正在使用的模型中。
ModelState属性只是一个包含模型当前状态的字典。查看模型状态就像一个错误列表。
如果您有自定义的ModelBinder,则可以将请求中的值映射到您选择的类中。这将最终成为你的行动方法的一个参数。
我不同意模型绑定器负责更新ModelState,因为ModelBinder在绑定这些值时运行,它在运行TryValidateModel之前仍然可以有IsValid = true。
当您稍后运行TryValidateModel(或针对此问题的ValidateModel)时,它将更新ModelState属性,并显示您拥有的任何错误。您还可以使用不同类型的验证方法(DataAnnotations,IValidatableObject ...)
感谢您的回复。不过,我不同意你的一些观点。首先,'ModelBinder'不是必需的,以填充'ModelState'对象。但是,我的经验是,如果'ModelBinder'没有填充'ModelState'对象,那么绑定模型不会包含在验证中。如果有办法让请求上下文将绑定对象放入'ModelState'中,那么这可能是我题目问题的答案。 – arootbeer 2011-03-11 03:47:44
我意识到'TryValidateModel'或'ValidateModel'会更新'ModelState'错误。我的观点是,MVC运行时似乎在我的自定义模型绑定器有机会将绑定模型放置在“ModelState”中之前调用这些方法(或类似的方法)**,这需要我明确地调用它们,感觉到我像一个不正确的操作顺序。我期望操作顺序是'接收请求 - >绑定参数到模型 - >验证模型 - >处理请求',但在这种情况下'验证模型'是'处理请求'的一部分。 – arootbeer 2011-03-11 03:54:06