I have a complex object that I'm binding off of a form. The model binder looks like this:
我有一个复杂的对象,我把它从表格上绑定起来。模型粘结剂是这样的:
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;
}
and it is doing what it's supposed to; I get a correctly populated MyForm
out of it, and a reference to the same MyForm instance is included in the ModelState. However, the form does not get validated using either the DataAnnotations
or my CustomValidation
validation. In order to cause that validation, I have to add a TryValidateModel()
call in my Controller:
它在做它应该做的;我从中得到一个正确填充的MyForm,并且在ModelState中包含了对同一个MyForm实例的引用。但是,使用dataannotation或我的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");
}
Which not only calls into my custom validation, but also updates the value of ModelState.IsValid.
它不仅调用我的自定义验证,而且还更新ModelState.IsValid的值。
In addition to my title question, this raises a couple of questions:
除了我的题目,这还提出了几个问题:
-
Why does
TryValidateModel(ModelState)
not validate the form whenModelState
has a reference to the same instance of the form thatTryValidateModel(form)
correctly validates?为什么当ModelState引用了TryValidateModel(form)正确验证的表单实例时,TryValidateModel(ModelState)不验证表单呢?
-
Why does
TryValidateModel(form)
cause the value ofModelState.IsValid
to be updated?为什么TryValidateModel(表单)会导致ModelState的值。IsValid更新吗?
-
In general, why are the binders responsible for updating
ModelState
?通常,为什么绑定器要负责更新ModelState?
1 个解决方案
#1
1
The ModelBinder's responsibility is to bind values from the request into the model(s) you are using.
ModelBinder的职责是将请求中的值绑定到您正在使用的模型中。
The ModelState property is just a dictionary containing the current state of you models. Look at modelstate like an errorlist.
ModelState属性只是一个包含模型当前状态的字典。将modelstate视为一个错误列表。
When you have a custom ModelBinder you map the values from the request into the class of your choice. That will end up as a parameter into your actionmethod.
当您有一个自定义的ModelBinder时,您可以将请求中的值映射到您所选择的类中。这将作为参数进入actionmethod。
I wouldn't agree with you that modelbinders are responsible for updating the ModelState since the ModelBinder is run when it binds the values, it can still have IsValid=true before you run TryValidateModel.
我不同意您的观点,因为在绑定值时运行ModelBinder,所以在运行TryValidateModel之前,它仍然可以具有IsValid=true。
When you later run the TryValidateModel (or ValidateModel for that matter) it will update the ModelState property with whatever errors you have. You can also use different types to validation methods (DataAnnotations, IValidatableObject...)
当您稍后运行TryValidateModel(或就此而言的ValidateModel)时,它将使用任何错误更新ModelState属性。您还可以使用不同的类型来验证方法(dataannotation, IValidatableObject…)
#1
1
The ModelBinder's responsibility is to bind values from the request into the model(s) you are using.
ModelBinder的职责是将请求中的值绑定到您正在使用的模型中。
The ModelState property is just a dictionary containing the current state of you models. Look at modelstate like an errorlist.
ModelState属性只是一个包含模型当前状态的字典。将modelstate视为一个错误列表。
When you have a custom ModelBinder you map the values from the request into the class of your choice. That will end up as a parameter into your actionmethod.
当您有一个自定义的ModelBinder时,您可以将请求中的值映射到您所选择的类中。这将作为参数进入actionmethod。
I wouldn't agree with you that modelbinders are responsible for updating the ModelState since the ModelBinder is run when it binds the values, it can still have IsValid=true before you run TryValidateModel.
我不同意您的观点,因为在绑定值时运行ModelBinder,所以在运行TryValidateModel之前,它仍然可以具有IsValid=true。
When you later run the TryValidateModel (or ValidateModel for that matter) it will update the ModelState property with whatever errors you have. You can also use different types to validation methods (DataAnnotations, IValidatableObject...)
当您稍后运行TryValidateModel(或就此而言的ValidateModel)时,它将使用任何错误更新ModelState属性。您还可以使用不同的类型来验证方法(dataannotation, IValidatableObject…)