我有一个WebAPI
项目,正在将exception
从try/catch
移到exception
filters
。以前当我使用try/catch
块时,我能够访问SQL
命令对象以获取SQL
命令文本以登录到数据库。现在我转向异常过滤器,我不再能够访问SQL
命令对象。我所追求的是一种将最后执行的SQL
命令传递给异常过滤器的方法,以便我仍然可以记录它。
以前的代码(try / catch blocks)
public HttpResponseMessage API([FromBody] int roomID)
{
HttpResponseMessage msg = null;
SqlCommand comm = Common.Shared.ConnectDB();
try
{
List<Models.room> room = room(comm, roomID);
msg = Request.CreateResponse(HttpStatusCode.OK, room);
}
catch (CustomException ex)
{
msg = Request.CreateResponse(HttpStatusCode.BadRequest, ex.Message);
}
catch (Exception ex)
{
comm.Parameters.Clear();
var sourceFunction = "rooms";
var returnException = Common.Logging.CreateLog(ex, comm, sourceFunction);
msg = Request.CreateResponse(HttpStatusCode.InternalServerError, returnException);
}
finally
{
comm.Connection.Close();
}
return msg;
}
异常过滤器代码
public class InternalServerErrorFilter : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
Log.Error(context.Exception, "Exception Information");
context.Response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
}
}
控制器异常过滤器
[InternalServerErrorFilter]
[HttpPost]
public HttpResponseMessage API([FromBody] int roomID)
{
HttpResponseMessage msg = null;
SqlCommand comm = Common.Shared.ConnectDB();
try
{
List<Models.room> room = room(comm, roomID);
msg = Request.CreateResponse(HttpStatusCode.OK, room);
}
finally
{
comm.Connection.Close();
}
return msg;
}
答案 0 :(得分:1)
您可以通过几种方式处理这种情况:
检查并将Exception
类型转换为更具体的例外,例如SqlException
(检查documentation)。在SqlException
内,您将能够找到该异常的原因。
public class InternalServerErrorFilter : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
if (context.Exception is SqlException)
{
var sqlException = (SqlException)context.Exception;
//Do your logging...
}
context.Response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
}
}
或者您可以创建自定义sql例外,您可以将SqlCommand
传递给它以进行进一步的记录。但是,您需要检查类型(如上所述)才能获得强类型访问权。
public class CustomSqlException : Exception
{
public SqlCommand ExecutedCommand { get; }
public CustomException(SqlCommand executedCommand)
: base("Custom Message")
{
ExecutedCommand = executedCommand;
}
}
public class InternalServerErrorFilter : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
if (context.Exception is CustomSqlException)
{
var sqlException = (CustomSqlException)context.Exception;
var command = sqlException.ExecutedCommand;
//Do your logging...
}
context.Response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
}
}
用法:
[InternalServerErrorFilter]
[HttpPost]
public HttpResponseMessage API([FromBody] int roomID)
{
HttpResponseMessage msg = null;
SqlCommand comm = Common.Shared.ConnectDB();
try
{
List<Models.room> room = room(comm, roomID);
msg = Request.CreateResponse(HttpStatusCode.OK, room);
}
catch (SqlException ex)
{
throw new CustomSqlException(comm);
}
finally
{
comm.Connection.Close();
}
return msg;
}
我建议您使用第一种方法,因为SqlException
应该具有在SQL服务器上执行SQL命令时出现的错误的所有必要信息。除此之外,由于抛出新的异常,您不会丢失堆栈跟踪。
如果您决定使用第二个解决方案,则可以通过将异常作为CustomSqlException
的内部异常传递来避免丢失堆栈跟踪的问题。