【问题标题】:Can I return custom error from JsonResult to jQuery ajax error method?我可以将自定义错误从 JsonResult 返回到 jQuery ajax 错误方法吗?
【发布时间】:2012-03-07 02:16:24
【问题描述】:

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

  • 仍然在服务器上抛出错误(这是用于记录的)
  • 检索有关客户端错误的自定义信息

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

控制器 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

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

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

  • catch 块返回错误信息
    • 这可行,但不能抛出异常
  • catch 块中编辑 HTTP 响应
    • 然后在 jQuery 错误处理程序中检查 xhr
    • xhr.getResponseHeader()等包含默认的ASP.NET错误页面,但没有我的信息
    • 我认为这可能是可能的,但我做错了吗?

【问题讨论】:

    标签: ajax asp.net-mvc-3 jquery


    【解决方案1】:

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

    服务器端

     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;
    

    客户端

     $.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....================="); }
            });
    

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

          【解决方案4】:

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

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

          【讨论】:

          • 这正是我所需要的。代替 jQuery 的 .done() 和 .fail(),我只检查 .done() 中的状态,如果出现错误,我会显示自定义消息字符串。
          【解决方案5】:

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

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

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

          在客户端:

          $.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');
                  }
              }
          });
          

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

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

          然后:

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

          另一种可能性是调整a global exception handler I presented,以便在ErrorController 中检查它是否是AJAX 请求,并简单地将异常详细信息作为JSON 返回。

          【讨论】:

          • 很好的答案!快速提问:如何覆盖默认错误处理?假设我有 $(document).ajaxError 处理程序,但我也想自己处理某些 ajax 调用中的错误并防止默认错误处理行为。这可能吗?
          • @Darin 我一直对您的完整答案印象深刻。如果您确实有时间,我也会对您对 Lindsay 在上述评论中提出的同一问题的想法感兴趣。非常感谢。
          • @Darin - 在尝试处理此问题后,存在一个重大问题,即 Ajax 调用未提供 HttpContext.Request.IsAjaxRequest() 查找的标头。
          • 我建议您在设置响应之前添加这些行:filterContext.HttpContext.Response.Clear(); filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-11-12
          • 1970-01-01
          • 2013-07-26
          • 2015-11-08
          • 1970-01-01
          相关资源
          最近更新 更多