ASP.NET MVC - 使用jQuery不引人注意的验证来阻止提交无效表单

时间:2016-10-07 13:51:14

标签: asp.net asp.net-mvc jquery-validate unobtrusive-validation

我有一个ASP.NET项目,它使用jQuery.Validate和ASP.NET构建的unobtrusive wrapper自动连接客户端验证。

a)我肯定有合适的库:jquery.jsjquery.validate.js,& jquery.validate.unobtrusive.js

b)MVC渲染引擎肯定在web.config的ClientValidationEnabled部分开启(UnobtrusiveJavaScriptEnabled& appSettings

这是一个简单的例子,其中的事情被打破了:

模型

public class Person
{
    [Required]
    public string Name { get; set; }
}

控制器

public ActionResult Edit()
{
    Person p = new Person();
    return View(p);
}

查看

@model validation.Models.Person

@using (Html.BeginForm()) {
    @Html.ValidationSummary(false)

    @Html.LabelFor(model => model.Name)
    @Html.EditorFor(model => model.Name)
}

这将生成以下客户端标记:

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.15.1/jquery.validate.js"></script>
<script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.validate.unobtrusive.js"></script>
    
<form action="/Person" method="post">
  <div class="validation-summary-valid" data-valmsg-summary="true">
    <ul><li style="display:none"></li></ul>
  </div>
  <label for="Name">Name</label>
  <input data-val="true" data-val-required="The Name field is required." id="Name" name="Name" type="text" value="" />
  <input type="submit" value="Save" />
</form>

运行时,它将执行客户端验证,注意某些表单元素无效,但发回服务器。

为什么不阻止状态无效的表单上的回发?

1 个答案:

答案 0 :(得分:6)

问题

事实证明,如果您没有为给定的表单元素添加@Html.ValidationMessageFor占位符,就会发生这种情况。

以下是对问题发生位置的深入探讨:

表单提交时,jquery.validate.js将调用以下方法:

validate: function( options ) {
  form: function() {
    showErrors: function(errors) {
      defaultShowErrors: function() {
        showLabel: function(element, message) {
          this.settings.errorPlacement(label, $(element) )

errorPlacement将在jquery.validate.unobtrusive.js中调用此方法:

function onError(error, inputElement) { 
   var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"),
       replace = $.parseJSON(container.attr("data-valmsg-replace")) !== false;

如果我们没有为验证邮件添加占位符,$(this).find(...)将找不到任何内容。

含义container.attr("data-valmsg-replace")将返回undefined

当我们尝试在未定义的值上调用$.parseJSON时,会出现问题。如果抛出错误(并且未被捕获),JavaScript将停止在其轨道中,并且永远不会到达原始方法(return false)中的最后一行代码,这会阻止表单提交。

解决方案

升级jQuery Validate Unobtrusive

Newer versions of jQuery Validate更好地处理这个并在将它们传递给$.parseJSON

之前检查空值
function onError(error, inputElement) {  // 'this' is the form element
    var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"),
        replaceAttrValue = container.attr("data-valmsg-replace"),
        replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null;

添加ValidationMessageFor

要解决核心问题,请对表单上的每个输入确保包括:

@Html.ValidationMessageFor(model => model.Name)

这将呈现以下客户端标记

<span class="field-validation-valid" data-valmsg-for="Name" data-valmsg-replace="true"></span>

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.15.1/jquery.validate.js"></script>
<script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.validate.unobtrusive.js"></script>
    
<form action="/Person" method="post">
  <div class="validation-summary-valid" data-valmsg-summary="true">
    <ul><li style="display:none"></li></ul>
  </div>
  <label for="Name">Name</label>
  <input data-val="true" data-val-required="The Name field is required." id="Name" name="Name" type="text" value="" />
  <span class="field-validation-valid" data-valmsg-for="Name" data-valmsg-replace="true"></span>
  <input type="submit" value="Save" />
</form>