【问题标题】:Get the error text message from a jqXHR when the error was raised on the server by an ASP.NET exception当 ASP.NET 异常在服务器上引发错误时,从 jqXHR 获取错误文本消息
【发布时间】:2013-12-11 08:04:15
【问题描述】:

我有一个如下所示的服务器端操作:

namespace MyProduct.Presentation.Controllers
{
    public class FooController : Controller
    {
        public ActionResult Delete(long[] fooIds)
        {
            throw new Exception("Something went wrong.");
        }
    }
}

我从客户端向该控制器发出 ajax 请求,如下所示:

var url = '/Foo/Delete';

$.ajax(url,
{
  cache: false, async: false, type: 'POST',
  data: JSON.stringify({ fooIds: fooIdsArray }), dataType: 'json',
  contentType: 'application/json', traditional: true,
  error: OnError, success: OnSuccess
});

function OnSuccess(data, textStatus, jqXHR) {
  debugger;
}

function OnError(jqXHR, textStatus, errorThrown) {
  debugger;

  // Here, I want the text "Something went wrong", 
  // which I set as the Message property
  // of my server side exception
}

如何将文本设置为服务器上引发的Exception 对象的Message 属性?

在这种情况下,客户端收到带有 HTTP 状态代码 500 的 HTML 响应。因此,我在 Fiddler 中看到我的响应如下所示:

HTTP/1.1 500 Internal Server Error
Server: ASP.NET Development Server/10.0.0.0
Date: Wed, 11 Dec 2013 07:47:26 GMT
X-AspNet-Version: 4.0.30319
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 10175
Connection: Close

<!DOCTYPE html>
<html>
    <head>
        <title>Could not delete category. This category has data associated with it. Please delete the associated data first.</title>
        <meta name="viewport" content="width=device-width" />
        <style>
         body {font-family:"Verdana";font-weight:normal;font-size: .7em;color:black;} 
         p {font-family:"Verdana";font-weight:normal;color:black;margin-top: -5px}
         b {font-family:"Verdana";font-weight:bold;color:black;margin-top: -5px}
         H1 { font-family:"Verdana";font-weight:normal;font-size:18pt;color:red }
         H2 { font-family:"Verdana";font-weight:normal;font-size:14pt;color:maroon }
         pre {font-family:"Consolas","Lucida Console",Monospace;font-size:11pt;margin:0;padding:0.5em;line-height:14pt}
         .marker {font-weight: bold; color: black;text-decoration: none;}
         .version {color: gray;}
         .error {margin-bottom: 10px;}
         .expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }
         @media screen and (max-width: 639px) {
          pre { width: 440px; overflow: auto; white-space: pre-wrap; word-wrap: break-word; }
         }
         @media screen and (max-width: 479px) {
          pre { width: 280px; }
         }
        </style>
    </head>

    <body bgcolor="white">

            <span><H1>Server Error in '/' Application.<hr width=100% size=1 color=silver></H1>

            <h2> <i>Could not delete category. This category has data associated with it. Please delete the associated data first.</i> </h2></span>

            <font face="Arial, Helvetica, Geneva, SunSans-Regular, sans-serif ">

            <b> Description: </b>An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

            <br><br>

            <b> Exception Details: </b>System.Exception: Could not delete category. This category has data associated with it. Please delete the associated data first.<br><br>

            <b>Source Error:</b> <br><br>

            <table width=100% bgcolor="#ffffcc">
               <tr>
                  <td>
                      <code><pre>

Line 66:                 }
Line 67: 
<font color=red>Line 68:                 throw new Exception(errorMessage);
</font>Line 69:             }
Line 70:             catch</pre></code>

                  </td>
               </tr>
            </table>

            <br>

            <b> Source File: </b> C:\Sathyaish\Clients\ESQ\SVN\GlobalizationUI.Presentation\Controllers\CategoryController.cs<b> &nbsp;&nbsp; Line: </b> 68
            <br><br>

            <b>Stack Trace:</b> <br><br>

            <table width=100% bgcolor="#ffffcc">
               <tr>
                  <td>
                      <code><pre>

