1

我以为我已经为 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中没有什么特别的。

请让我知道我是否可以更清楚或添加任何帮助。

4

1 回答 1

0

好的,这可能是随机黑客历史上最黑客的黑客,但我最终在对话框中添加了一个覆盖 div 以停止字段和按钮交互并重置输入值,如下所示,以强制通过后续点击的验证重新评估表单:

// Force validation to reevaluate next time
var inputs = $form.find(":input");
inputs.removeData("previousValue");

这实际上并没有重置值,但它似乎确实删除了验证器用于将字段标记为有效或无效的任何内容。我不会将此标记为“答案”,但这肯定是完成它的一种方法!

于 2013-05-02T01:49:59.823 回答