Подтвердить что ты не робот

JQuery Validate, ASP.NET MVC ModelState Ошибки (Async POST)

Я разрабатываю веб-приложение с asp.net mvc 3, и у меня есть некоторая форма 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 на мой взгляд? Если можно отправить какой-то код в образец... Я бы это заметил!

Спасибо, ребята!

4b9b3361

Ответ 1

Вместо того, чтобы отправлять JSON в случае ошибки, я бы поместил форму внутри частичного, а затем действие контроллера вернуло это частичное в случае ошибки. Проблема с JSON заключается в том, что вы действительно можете получить ошибки из ModelState с помощью LINQ, но это может быть 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;
    });
});

Ответ 2

Вы можете вернуть ошибки 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 />');
    }
}

Я предпочитаю ответ Дарина для большинства проектов, но ваш потребитель не всегда может быть вашим собственным приложением, и в этом случае возврат списка ошибок более уместен, поскольку он позволит потребителю отображать ошибки, но они хотят.

Ответ 3

Создайте класс для представления ошибок ModelState для отдельных свойств.

public class ValidationError
{

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

Создать метод, который возвращает список ValidationErrors на основе ModelState

    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 Method сделайте:

        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. Вы можете создать дополнительный цикл, чтобы получить все сообщения и добавить их к своему периоду проверки.

Ответ 4

Попробуйте этот код. Это простое решение вашей проблемы. Он объединит все ошибки состояния модели в одну строку.

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