HttpHandler 在捕获 SqlException 后不发送响应?

HttpHandler does not send response after catching SqlException?

如果 con.Open() 抛出异常,例如 faultyConnectionString 的数据库名称无效,则此 HttpHandler 不会发送响应。为什么?

public void ProcessRequest(HttpContext context)
{
    int status = 400;
    string message = "Test error!";
    string faultyConnectionString = "Data Source=LOCALHOST\SQLEXPRESS;Initial Catalog=XXX;User ID=XXX;Password=XXX";
    try
    {
        using (SqlConnection con = new SqlConnection(faultyConnectionString))
        {
            //throw new Exception("This works as expected, and is returned to client");
            con.Open();
        }
    }
    catch (Exception ex)
    {
        status = 500;
        message = "Test Exception: " + ex.Message;
    }

    context.Response.StatusCode = status;
    context.Response.StatusDescription = message;
}

这是我在客户端处理调用的方式:

function GetContacts() {
  $.ajax({
    type: "POST",
    url: "xxx.ashx",
    data: "",
    contentType: "application/x-www-form-urlencoded; charset=utf-8",
    dataType: "text", // "json",
    success: function (response, a, b) {
        alert(response.status + " " + response.statusText);
    },
    error: function (response, a, b) {
        alert(response.status + " " + response.statusText);
    }
  });
}

如果我在 FireFox 中按 F12,它显示在发送请求后没有收到响应。在 IE 中它显示 "SCRIPT7002: XMLHttpRequest: Network Error 0x2ef3, Could not complete the operation due to error 00002ef3."。在这两种情况下,jquery ajax 调用 returns status=0 和 statusText="error".

如果我注释掉 catch 块中的两行,那么它会按预期工作,向客户端发送 403 代码并忽略异常。

不同类型的异常不会出现同样的问题。如果我在 con.Open() 之前抛出一个新的 Exception() 那么它也会按预期工作。 SqlException 有什么不同?

更新:我第一次点击 ProcessRequest 时,它在客户端显示 status=0 结果之前连续调用了 5 次(第一行的断点被点击了 5 次)。

FIDDLER:如果我启动 Fiddler,它 (fiddler) 会拦截事务并向我的 ajax 调用发送“504 Fiddler - 接收失败”。看起来最初的重复可能是一种重试机制,当提琴手处于活动状态时,它会重复 13 次。 Fiddler 报告:"Session #xxx raised exception System.Net.Sockets.SocketException An existing connection was forcibly closed by the remote host".

我相信您的客户端(浏览器)处理 404 错误的方式是造成这种情况的原因,并且每种浏览器类型对错误的处理方式不同。 404 错误特定于 "Not Found",因此您可能需要使用不同的错误代码,例如 500 错误。此处提供了有关错误代码的更多信息:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

请记住,由于信息泄露,将详细的错误消息传回客户端可能是一个安全问题。您最好将一般错误传回客户端并在服务器端记录详细的错误信息。

编辑: 在本地进行测试,您将 context.Response.StatusDescription 设置为包含 ex.Message 的方式会产生无效的 HTTP 响应。尝试只在其中放置诸如 Internal Server Error 之类的文本。可以使用 context.Response.Write(bodyText) 将其他详细信息添加到响应正文中,但请牢记这一点的安全隐患。