我以为我已经为 MVC Web 应用程序使用 jQuery Unobtrusive Validation 设置了一个非常安全的设置,但最近的一个错误让我非常困惑。
我希望所有验证都保持一致,因此使用远程验证属性和控制器方法来涵盖唯一电子邮件/用户名检查等内容。我很早就发现,在您的呼叫中导致误报的服务器端不需要太多延迟,form.valid()
因此在最终输出错误消息或提交表单之前,破解了一个待处理的验证检查和一个等待验证完成的时间间隔.
下面的代码绑定了 onclick 函数并关闭了表单的 onkeyup 验证:
$(document).ready(function () {
// Bind events to buttons so they can be removed later
$('#btnSave').click(function () {
SaveEntry();
});
$('#btnCancel').click(function () {
$('#dialog-Timesheet').dialog('close');
});
var $form = $("#btnSave").closest("form");
// Just something I was trying..
$.validator.unobtrusive.parse($form);
// Find the validator and turn temporarily turn of onkeyup validation to prevent user making the form valid before the remote validation is complete
var validator = $form.data("validator");
// Seems to work with the below on its own but keyup still fires validation later
validator.settings.onkeyup = false;
});
然后我有先前绑定的SaveEntry()
方法,它找到表单,找到它的验证器,并使用一个间隔,在最终检查表单并输出错误消息或提交 ajax 请求之前检查是否有任何待处理的验证请求:
function SaveEntry() {
var $form = $("#btnSave").closest("form");
var validator = $form.data("validator");
var closeButton = "<br/><input type='button' value='OK' style='font-size:small; font-weight:bold; float:right;' onclick=\"$('#dialog-Timesheet').dialog('close');\" class='greenbutton' />";
var errorMessage = "";
var successMessage = "";
// Starts the remote validation checks
if ($form.valid()) {
}
// Call function every 30 milliseconds
interval = setInterval(pendingValidationComplete, 30);
// Saves or validates as long as no validation pending
function pendingValidationComplete() {
// This only runs once remote validation is finished
if (validator.pendingRequest === 0) {
clearInterval(interval);
//Force validation to present to user (this will not retrigger remote validation)
if ($form.valid()) {
// If is valid then submit
if ($('#TimeSheetEntryID').val() > 0) {
$.ajax(
{
type: "POST",
url: "/Timesheet/EditEntry",
data: "id=" + $('#Id').val() + "&" + $form.serialize(),
success: function (result) {
ShowData("fromCookie", "current");
successMessage = "<div style='text-align:center; margin-top: 10px;'>" + result + "<div>";
$openDialog.html(successMessage + closeButton);
},
error: function (jqXhr, textStatus, errorThrown) {
// Populate dialog with error message and button
errorMessage = "<div style='text-align:center'>Error '" + jqXhr.status + "' (Status: '" + textStatus + "', errorThrown: '" + errorThrown + "')<div>";
$openDialog.html(errorMessage + closeButton);
}
});
} else {
$.ajax(
{
type: "POST",
url: "/Timesheet/CreateEntry",
data: $form.serialize(),
success: function (result) {
ShowData("fromCookie", "current");
successMessage = "<div style='text-align:center; margin-top: 10px;'>" + result + "<div>";
$openDialog.html(successMessage + closeButton);
},
error: function (jqXhr, textStatus, errorThrown) {
// Populate dialog with error message and button
errorMessage = "<div style='text-align:center'>Error '" + jqXhr.status + "' (Status: '" + textStatus + "', errorThrown: '" + errorThrown + "')<div>";
$openDialog.html(errorMessage + closeButton);
}
});
}
}
//else { alert("invalid"); }
}
//else { alert("NOT YET"); }
};
}
所以,这一切都很好,除了在测试不同的问题期间我发现如果你提交表单,它会按预期使必填字段无效,但如果你足够快地更正必填字段(大概是在它循环等待验证,虽然我一直在努力测试它,因为调试会导致延迟)它会提交请求,即使你没有点击,因为你看到了原始的错误消息。所以我认为 onkeyup 必须重置验证器(及其挂起的验证值)或其他东西,所以间隔中的下一次检查是有效的并且它提交?但是我在文档或我查看确认的各种帖子中找不到任何内容。
作为一种临时解决方法,我想停止表单的 onkeyup,但在相同的情况下 - 快速将有效数据输入到无效字段中 - onkeyup 触发并且表单提交!我想这是相关的,但验证器设置总是显示onkeyup = false
,所以我不明白它为什么验证和提交。
欢迎任何想法。在向控制器方法发出 ajax 请求返回部分后,该表单在 jQuery 对话框中呈现。html中没有什么特别的。
请让我知道我是否可以更清楚或添加任何帮助。