6

我正在尝试使用实现可选的客户端验证

  • ASP.NET MVC 4,
  • 不显眼的 jQuery 验证,
  • 不显眼的ajax

这工作正常

下面的图片显示了我对可选客户端验证的含义:我的表单上唯一的一个字段应该包含电子邮件,因此附加了一个电子邮件验证器。

在此处输入图像描述

现在我们点击保存。因为我们的文本“name@doamin”不是有效的电子邮件,所以会显示验证摘要。连同验证摘要,我们将取消隐藏“仍然保存”按钮。

在此处输入图像描述

第二个按钮是一个普通的提交按钮,只有class="cancel". 这指示jQuery.validate.js脚本在使用此按钮提交时跳过验证。

这是视图的代码片段:

@using (Html.BeginForm())
{
    <div>
        <input data-val="true" data-val-email="Uups!" name="emailfield" />
        <span class="field-validation-valid" data-valmsg-for="emailfield" data-valmsg-replace="false">*</span>
    </div>

    <input type="submit" value="Save" />
    @Html.ValidationSummary(false, "Still errors:")
    <div class="validation-summary-valid" data-valmsg-summary="true">
        <input type="submit" value="Save anyway" class="cancel" />
    </div>
}

这些都工作正常。

问题

第二个提交按钮 -如果我切换到 Ajax 表单,“仍然保存”将按预期停止工作。它的行为就像正常的一样,并且在验证成功之前阻止提交。

这是“ajaxified”视图的代码片段:

@using (Ajax.BeginForm("Edit", new { id = "0" },
        new AjaxOptions
            {
                HttpMethod = "POST",
                InsertionMode = InsertionMode.Replace,
                UpdateTargetId = "ajaxSection",
            }))
{
    <div>
        <input data-val="true" data-val-email="Uups!" name="emailfield" />
        <span class="field-validation-valid" data-valmsg-for="emailfield" data-valmsg-replace="false">*</span>
    </div>

    <input type="submit" value="Save" />
    @Html.ValidationSummary(false, "Still errors:")
    <div class="validation-summary-valid" data-valmsg-summary="true">
        <input type="submit" value="Save anyway" class="cancel" name="saveAnyway" />
    </div>
}

我已经调试jQuery.validation.js以找出有什么区别,但失败了。

问题

欢迎任何解决或解决问题并让 ajax 表单按预期运行的想法。


附录

进行客户端验证是绝对必须的。服务器端验证不是一种选择。除了更高的流量(这个示例是一个简化 - 真实的表单包含更多的字段)和延迟之外,还有一件事是服务器端验证不会做的:客户端验证器会突出显示失去焦点的错误字段。这意味着一旦您切换到下一个字段,您就会收到反馈。

4

3 回答 3

11

这是微软不显眼的 ajax 脚本的一个已知限制。您可以对其进行修改以修复错误。所以在jquery.unobtrusive-ajax.js脚本中替换第 144 行的以下内容:

$(form).data(data_click, name ? [{ name: name, value: evt.target.value }] : []);

和:

$(form).data(data_click, name ? [{ name: name, value: evt.target.value, className: evt.target.className }] : []);

此外,我们将类名传递给处理程序,以便它可以决定是否应该触发客户端验证。目前,无论单击哪个按钮,它都会触发验证。现在在第 154 行,我们修改以下测试:

if (!validate(this)) {

和:

if (clickInfo[0].className != 'cancel' && !validate(this)) {

因此,如果使用具有类名取消的提交按钮来提交表单,则不再触发客户端验证。另一种可能性是刮掉jquery.unobtrusive-ajax.js脚本并将您的脚本替换为您可以使用普通旧 jQuery 不显眼地进行 AJAXifyAjax.BeginForm的标准。Html.BeginForm

于 2012-07-26T06:07:59.453 回答
7

最后我想出了一个本身不引人注目的解决方案

    // restore behavior of .cancel from jquery validate to allow submit button 
    // to automatically bypass all jquery validation
    $(document).on('click', 'input[type=image].cancel,input[type=submit].cancel', function (evt)
    {
        // find parent form, cancel validation and submit it
        // cancelSubmit just prevents jQuery validation from kicking in
        $(this).closest('form').validate().cancelSubmit = true;
        $(this).closest('form').submit();
        return false;
    });

注意:如果第一次尝试它似乎不起作用 - 确保您没有往返服务器并刷新错误页面。您必须通过其他方式绕过服务器端的验证 - 这只是允许提交表单,而不必为.ignore表单中的所有内容添加属性。

button(如果您使用按钮,可能需要添加到选择器)

于 2013-07-01T09:56:26.827 回答
-2

如果不需要不显眼的验证,请禁用它并在服务器端进行所有检查。

您可以在服务器端检查提交按钮的值并根据该值继续:

name为您的两个提交输入添加属性:

<input type="submit" value="Save" name="btnSubmit" />
<input type="submit" value="Save anyway" class="cancel" name="btnSubmit" />

更新您要采取的行动string btnSubmit。如果你有一个,你可以把它放在你的模型中。

[HttpPost]
public ActionResult Edit(string emailfield, string btnSubmit)
{
    switch (btnSubmit)
    {
        case "Save":
            if(ModelState.IsValid)
            {
                // Save email
            }
            break;
        case "Save anyway":
            // Save email
            return RedirectToAction("Success");
            break;
    }
    // ModelState is not valid
    // whatever logic to re display the view
    return View(model);
}

更新

我知道客户端验证简化了工作,但是如果您无法弄清楚 Ajax 有什么问题(我不熟悉在输入输入时 class="cancel" 的行为),您可以编写一个脚本来验证在服务器端不关注的输入:

$('input[type=text]').blur(function(){
    $.ajax({
        url: '/ControllerName/ValidateInput',
        data: { inputName: $(this).val() },
        success: function(data) {
            //if there is a validation error, display it
        },
        error: function(){
            alert('Error');
        }
    });
});

现在您需要创建一个操作来验证输入:

public ActionResult ValidateInput(string inputName)
{
    bool isValid = true;
    string errorMessage = "";
    switch (inputName)
    {
        case "password"
            // do password validation
            if(!inputIsValid)
            {
                isValid = false;
                errorMessage = "password is invalid";
            }
            break;
        case "email"
            // do email validation
            if(!inputIsValid)
            {
                isValid = false;
                errorMessage = "email is invalid";
            }
            break;
    }
    return Json(new { inputIsValid = isValid, message = errorMessage });
}

这有点麻烦,但正如我所说,如果您不弄清楚客户端验证,它可能会起作用。


更新

不知道为什么我没有首先想到这个......而不是依靠class="cancel"你可以做这样的事情:

提供您的“无论如何”提交输入 ID:

<input type="submit" value="Save anyway" class="cancel" name="btnSubmit" id="submitAyway" />

然后有一个这样的脚本:

$('#submitAyway').click(function(evt) {
    evt.preventDefault();
    $('form').submit();
});

我没有对此进行测试,但理论上,这应该提交表单而不进行验证。正如我在第一个示例中展示的那样,您可能仍然需要服务器端验证。

于 2012-07-25T17:53:38.717 回答