jQuery验证,ASP.NET MVC ModelState错误(异步POST)

时间:2011-09-02 17:56:27

标签: jquery asp.net-mvc jquery-validate

我正在使用asp.net mvc 3开发一个Web应用程序,我有一些表单可以POST到异步操作(通过ajax)。此操作将返回带有一些数据注释的ViewModel以对其进行验证。验证工作正常,但当验证器返回错误时,我不知道如何将其返回到我的视图中显示(因为POST是由ajax制作的)。

我的行动是这样的:

[HttpPost]
public ActionResult SaveCustomer(CustomerViewModel input) {
    if (!ModelState.IsValid) { // <-- business validation
        return Json(new { success = false, errors = ???});
    }
    // persist 
    return Json(new { success = true });
}

如何在视图中使用jquery validate显示此错误? 如果有可能发布一些代码进行抽样......我会认为这样做!

谢谢你们!

4 个答案:

答案 0 :(得分:49)

如果出现错误而不是发送JSON,我会将表单放在partial中,然后让控制器操作在发生错误时返回此部分。 JSON的问题在于你实际上可以使用LINQ从ModelState中获取错误,但它可能是一个PITA来在视图上显示它们。

所以:

<div id="myform">
    @Html.Partial("_MyForm")
</div>

然后在_MyForm.cshtml内:

@model CustomerViewModel
@using (Html.BeginForm())
{
    @Html.EditorFor(x => x.Foo)
    @Html.ValidationMessageFor(x => x.Foo)
    <br />
    @Html.EditorFor(x => x.Bar)
    @Html.ValidationMessageFor(x => x.Bar)
    <br />
    <input type="submit" value="OK" />
}

并且控制器操作将变为:

[HttpPost]
public ActionResult SaveCustomer(CustomerViewModel model)
{
    if (!ModelState.IsValid)
    {
        return PartialView("_MyForm", model);
    }
    return Json(new { success = true });
}

最后一步是AJAXify这个表单,可以在一个单独的javascript文件中完成:

$(function () {
    $('#myform').delegate('form', 'submit', function () {
        $.ajax({
            url: this.action,
            type: this.method,
            data: $(this).serialize(),
            success: function (result) {
                if (result.success) { 
                    // We have a JSON object in case of success
                    alert('success');
                } else {
                    // We have the partial with errors in case of failure
                    // so all we have to do is update the DOM
                    $('#myform').html(result);
                }
            }
        });
        return false;
    });
});

答案 1 :(得分:15)

您可以返回ModelState错误。这是未经测试的,但这样的事情应该有效。

return Json(new
            {
                success = false,
                errors = ModelState.Keys.SelectMany(k => ModelState[k].Errors)
                                .Select(m => m.ErrorMessage).ToArray()
            });

编辑:要在视图中显示错误,您只需检查是否成功,如果没有,则迭代错误列表并将其放在显示错误的位置。

if(!result.success) {
    for(var error in result.errors) {
        $('#errorMessages').append(error + '<br />');
    }
}

我更喜欢Darin对大多数项目的回答,但您的消费者可能并不总是您自己的应用程序,在这种情况下返回错误列表更合适,因为它会允许消费者显示他们想要的错误。

答案 2 :(得分:0)

创建一个类来表示各个属性的ModelState错误。

public class ValidationError
{

    public string PropertyName = "";
    public string[] ErrorList = null;
}

创建一个基于ModelState返回ValidationErrors列表的方法

    public IEnumerable<ValidationError> GetModelStateErrors(ModelStateDictionary modelState)
    {
        var errors = (from m in modelState
                            where m.Value.Errors.Count() > 0
                            select
                               new ValidationError
                               {
                                   PropertyName = m.Key,
                                   ErrorList = (from msg in m.Value.Errors
                                                  select msg.ErrorMessage).ToArray()
                               })
                            .AsEnumerable();
        return errors;
    }

然后在控制器的Post方法中执行以下操作:

        if (!ModelState.IsValid)
        {
            return Json(new
            {
                errors = true,
                errorList = GetModelStateErrors(ModelState)
            }, JsonRequestBehavior.AllowGet);
        }

您可以创建一个遍历上面返回的错误列表的JS函数

$.ajax({
            cache: false,
            async: true,
            type: "POST",
            url: form.attr('action'),
            data: form.serialize(),
            success: function (data) {
                if (data.errors) {
                    displayValidationErrors(data.errorList);
                 }
            },
        error: function (result) {
            console.log("Error");
        }

    });

function displayValidationErrors(errors) {
    $.each(errors, function (idx, validationError) {

        $("span[data-valmsg-for='" + validationError.PropertyName + "']").text(validationError. ErrorList[0]);

    });
}

在上面的示例中,我仅从“ ErrorList”中收到第一条错误消息。您可以创建一个附加循环以获取所有消息并追加到您的验证范围内。

答案 3 :(得分:0)

  

尝试此代码。这是解决您问题的简单方法。它将所有模型状态错误合并为一个字符串。

[HttpPost]
    public ActionResult SaveCustomer(CustomerViewModel input) {
        if (!ModelState.IsValid) { // <-- business validation
            return Json(new { success = false, errors = string.Join("; ", ModelState.Values
                                            .SelectMany(x => x.Errors)
                                            .Select(x => x.ErrorMessage));});
        }
        // persist 
        return Json(new { success = true });
    }