报告 Ajax 调用 MVC 中的 PartialView 方法的错误

发布于 2024-12-18 00:08:52 字数 912 浏览 2 评论 0原文

如果正常的页面加载错误,我可以通过 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) 结果错误消息?

ViewResult 显式评估 html 并将其作为 Json 对象的一部分与状态一起返回似乎太难闻了。是否有处理这种情况的既定模式?

If a normal page load errors I can report the exception details to the user via the Error view and HandleErrorInfo model.

If an ajax call expecting a Json result errors, I can explicitly handle the error and pass details to the client:

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

So, my problem, I can't see any way to report error details from an Ajax call to an action returning a partial view.

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

This will only report an Http error code (e.g. Internal Server Error) which is not helpful to the client. Is there some clever trick to pass either a successful PartialView (html) result or an error message?

Explicitly evaluating the html from the ViewResult and returning it as part of a Json object along with a status seems too smelly. Is there an established pattern for handling this scenario?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你的笑 2024-12-25 00:08:52

控制器操作:

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

Controller action:

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

Then we define a Global error handler for our application:

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

Here's how the ErrorsController used in the global error handler could look like. Probably we could define some custom views for the 404 and 500 actions:

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

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

Then we could subscribe for a global error handler for all AJAX errors so that we don't have to repeat this error handling code for all AJAX requests but if we wanted we could repeat it:

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

And finally we fire an AJAX request to the controller action that we hope will return an HTML partial in this case:

$.ajax({
    url: 'whatever/trevor',
    success: function (html) {
        $container.html(html);
    }
});
所谓喜欢 2024-12-25 00:08:52

创建 HandleErrorAttribute (JsonHandleErrorAttribute ?) 的重写版本并在 json 操作中添加 [JsonHandleError]。

看看 asp.net mvc [handleerror] [authorize] 中的 AjaxAuthorizeAttribute 和 JsonResult ?

Create an overriden version of HandleErrorAttribute (JsonHandleErrorAttribute ?) and add [JsonHandleError] on your json action.

Have a look at AjaxAuthorizeAttribute in asp.net mvc [handleerror] [authorize] with JsonResult?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文