ASP.NET-MVC jQuery不显眼的远程验证返回误报

时间:2014-04-15 01:06:49

标签: jquery asp.net-mvc validation

我回到了9个月前我上次工作的项目,查看了我们编写的一些代码,并希望现在有更好的方法来实现这一目标......

虽然最初对jQuery的不引人注目的验证印象非常深刻,但我们最终还是要将下面的黑客(部分基于我现在不能动手的博客文章)放在一起来处理远程验证。问题在于服务器端验证过程很慢 - 通常是涉及数据库调用的任何事情 - 验证器不会等待验证方法的响应,并且会表现得好像它已经传回正面。

hack基本上是继续检查验证器是否有任何待处理请求,并且在没有任何待处理请求之前不进行,当你可以确定真正的验证结果时:

function SaveChangePassword() {

// Find form, fire validation
var $form = $("#btnSave").closest("form");

if ($form.valid()) {
//Do nothing - just firing validation
}

// Calls method every 30 milliseconds until remote validation is complete
var interval = setInterval(saveWhenValidationComplete, 30);

// Check if validation pending, save and clear interval if not
function saveWhenValidationComplete() {

    // Find form validator, check if validation pending - save once remote validation is finished
    var validator = $form.data("validator");
    if (validator.pendingRequest === 0) {

        clearInterval(interval);

        //Force validation to present to user (this will not retrigger remote validation)
        if ($form.valid()) {

            var closeButton = "<br/><input type='button' value='OK' style='font-size:small; font-weight:bold; float:right;' onclick=\"$('#changePasswordDialog').dialog('close');\" class='greenbutton' />";
            // If form is valid then submit
            $.ajax(
                {
                    type: "POST",
                    url: "/Account/SavePassword",
                    data: $form.serialize(),
                    success: function (result) {
                        var successMessage = "<div style='text-align:center; margin-top: 10px;'>" + result + "<div>";
                        $("#changePasswordDialog").html(successMessage + closeButton);
                            },
                    error: function (jqXhr, textStatus, errorThrown) {
                        // Populate dialog with error message and button
                        var errorMessage = "<div style='text-align:center'>Error '" + jqXhr.status + "' (Status: '" + textStatus + "', errorThrown: '" + errorThrown + "')<div>";
                        $("#changePasswordDialog").html(errorMessage + closeButton);
                    }
                });

        }

        // Else validation will show
    }

    // Else don't save yet, wait another 30 miliseconds while validation runs
};

// Prevent default and stop event propagation
return false;
}

我希望在过去的9个月中有一些发展,这已经不再需要了!任何想法欢迎,如果我能提供任何进一步的细节,请告诉我。

1 个答案:

答案 0 :(得分:2)

虽然您可以为用户提供客户端验证,但您应始终(始终!)在服务器上重新验证。用户很容易禁用javascript或以其他方式伪造无效的POST到您的控制器操作,如果您不检查服务器端的内容,则会为用户创建破坏数据的机会在你的系统中。

幸运的是,ASP.NET MVC中的大多数验证都是为您完成的。如果您的控制器操作如下所示:

public ActionResult SaveSomething(Something thing)
{
    if(!ModelState.IsValid)
    {
        return View("EditSomething", thing);
    }
    // otherwise, save something...
}

...然后您就会发现问题,即用户提供的数据无法绑定到您的数据属性,以及[Required]和{{1}等属性验证的内容}}。但是,某些形式的验证不会自动为您检查。 [StringLength(x)]就是其中之一。

如果您有一个[Remote]属性指向这样的控制器操作:

[Remote]

...那么你在提交动作中也应该有这样的东西:

public ActionResult CheckThingCodeValidity(string code)
{
    return Json(_thingCodeChecker.ThingCodeWorks(code), JsonRequestBehavior.AllowGet);
}

这样,您的标准服务器端验证技术可以将视图发送回用户,并在该属性上向他们提供错误消息,以指示他们需要修复的内容。

如果您这样做,那么您不必担心在提交表单时是否仍在进行异步验证检查。如果您的客户端验证通常无法通过缺陷,网络问题或恶意用户干预,那么无关紧要。您仍然会阻止他们提交无效的内容,他们仍然可以很好地了解他们提交内容无效的原因。