ASP.NET MVC - 使用jQuery不显眼的验证来阻止提交无效表单

时间:2022-11-23 19:58:09

I have an ASP.NET project that automatically wires up client side validation using jQuery.Validate and the unobtrusive wrapper built by ASP.NET.

我有一个ASP.NET项目,它使用jQuery.Validate和ASP.NET构建的不显眼的包装器自动连接客户端验证。

a) I definitely have the appropriate libraries: jquery.js, jquery.validate.js, & jquery.validate.unobtrusive.js

a)我肯定有相应的库:jquery.js,jquery.validate.js和jquery.validate.unobtrusive.js

b) And the MVC rendering engine is definitely turned on (ClientValidationEnabled & UnobtrusiveJavaScriptEnabled in the appSettings section of the web.config)

b)MVC渲染引擎肯定已打开(web.config的appSettings部分中的ClientValidationEnabled和UnobtrusiveJavaScriptEnabled)

Here's a trivial example where things are broken:

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

Model:

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

Controller:

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

View:

@model validation.Models.Person

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

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

This generates the following client side markup:

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

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

When run it will perform the client side validation, noting that some form elements are invalid, but then also post back to the server.

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

Why is it not preventing postback on a form with an invalid state?

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

1 个解决方案

#1


6  

The Problem

It turns out this happens when you don't include a @Html.ValidationMessageFor placeholder for a given form element.

事实证明,当您没有为给定表单元素包含@ Html.ValidationMessageFor占位符时会发生这种情况。

Here's a deeper dive into where the problem occurs:

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

When a form submits, jquery.validate.js will call the following methods:

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

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

Where errorPlacement will call this method in jquery.validate.unobtrusive.js:

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;

When we don't add a placeholder for the validation message, $(this).find(...) won't find anything.

当我们不为验证消息添加占位符时,$(this).find(...)将找不到任何内容。

Meaning container.attr("data-valmsg-replace") will return undefined

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

This poses a problem is when we try to call $.parseJSON on an undefined value. If an error is thrown (and not caught), JavaScript will stop dead in its tracks and never reach the final line of code in the original method (return false) which prevents the form from submitting.

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

The Solution

Upgrade jQuery Validate Unobtrusive

Newer versions of jQuery Validate handle this better and check for nulls before passing them to $.parseJSON

较新版本的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;

Add ValidationMessageFor

To address the core problem, for every input on your form, make sure to include:

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

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

Which will render the following client side markup

这将呈现以下客户端标记

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

#1


6  

The Problem

It turns out this happens when you don't include a @Html.ValidationMessageFor placeholder for a given form element.

事实证明,当您没有为给定表单元素包含@ Html.ValidationMessageFor占位符时会发生这种情况。

Here's a deeper dive into where the problem occurs:

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

When a form submits, jquery.validate.js will call the following methods:

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

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

Where errorPlacement will call this method in jquery.validate.unobtrusive.js:

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;

When we don't add a placeholder for the validation message, $(this).find(...) won't find anything.

当我们不为验证消息添加占位符时,$(this).find(...)将找不到任何内容。

Meaning container.attr("data-valmsg-replace") will return undefined

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

This poses a problem is when we try to call $.parseJSON on an undefined value. If an error is thrown (and not caught), JavaScript will stop dead in its tracks and never reach the final line of code in the original method (return false) which prevents the form from submitting.

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

The Solution

Upgrade jQuery Validate Unobtrusive

Newer versions of jQuery Validate handle this better and check for nulls before passing them to $.parseJSON

较新版本的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;

Add ValidationMessageFor

To address the core problem, for every input on your form, make sure to include:

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

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

Which will render the following client side markup

这将呈现以下客户端标记

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