[Exception: Could not delete category. This category has data associated with it. Please delete the associated data first.]
   MyProduct.Presentation.Controllers.CategoryController.Delete(Int64[] categoryIds) in yada yada yada

</pre></code>

                  </td>
               </tr>
            </table>

            <br>

            <hr width=100% size=1 color=silver>

            <b>Version Information:</b>&nbsp;Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.18055

            </font>

    </body>
</html>
<!-- 
[Exception]: Could not delete category. This category has data associated with it. Please delete the associated data first.
   at MyProduct.Presentation.Controllers.CategoryController.Delete(Int64[] categoryIds) in ...yada yada yada...

【问题讨论】:

  • @Zabavsky:我对如何解决处理错误情况的一般问题并不感兴趣。我对处理 ASP.NET 抛出的异常的替代方法也不感兴趣。我知道所有的选择。我只是想知道序列化异常在 jQuery XHR 对象中转换为什么。似乎 XHR 并不关心返回的响应的细节,在这种情况下,它恰好是一个 HTML DOM,我感兴趣的值被嵌入到 DOM 中,我不想写一个DOM 解析例程以获取该值。

标签: jquery asp.net asp.net-mvc asp.net-mvc-4


【解决方案1】:

您可以使用以下方法,而不是抛出异常:

return new HttpStatusCodeResult(500, "Could not delete category. This category has data associated with it. Please delete the associated data first.");

然后您可以从 textStatus 变量访问消息。

【讨论】:

  • 好点。我知道所有的选择。我只是想知道序列化异常在 jQuery XHR 对象中转换为什么。看起来 XHR 并不关心返回的响应的细节,在这种情况下,它恰好是一个 HTML DOM,我感兴趣的值被嵌入到 DOM 中,我不想写一个DOM 解析例程以获取该值。
  • 你说得对,Html 响应是 ASP.NET 特定的,仅用作视觉错误表示,在 Live 环境中会被 customErrors 掩盖。另一种方法是以编程方式处理错误的最佳方法。
  • 对死灵很抱歉,但这应该是答案......我正在使用带有 toastr 的 Telerik,这会触发 Telerik onerror 事件。我可以轻松地将 .xhr.statusText 放在 toastr.error 中。而不是抛出特定于 ASP.NET 的异常......它应该返回状态代码结果。不需要解析器。
【解决方案2】:

执行此操作的一种方法是将服务器上的操作的返回类型更改为JsonResult,然后将您的方法调用包装在try catch 中。然后,这允许您在发生异常时以 json 格式返回异常消息:

public JsonResult Delete(long[] fooIds)
{
    try
    {
        //make method calls
        return Json(new {});
    }
    catch(Exception ex)
    {
         return Json(new {exception = ex.message});
    }

}

【讨论】:

  • 如果你写 try catch 然后在 ajax 中调用 OnSuccess 方法每次都会被调用。 OnError 方法永远不会被调用
  • 您可以通过向返回的 json 对象添加成功布尔参数来解决此问题。然后,如果您的成功参数是 true 或 false,您可以签入您的 javascript,如果它等于 false,则写出异常。另一个选项可能是使用ASP.NET Web API 而不是标准控制器,这样您的操作可以返回一个 HttpResponseMessage ,您可以在其中手动设置响应代码并在响应正文中返回异常。
  • 好点。我知道所有的选择。我只是想知道序列化异常在 jQuery XHR 对象中转换为什么。看起来 XHR 并不关心返回的响应的细节,在这种情况下,它恰好是一个 HTML DOM,我感兴趣的值被嵌入到 DOM 中,我不想写一个DOM 解析例程以获取该值。
猜你喜欢
  • 2012-02-11
  • 2014-08-11
  • 2016-03-12
  • 2011-05-26
  • 2018-12-16
  • 2018-08-03
  • 1970-01-01
  • 2011-08-31
  • 2011-11-03
相关资源
最近更新 更多