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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7287412/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 23:38:32  来源:igfitidea点击:

jQuery Validate, ASP.NET MVC ModelState Errors (Async POST)

jqueryasp.net-mvcjquery-validate

提问by Felipe Oriani

I'm developing a web app with asp.net mvc 3 and I have some form that POST to an async action (via ajax). This action recives a ViewModel with some data annotations to validate it. The validation works fine but when the validators return a error I don't know how can I return it to show in my view (because the POST was made by ajax).

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

My action is something like:

我的行动是这样的:

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

How can I show this errors with jquery validate in my view? If it's possible to post some code to sample... I would appretiate that!

如何在我的视图中使用 jquery validate 显示此错误?如果可以发布一些代码来采样......我会很感激!

Thanks guys!

谢谢你们!

回答by Darin Dimitrov

Instead of sending JSON in case of error I would put the form inside a partial and then have the controller action return this partial in case of error. The problem with JSON is that you could in fact fetch the errors from the ModelState using LINQ, but it could be a PITA to show them on the view.

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

So:

所以:

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

and then inside _MyForm.cshtml:

然后在里面_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" />
}

and the controller action would become:

控制器动作将变为:

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

and the last step is to AJAXify this form which could be done in a separate javascript file:

最后一步是对这个表单进行 AJAX 化,这可以在单独的 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;
    });
});

回答by Timothy Strimple

You could return the ModelState errors. This is untested, but something like this should work.

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

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

Edit: To display the errors in a view you just check to see if you were successful, and if not, iterate over the list of errors and put them where you show your errors.

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

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

I prefer Darin's answer for most projects, but your consumer may not always be your own application in which case returning a list of errors is more appropriate since it would allow the consumer to display the errors however they want.

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

回答by Asaad

Create a class to represent ModelState Errors for individual properties.

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

public class ValidationError
{

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

Create A Method which returns a List of ValidationErrors based on the ModelState

创建一个基于 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;
    }

Then in your controller Post Method do:

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

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

You can create a JS Functions that loops through the error list returned above

您可以创建一个循环遍历上面返回的错误列表的 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]);

    });
}

In the example above I am only getting the first error message from 'ErrorList'. You can create an additional loop to get all the messages and append to your validation span.

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

回答by Keerthi

Try this code. This is a simple solution for your problem. It will join all the model state errors into one string.

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

[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 });
    }