我可以将自定义错误从 JsonResult 返回到 jQuery ajax 错误方法吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9298466/
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-27 10:36:52  来源:igfitidea点击:

Can I return custom error from JsonResult to jQuery ajax error method?

ajaxasp.net-mvc-3jquery

提问by Drew Gaynor

How can I pass custom error information from an ASP.NET MVC3 JsonResultmethod to the error(or successor complete, if need be) function of jQuery.ajax()? Ideally I'd like to be able to:

如何将自定义错误信息从 ASP.NET MVC3JsonResult方法传递到error(或successcomplete,如果需要)的函数jQuery.ajax()?理想情况下,我希望能够:

  • Still throw the error on the server (this is used for logging)
  • Retrieve custom information about the error on the client
  • 仍然在服务器上抛出错误(这是用于日志记录)
  • 在客户端检索有关错误的自定义信息

Here is a basic version of my code:

这是我的代码的基本版本:

Controller JsonResult method

控制器 JsonResult 方法

public JsonResult DoStuff(string argString)
{
    string errorInfo = "";

    try
    {
        DoOtherStuff(argString);
    }
    catch(Exception e)
    {
        errorInfo = "Failed to call DoOtherStuff()";
        //Edit HTTP Response here to include 'errorInfo' ?
        throw e;
    }

    return Json(true);
}

JavaScript

JavaScript

$.ajax({
    type: "POST",
    url: "../MyController/DoStuff",
    data: {argString: "arg string"},
    dataType: "json",
    traditional: true,
    success: function(data, statusCode, xhr){
        if (data === true)
            //Success handling
        else
            //Error handling here? But error still needs to be thrown on server...
    },
    error: function(xhr, errorType, exception) {
        //Here 'exception' is 'Internal Server Error'
        //Haven't had luck editing the Response on the server to pass something here
    }
});

Things I've tried (that didn't work out):

我尝试过的事情(没有成功):

  • Returning error info from catchblock
    • This works, but the exception can't be thrown
  • Editing HTTP response in catchblock
    • Then inspected xhrin the jQuery error handler
    • xhr.getResponseHeader(), etc. contained the default ASP.NET error page, but none of my information
    • I think this may be possible, but I just did it wrong?
  • catch块 返回错误信息
    • 这有效,但不能抛出异常
  • catch块中 编辑 HTTP 响应
    • 然后xhr在 jQuery 错误处理程序中检查
    • xhr.getResponseHeader()等包含默认的 ASP.NET 错误页面,但没有我的信息
    • 我认为这可能是可能的,但我做错了吗?

回答by Darin Dimitrov

You could write a custom error filter:

您可以编写自定义错误过滤器:

public class JsonExceptionFilterAttribute : FilterAttribute, IExceptionFilter
{
    public void OnException(ExceptionContext filterContext)
    {
        if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
        {
            filterContext.HttpContext.Response.StatusCode = 500;
            filterContext.ExceptionHandled = true;
            filterContext.Result = new JsonResult
            {
                Data = new
                {
                    // obviously here you could include whatever information you want about the exception
                    // for example if you have some custom exceptions you could test
                    // the type of the actual exception and extract additional data
                    // For the sake of simplicity let's suppose that we want to
                    // send only the exception message to the client
                    errorMessage = filterContext.Exception.Message
                },
                JsonRequestBehavior = JsonRequestBehavior.AllowGet
            };
        }
    }
}

and then register it either as a global filter or only apply to particular controllers/actions that you intend to invoke with AJAX.

然后将其注册为全局过滤器或仅应用于您打算使用 AJAX 调用的特定控制器/操作。

And on the client:

在客户端:

$.ajax({
    type: "POST",
    url: "@Url.Action("DoStuff", "My")",
    data: { argString: "arg string" },
    dataType: "json",
    traditional: true,
    success: function(data) {
        //Success handling
    },
    error: function(xhr) {
        try {
            // a try/catch is recommended as the error handler
            // could occur in many events and there might not be
            // a JSON response from the server
            var json = $.parseJSON(xhr.responseText);
            alert(json.errorMessage);
        } catch(e) { 
            alert('something bad happened');
        }
    }
});

Obviously you could be quickly bored to write repetitive error handling code for each AJAX request so it would be better to write it once for all AJAX requests on your page:

显然,您可能很快就会厌倦为每个 AJAX 请求编写重复的错误处理代码,因此最好为页面上的所有 AJAX 请求编写一次:

$(document).ajaxError(function (evt, xhr) {
    try {
        var json = $.parseJSON(xhr.responseText);
        alert(json.errorMessage);
    } catch (e) { 
        alert('something bad happened');
    }
});

and then:

进而:

