关于c#:如果不能将IValidatableObject的MVC实现用于对象的完全验证,那又有什么意义呢?

What is the point of the MVC implementation of IValidatableObject if it can't be used to perform full validation of the object?

请有人帮帮我,因为我一口气验证控制器动作中绑定的对象确实很麻烦。

我认为IValidatableObjectValidate()方法将在每次绑定时触发,但这不是真的...如果存在一般模型错误,则不会触发。

这使我想知道,如何对对象执行完整的复杂验证并返回完整的验证错误集?没有人想要在网络表单上修复所有报告的错误,然后提交以将更多错误返回给他们。

我以为我也许可以在Validate()方法中执行所有验证,但是事实并非如此,因为似乎没有办法摆脱对模型的常规验证。例如,如果您尝试将string绑定到int,它不会默默地失败,它会添加模型验证错误,然后不会触发Validate对对象执行进一步的验证。铅>

所以我不能仅使用一种方法执行所有验证:

  • 使用验证属性进行常规模型验证

    • 原因
    • 无法执行高级验证,例如基于模型中其他值的条件验证
    • 除了单独的字段验证之外,它还不执行其他任何操作
  • 实现IValidatableObject并在Validate()方法中执行完全验证

    • 原因
    • 没有逃脱或"关闭"常规模型验证,以使其静默失败,因此我可以对对象执行完全验证
    • 如果常规模型验证以任何方式失败(例如绑定失败),IValidatebleObject并不总是会触发
  • 无论绑定是否成功,如何一次性验证对象?

    无论绑定成功如何,IValidatableObject为什么不触发Validation()方法?


    您似乎遇到的问题是,由于不同的原因,验证在框架的不同部分进行。

    首先,进行客户端验证。如果您的所有字段都具有不干扰的客户端验证,则所有验证将立即在客户端上进行。

    第二个是模型绑定。如果尝试将项目绑定到其模型条目时发生错误,则这些项目将首先失败。例如,如果您尝试将字符串" xxx"绑定到DateTime,它将抛出验证错误,因为它无法将" xxx"转换为DateTime。而且,由于DateTime是不可为空的,因此不能简单地在其中放置null。

    第三项是您实际的服务器端数据属性验证。如果您只有部分客户端验证(意味着并非所有字段都具有客户端验证),那么您可能会遇到奇怪的情况,即它会为客户端的某些项目抛出验证错误,然后在用户解决这些问题并提交之后,服务器端验证发现错误,您将抛出更多错误。

    最后,调用IValidatableObject。不幸的是,IValidatableObject没有客户端验证,因此您将不得不为这些字段创建客户端验证,或者完全禁用客户端验证才能一次完成所有服务器端验证。

    IValidatableObject是一个相当通用的接口,并且在不仅仅是MVC的更多地方使用。 MVC之所以使用它,是因为它是一个方便的现有接口。并且,在将客户端验证添加到MVC之前就已经存在。更好的方法是创建一个实现客户端验证的ValidationAttribute派生属性,然后提供适当的javascript插件以进行不干扰验证。

    如果在任何步骤中验证均失败,则不会继续进行下一步。即,如果客户端验证失败,则不会调用服务器端。如果数据属性失败,则不会调用IValidatableObject。

    解决此问题的一种方法:

    如何强制MVC验证IValidatableObject


    想到了几种不同的选择。如果您需要在客户端上进行复杂的验证,则使用Angular或Knockout之类的javascript框架将是有益的,否则,如果添加jQuery验证插件,则可能会失败:
    http://jqueryvalidation.org/

    也许还值得回顾一下ModelStateDictonary方法,看看这些方法是否有帮助-例如在控制器中为复杂的验证方案手动调用ModelState.AddModelError。

    http://msdn.microsoft.com/zh-cn/library/system.web.mvc.modelstatedictionary_methods(v = vs.118).aspx

    示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
     bool valid = true;

     if (string.IsNullOrEmpty(model.JobNumber))
     {
         ModelState.AddModelError("jobNumber","Please enter job number");
         valid = false;
     }

     return View(model);