Каков рекомендуемый способ отображения ошибок из JavaScript (jQuery) в представлениях ASP.NET MVC 3? - PullRequest
4 голосов
/ 02 сентября 2011

Я отправляю форму на свой сервер ASP.NET MVC 3 через обработчик JavaScript (я использую jQuery) и получаю ответы об ошибках от сервера в другом обработчике JavaScript.Что мне интересно, так это то, как я должен отображать сообщения об ошибках, возникающих в результате отправки формы, в представлении?Я бы предпочел использовать некоторые стандартные ASP.NET MVC 3 идиома / конструкция.

EDIT

Обратите внимание, что я хочу отображать сообщения об ошибках с сервера, полученные в JavaScriptфункция обработчика ошибок.

Ответы [ 5 ]

2 голосов
/ 02 сентября 2011

Если вы используете валидацию jQuery, которая поставляется с шаблонами решений MVC, в вашем обработчике javascript вам придется добавить ошибки в валидатор.Существует метод showErrors для валидатора .

На стороне клиента :

var formSubmitCallback = function(result){
  var validator = $(this).data('validator');
  if(!result.IsValid && validator)
      validator.showErrors(result.Errors); // uses jquery validator to highlight the fields
  // process the rest of the result here
  // if result.Action == ActionTypes.Redirect
  //     location.href = result.Url
  // etc
}

Теперь мне пришлось стандартизировать объект результатас сервера, чтобы вернуть объект json, отформатированный с { "FieleName": "Error Message" }.Для этого я создал несколько расширений Controller и ViewModel на стороне сервера.

На стороне сервера :

public ActionResult SomeAction(Model someModel){
    if(ModelState.IsValid)
        // save
    else
        // other stuff

    // always return this.AjaxSubmit.
    // Extension function will add Errors, and IsValid to the response data
    return this.AjaxSubmit(new ClientAction{
        Action = ClientActionType.Redirect,
        Url = "/Some/Redirect/Route"
    });
}

Примечание: оглядываясь назад, я написал немного собственного кода, чтобы он работал.В конечном итоге я добавлю код клиента и сервера вместе с примерами на github.Но это общая идея.

Необходимые вам классы серверов и расширения ниже

// GetAllErrors is a ModelState extension to format Model errors for Json response
public static Dictionary<string, string> GetAllErrors(this ModelStateDictionary modelState)
{
    var query = (from state in modelState
                 where state.Value.Errors.Count > 0
                 group state by state.Key into g
                 select new
                 {
                     FieldName = g.Key,
                     FieldErrors = g.Select(prop => prop.Value.Errors).First().Select(prop => prop.ErrorMessage).ToList()
                 });

    return query.ToDictionary(k => k.FieldName, v => string.Join("<br/>", v.FieldErrors));
}

// Controller result extension to return from actions
public static JsonResult AjaxSubmit(this Controller controller, ClientAction action)
{
    if (controller == null) return new JsonResult { Data = action };

    var result = new AjaxSubmitResult
    {
        Errors = controller.ModelState.GetAllErrors(),
        IsValid = controller.ModelState.IsValid,
        ClientAction = action
    };

    return new JsonResult{ Data = result };
}

// Action to perform on the client after a successful, valid response
public class ClientAction
{
    public ClientActionType Action { get; set; }
    public string Url { get; set; }
    public string Function { get; set; }
    public object Data { get; set; }
    public Dictionary<string, string> Updatables { get; set; }
}

public enum ClientActionType
{
    Redirect,
    Ajax,
    Function,
    Modal,
    Message,
    FunctionAndMessage
}
2 голосов
/ 02 сентября 2011

Вы можете пойти в чистом MVC-пути: http://www.asp.net/mvc/tutorials/creating-a-mvc-3-application-with-razor-and-unobtrusive-javascript

Прокрутите вниз до «Включение проверки на стороне клиента».

В вашем View вы получите код, который выглядит следующим образом:

@Html.TextBoxFor(model => model.UserName)
@Html.ValidationMessageFor(model => model.UserName)

ОБНОВЛЕНИЕ

Кажется, что OP заинтересован в пользовательских сообщениях.Не существует никакой конструкции MVC для такого рода пользовательских сообщений.Лучше всего создать свою собственную область сообщений и писать в нее сообщения в функции обратного вызоваНе должно быть слишком сложно!

$.ajax(..., function(data) {
    $('#errors').append('<p>' + data + '</p>');
});
1 голос
/ 02 сентября 2011

В прошлом я отвечал на нечто подобное за добавление сообщений об ошибках.

MVC Validation Сводная обработка с элементами JS и Dynamic DOM

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


var ul = $("#validationSummary ul"); ul.append("<li>Custom Error Message</li>")

1 голос
/ 02 сентября 2011

Сервер должен ответить стандартным сообщением.Это сообщение может содержать полное сообщение об ошибке (HTML), которое затем можно отобразить в пустом элементе div, который является частью вашей _Layout страницы:

function(response) {
  if(response.Status === "error") {
    $("#errorContainer").html(response.ErrorHtml);
  } else {
    // the success handler
  }
}

Преимущество состоит в том, что вы можете выполнить довольно стандартизированную ошибкурендеринг сообщений на сервере.Конечно, вы также можете отобразить их как js popups / модальные диалоговые окна и т. Д.

Форматирование сообщения об ошибке выполняется с помощью CSS, который может быть применен весьма обобщенно к #errorContainer и его содержимому.

Возможно, вы захотите возразить, что лучше отвечать простым текстом с сервера и добавлять любой html-код в клиент через JS.Это также возможно, и, вероятно, лучше работает с «настоящими» REST API.Однако он не позволяет использовать отформатированные сообщения об ошибках (например, со ссылками и т. Д.)

0 голосов
/ 03 сентября 2011

Как я это делаю:

Создать базовый класс контроллера и переопределить обработчик OnException

public abstract class MyBaseController : Controller
{
    protected override void OnException(ExceptionContext filterContext)
    {
        if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
        {
            // add my own status code
            Response.StatusCode = 550;
            // write the error message to the response
            Response.Write(filterContext.Exception.Message);
            // mark the exception as handled
            filterContext.ExceptionHandled = true;
        }

        base.OnException(filterContext);
    }
}

На стороне клиента на готовом документе я регистрирую глобальный обработчик ошибок ajax

$(document).ready(function(){
$.ajaxSetup({
    error:function(x,e){
        if(x.status==0){
           alert('You are offline!!\n Please Check Your Network.');
        }else if(x.status==404){
           alert('Requested URL not found.');
        }else if(x.status==550){ // <----- THIS IS MY CUSTOM ERROR CODE --------
           alert(x.responseText);
        }else if(x.status==500){
           alert('Internel Server Error.');
        }else if(e=='parsererror'){
           alert('Error.\nParsing JSON Request failed.');
        }else if(e=='timeout'){
           alert('Request Time out.');
        }else {
           alert('Unknow Error.\n'+x.responseText);
        }
    }
});
});

Конечно, вы можете настроить эти методы в соответствии со своими потребностями. Надеюсь, это поможет.

...