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

发布于 2024-10-19 05:52:57 字数 1475 浏览 7 评论 0原文

我有一个复杂的对象,我正在将其绑定到表单上。模型绑定器看起来像这样:

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,并且对同一 MyForm 实例的引用包含在 ModelState 中。但是,该表单未使用 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 的值。

除了我的标题问题之外,这还引发了几个问题:

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

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

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

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:

  1. 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?

  2. Why does TryValidateModel(form) cause the value of ModelState.IsValid to be updated?

  3. In general, why are the binders responsible for updating ModelState?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

陈年往事 2024-10-26 05:52:57

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

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

当您有自定义 ModelBinder 时,您可以将请求中的值映射到您选择的类中。这最终将作为您的操作方法的参数。

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

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

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...)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文