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)
将其他详细信息添加到响应正文中,但请牢记这一点的安全隐患。
如果 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)
将其他详细信息添加到响应正文中,但请牢记这一点的安全隐患。