ASP.NET MVC - 使用 jQuery 不显眼的验证防止提交无效表单
ASP.NET MVC - prevent submit of invalid form using jQuery unobtrusive validation
我有一个 ASP.NET 项目,它使用 ASP.NET 构建的 jQuery.Validate and the unobtrusive wrapper 自动连接客户端验证。
a) 我绝对有合适的库:jquery.js, jquery.validate.js, & jquery.validate.unobtrusive.js
b) 并且 MVC 渲染引擎肯定是打开的(ClientValidationEnabled
& UnobtrusiveJavaScriptEnabled
在 web.config 的 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>
当运行时,它将执行客户端验证,注意到某些表单元素无效,然后也 post返回服务器。
为什么它不能阻止 post返回状态无效的表单?
问题
当您没有为给定的表单元素包含 @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")
会returnundefined
当我们尝试对未定义的值调用 $.parseJSON
时,就会出现问题。如果抛出错误(但未被捕获),JavaScript 将停滞不前,永远不会到达原始方法 (return false
) 中阻止表单提交的最后一行代码。
解决方案
升级jQuery验证不显眼
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>
我有一个 ASP.NET 项目,它使用 ASP.NET 构建的 jQuery.Validate and the unobtrusive wrapper 自动连接客户端验证。
a) 我绝对有合适的库:jquery.js, jquery.validate.js, & jquery.validate.unobtrusive.js
b) 并且 MVC 渲染引擎肯定是打开的(ClientValidationEnabled
& UnobtrusiveJavaScriptEnabled
在 web.config 的 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>
当运行时,它将执行客户端验证,注意到某些表单元素无效,然后也 post返回服务器。
为什么它不能阻止 post返回状态无效的表单?
问题
当您没有为给定的表单元素包含 @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")
会returnundefined
当我们尝试对未定义的值调用 $.parseJSON
时,就会出现问题。如果抛出错误(但未被捕获),JavaScript 将停滞不前,永远不会到达原始方法 (return false
) 中阻止表单提交的最后一行代码。
解决方案
升级jQuery验证不显眼
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>