Reputation: 8792
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:
[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.
In addition to my title question, this raises a couple of questions:
Why does TryValidateModel(ModelState)
not validate the form when ModelState
has a reference to the same instance of the form that TryValidateModel(form)
correctly validates?
Why does TryValidateModel(form)
cause the value of ModelState.IsValid
to be updated?
In general, why are the binders responsible for updating ModelState
?
Upvotes: 2
Views: 2672
Reputation: 391
The ModelBinder's responsibility is to bind values from the request into the model(s) you are using.
The ModelState property is just a dictionary containing the current state of you models. Look at modelstate like an errorlist.
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.
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.
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...)
Upvotes: 1