$.ajax({
    type: "POST",
    url: "@Url.Action("DoStuff", "My")",
    data: { argString: "arg string" },
    dataType: "json",
    traditional: true,
    success: function(data) {
        //Success handling
    }
});


Another possibility is to adapt a global exception handler I presentedso that inside the ErrorController you check if it was an AJAX request and simply return the exception details as JSON.

另一种可能性是调整我介绍的全局异常处理程序,以便在 ErrorController 中检查它是否是 AJAX 请求,并简单地将异常详细信息作为 JSON 返回。

回答by Artem G

The advice above wouldn't work on IIS for remote clients. They will receive a standard error page like 500.htm instead of a response with a message. You have to use customError mode in web.config, or add

上述建议不适用于远程客户端的 IIS。他们将收到一个标准错误页面,如 500.htm,而不是带有消息的响应。你必须在 web.config 中使用 customError 模式,或者添加

<system.webServer>
        <httpErrors existingResponse="PassThrough" />
    </system.webServer>

or

或者

"You can also go into IIS manager --> Error Pages then click on the right on "Edit feature settings..." And set the option to "Detailed errors" then it will be your application that process the error and not IIS."

“您也可以进入 IIS 管理器 --> 错误页面,然后单击右侧的“编辑功能设置...”并将选项设置为“详细错误”,那么处理错误的将是您的应用程序,而不是 IIS。 ”

回答by linktoarun

you can return JsonResult with error and track the status at javascript side to show error message :

您可以返回带有错误的 JsonResult 并跟踪 javascript 端的状态以显示错误消息:

 JsonResult jsonOutput = null;
        try
        {
           // do Stuff
        }
        catch
        {
            jsonOutput = Json(
                 new
                 {
                     reply = new
                     {
                         status = "Failed",
                         message = "Custom message "
                     }
                 });
        }
        return jsonOutput ;

回答by John M

My MVC project wasn't returning any error message (custom or otherwise). I found that this worked well for me:

我的 MVC 项目没有返回任何错误消息(自定义或其他)。我发现这对我很有效:

$.ajax({
        url: '/SomePath/Create',
        data: JSON.stringify(salesmain),
        type: 'POST',
        contentType: 'application/json;',
        dataType: 'json',
        success: function (result) {

            alert("start JSON");
            if (result.Success == "1") {
                window.location.href = "/SomePath/index";
            }
            else {
                alert(result.ex);
            }

            alert("end JSON");
        },
        error: function (xhr) {

            alert(xhr.responseText);

        }
        //error: AjaxFailed
    });

Showing the xhr.responseText resulted in a very detailed HTML formatted alert message.

显示 xhr.responseText 会产生非常详细的 HTML 格式的警报消息。

回答by Leo Garza

If for some reason you can't send a server error. Here's an option that you can do.

如果由于某种原因您无法发送服务器错误。这是您可以执行的一个选项。

server side

服务器端

 var items = Newtonsoft.Json.JsonConvert.DeserializeObject<SubCat>(data); // Returning a parse object or complete object

        if (!String.IsNullOrEmpty(items.OldName))
        {
            DataTable update = Access.update_SubCategories_ByBrand_andCategory_andLikeSubCategories_BY_PRODUCTNAME(items.OldName, items.Name, items.Description);

            if(update.Rows.Count > 0)
            {
                List<errors> errors_ = new List<errors>();
                errors_.Add(new errors(update.Rows[0]["ErrorMessage"].ToString(), "Duplicate Field", true));

                return Newtonsoft.Json.JsonConvert.SerializeObject(errors_[0]); // returning a stringify object which equals a string | noncomplete object
            }

        }

        return items;

client side

客户端

 $.ajax({
            method: 'POST',
            url: `legacy.aspx/${place}`,
            contentType: 'application/json',
            data:  JSON.stringify({data_}),              
            headers: {
                'Accept': 'application/json, text/plain, *',
                'Content-type': 'application/json',
                'dataType': 'json'
            },
            success: function (data) {

                if (typeof data.d === 'object') { //If data returns an object then its a success

                    const Toast = Swal.mixin({
                        toast: true,
                        position: 'top-end',
                        showConfirmButton: false,
                        timer: 3000
                    })

                    Toast.fire({
                        type: 'success',
                        title: 'Information Saved Successfully'
                    })

                    editChange(place, data.d, data_);

                } else { // If data returns a stringify object or string then it failed and run error

                    var myData = JSON.parse(data.d);

                    Swal.fire({
                      type: 'error',
                      title: 'Oops...',
                      text: 'Something went wrong!',
                      footer: `<a href='javascript:showError("${myData.errorMessage}", "${myData.type}", ${data_})'>Why do I have this issue?</a>`
                    })
                }
            },
            error: function (error) { console.log("FAIL....================="); }
        });