将值传递给ExceptionFilter

时间:2017-05-29 05:33:44

标签: c# asp.net-web-api exception-handling

我有一个WebAPI项目,正在将exceptiontry/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;
}

1 个答案:

答案 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的内部异常传递来避免丢失堆栈跟踪的问题。