如何将其他异常数据传递给C#中的全局异常过滤器?

时间:2017-01-24 23:15:17

标签: c# asp.net-web-api2

我正在开发一个WebAPI 2项目,并且我实现了一个全局错误过滤器属性,如下所示:

public class MyExceptionFilterAttribute: ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecuteContext context)
    {
        if (context.Exception is MyException)
        {
             // Handle MyException
        }
        else if (context.Exception is UnauthorizedAccessException)
        {
            // Handle UnauthorizedAccessException
        }
    }
}

当我调用外部API并收到错误响应时,我抛出MyException

var httpResponseMessage = _httpClient.GetAsync(request).Result;
if (!httpResponseMessage.IsSuccessStatusCode)
{
    var message = "Error calling external API";
    var except = new MyException(message);
    throw except;
}

我想将API返回的状态代码作为MyException的一部分传递给全局错误过滤器。我的第一次尝试是将状态代码添加为MyException的属性。

public class MyException : Exception
{
    public HttpStatusCode statusCode;
    public MyException() : base() { }
    public MyException(string message, HttpStatusCode statusCode) : base(message)
    {
        this.statusCode = statusCode;
    }
}

在抛出异常中:

var httpResponseMessage = _httpClient.GetAsync(request).Result;
if (!httpResponseMessage.IsSuccessStatusCode)
{
    var message = "Error calling external API";
    var except = new MyException(message, httpResponseMessage.StatusCode);
    throw except;
}

然后在我的过滤器中,我将context.Exception投回到MyException并尝试访问该属性,但该属性始终以null的形式返回。

var ex = context.Exception as MyException;
var code = ex.statusCode; // Always comes back as null

我的第二次尝试是将状态代码添加到Data继承自MyException的{​​{1}}媒体资源。

Exception

但是,当我尝试在过滤器中访问它时,var httpResponseMessage = _httpClient.GetAsync(request).Result; if (!httpResponseMessage.IsSuccessStatusCode) { var message = "Error calling external API"; var except = new MyException(message); except.Data.add("status", httpResponseMessage.StatusCode); throw except; } 没有密钥。我知道我可以在我的异常消息中包含状态代码,然后在过滤器中解析它,但我宁愿不这样做,因为我认为它是错误的解决方案。如何将状态代码提供给我的异常过滤器,以便在处理异常时可以使用它?

1 个答案:

答案 0 :(得分:0)

异常可能会在调用堆栈中被包含在更高的位置。然后它将处于内部异常中。您可以迭代所有内部异常以查看它们中是否有任何异常,但访问属性的代码应该按预期工作。

        var ex = context.Exception;
        while (ex != null)
        {
            if (ex is MyException)
            {
                // Do work
                break;
            }

            ex = ex.InnerException;
        }