我可以在自定义模型绑定器中自动触发模型验证吗?

时间:2011-02-25 15:19:29

标签: asp.net-mvc validation imodelbinder

我有一个复杂的对象,我绑定了一个表单。模型绑定器如下所示:

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的值。

除了我的标题问题,这还提出了几个问题:

  1. TryValidateModel(ModelState)引用ModelState正确验证的表单的同一个实例时,TryValidateModel(form)为什么不验证表单?

  2. 为什么TryValidateModel(form)会导致更新ModelState.IsValid的值?

  3. 一般来说,为什么绑定者负责更新ModelState

1 个答案:

答案 0 :(得分:1)

ModelBinder的职责是将请求中的值绑定到您正在使用的模型中。

ModelState属性只是一个包含模型当前状态的字典。看看modelstate就像一个错误列表。

当您拥有自定义ModelBinder时,您将请求中的值映射到您选择的类中。这将最终成为您的行动方法的参数。

我不同意你的说法,模型绑定器负责更新ModelState,因为ModelBinder在绑定值时运行,在运行TryValidateModel之前它仍然可以具有IsValid = true。

当您稍后运行TryValidateModel(或ValidateModel)时,它将使用您拥有的任何错误更新ModelState属性。您还可以使用不同类型的验证方法(DataAnnotations,IValidatableObject ...)