Сообщения об ошибках из Ajax вызывали методы PartialView в MVC

если обычные ошибки загрузки страницы я могу сообщить об исключениях пользователю через Error вид HandleErrorInfo - модели.

если ajax вызов ждет Json ошибки, я могу четко обработать ошибку и передать данные клиента:

public JsonResult Whatever()
{
    try
    {
        DoSomething();
        return Json(new { status = "OK" });
    }
    catch (Exception e)
    {
        return Json(new { status = "Error", message = e.Message });
    }
}

Итак, моя проблема, я не вижу способа сообщить подробности об ошибке из вызова Ajax в действие, возвращающее частичное представление.

$.ajax({
    url: 'whatever/trevor',
    error: function (jqXHR, status, error) {
        alert('An error occured: ' + error);
    },
    success: function (html) {
        $container.html(html);
    }
});

это сообщит только код ошибки Http (например, внутренний Ошибка сервера), что не полезно для клиента. Есть ли какой-то умный трюк, чтобы передать либо успешный результат PartialView (html)или сообщение об ошибке?

явная оценка html из ViewResult и возвращая его как часть Json объект вместе со статусом, кажется, слишком вонючий. Существует ли установленный шаблон для обработки этого сценария?

2 ответов


действие контроллера:

public ActionResult Foo()
{
    // Obviously DoSomething could throw but if we start 
    // trying and catching on every single thing that could throw
    // our controller actions will resemble some horrible plumbing code more
    // than what they normally should resemble: a.k.a being slim and focus on
    // what really matters which is fetch a model and pass to the view

    // Here you could return any type of view you like: JSON, HTML, XML, CSV, PDF, ...

    var model = DoSomething();
    return PartialView(model);
}

затем мы определяем глобальный обработчик ошибок для нашего приложения:

protected void Application_Error(object sender, EventArgs e)
{
    var exception = Server.GetLastError();
    var httpException = exception as HttpException;
    Response.Clear();
    Server.ClearError();

    if (new HttpRequestWrapper(Request).IsAjaxRequest())
    {
        // Some error occurred during the execution of the request and 
        // the client made an AJAX request so let's return the error
        // message as a JSON object but we could really return any JSON structure
        // we would like here

        Response.StatusCode = 500;
        Response.ContentType = "application/json";
        Response.Write(new JavaScriptSerializer().Serialize(new 
        { 
            errorMessage = exception.Message 
        }));
        return;
    }

    // Here we do standard error handling as shown in this answer:
    // http://stackoverflow.com/q/5229581/29407

    var routeData = new RouteData();
    routeData.Values["controller"] = "Errors";
    routeData.Values["action"] = "General";
    routeData.Values["exception"] = exception;
    Response.StatusCode = 500;
    if (httpException != null)
    {
        Response.StatusCode = httpException.GetHttpCode();
        switch (Response.StatusCode)
        {
            case 404:
                routeData.Values["action"] = "Http404";
                break;
            case 500:
                routeData.Values["action"] = "Http500";
                break;
        }
    }

    IController errorsController = new ErrorsController();
    var rc = new RequestContext(new HttpContextWrapper(Context), routeData);
    errorsController.Execute(rc);
}

вот как может выглядеть ErrorsController, используемый в глобальном обработчике ошибок. Вероятно, мы могли бы определить некоторые пользовательские представления для действий 404 и 500:

public class ErrorsController : Controller
{
    public ActionResult Http404()
    {
        return Content("Oops 404");
    }

    public ActionResult Http500()
    {
        return Content("500, something very bad happened");
    }
}

затем мы могли бы подписаться на глобальный обработчик ошибок для всех ошибок AJAX, чтобы нам не пришлось повторять этот код обработки ошибок для всех запросов AJAX, но если мы хотели, чтобы мы могли повторить это:

$('body').ajaxError(function (evt, jqXHR) {
    var error = $.parseJSON(jqXHR.responseText);
    alert('An error occured: ' + error.errorMessage);
});

и, наконец, мы запускаем запрос AJAX к действию контроллера, который, как мы надеемся, вернет HTML-частичный в этом случае:

$.ajax({
    url: 'whatever/trevor',
    success: function (html) {
        $container.html(html);
    }
});

создать переопределенную версию HandleErrorAttribute (JsonHandleErrorAttribute ?) и добавьте [JsonHandleError] в действие json.

посмотрите на AjaxAuthorizeAttribute в asp.net mvc [handleerror] [авторизовать] с помощью JsonResult?