C# 使用FilterAttributes处理Web API异常

C# 使用FilterAttributes处理Web API异常,c#,error-handling,asp.net-web-api2,C#,Error Handling,Asp.net Web Api2,我有一个过滤器可以捕获错误并记录它们,但我希望它返回正确的HttpStatusCode,以便我的客户端应用程序可以显示一条正确的错误消息。 目前,在我的filter属性的overridedOnException方法中,我试图通过将异常转换为HttpException来获取状态码。 这看起来像这样: public class LogExceptionFilterAttribute : ExceptionFilterAttribute { // Private properties

我有一个过滤器可以捕获错误并记录它们,但我希望它返回正确的HttpStatusCode,以便我的客户端应用程序可以显示一条正确的错误消息。 目前,在我的filter属性的overridedOnException方法中,我试图通过将异常转换为HttpException来获取状态码。 这看起来像这样:

public class LogExceptionFilterAttribute : ExceptionFilterAttribute
{

    // Private properties
    private readonly ILogProvider _logger;

    /// <summary>
    /// Our default constructor
    /// </summary>
    /// <param name="logger"></param>
    public LogExceptionFilterAttribute(ILogProvider logger)
    {
        _logger = logger;
    }

    /// <summary>
    /// Invoked when an exception has been thrown
    /// </summary>
    /// <param name="context">The context</param>
    public override async void OnException(HttpActionExecutedContext context)
    {

        // Get our user
        var requestContext = context.Request.GetRequestContext();
        var user = requestContext.Principal.Identity;

        // Create our response
        var message = await _logger.ErrorAsync(context.Exception, user);
        var content = new HttpResponseMessage
        {
            Content = new StringContent(message),
            StatusCode = GetStatusCodeFromException(context)
        };

        // Assign our response to our context
        context.Response = content;
    }

    /// <summary>
    /// Gets a status code from an error
    /// </summary>
    /// <param name="context">The context</param>
    /// <returns></returns>
    private static HttpStatusCode GetStatusCodeFromException(HttpActionExecutedContext context)
    {

        // Cast the exception as an HttpException
        var exception = context.Exception as HttpException;

        // If we don't have an exception
        if (exception != null)
        {

            // Return the HttpException code
            return (HttpStatusCode)exception.GetHttpCode();
        }

        // Return Internal Server Error
        return HttpStatusCode.InternalServerError;
    }
}
private static HttpStatusCode GetStatusCodeFromException(HttpActionExecutedContext context)
{

    // Cast the exception as an HttpException
    var exception = context.Exception as HttpException;

    // If there is still an exception, return the code
    if (exception != null)
        return (HttpStatusCode)exception.GetHttpCode();

    // Otherwise, work out what type of error we have
    switch(context.Exception.GetType().ToString())
    {
        case "NullReferenceException":
            return HttpStatusCode.BadRequest;
        default:
            return HttpStatusCode.InternalServerError;
    }
}
private static HttpStatusCode GetStatusCodeFromException(HttpActionExecutedContext context)
{

    // Cast the exception as an HttpException
    var exception = context.Exception as HttpException;

    // If there is still an exception, return the code
    if (exception != null)
        return (HttpStatusCode)exception.GetHttpCode();

    // Witch on the exception type
    switch (context.Exception)
    {
        case ObjectNotFoundException ex:
            return HttpStatusCode.NotFound;
        default:
            return HttpStatusCode.InternalServerError;
    }
}
但现在我不确定这是否正确。
有人能帮我扩展一下,或者告诉我一种更好的方法吗?

与其在名称上比较类型,不如实际检查类型本身:

if (context.Exception is NullReferenceException)
{
    return HttpStatusCode.BadProgrammer;
}
else
{
    return HttpStatusCode.InternalServerError;
}

我已将@Patrick Hofman的答案标记为正确,但我使用c#7来生成一个switch语句,如下所示:

public class LogExceptionFilterAttribute : ExceptionFilterAttribute
{

    // Private properties
    private readonly ILogProvider _logger;

    /// <summary>
    /// Our default constructor
    /// </summary>
    /// <param name="logger"></param>
    public LogExceptionFilterAttribute(ILogProvider logger)
    {
        _logger = logger;
    }

    /// <summary>
    /// Invoked when an exception has been thrown
    /// </summary>
    /// <param name="context">The context</param>
    public override async void OnException(HttpActionExecutedContext context)
    {

        // Get our user
        var requestContext = context.Request.GetRequestContext();
        var user = requestContext.Principal.Identity;

        // Create our response
        var message = await _logger.ErrorAsync(context.Exception, user);
        var content = new HttpResponseMessage
        {
            Content = new StringContent(message),
            StatusCode = GetStatusCodeFromException(context)
        };

        // Assign our response to our context
        context.Response = content;
    }

    /// <summary>
    /// Gets a status code from an error
    /// </summary>
    /// <param name="context">The context</param>
    /// <returns></returns>
    private static HttpStatusCode GetStatusCodeFromException(HttpActionExecutedContext context)
    {

        // Cast the exception as an HttpException
        var exception = context.Exception as HttpException;

        // If we don't have an exception
        if (exception != null)
        {

            // Return the HttpException code
            return (HttpStatusCode)exception.GetHttpCode();
        }

        // Return Internal Server Error
        return HttpStatusCode.InternalServerError;
    }
}
private static HttpStatusCode GetStatusCodeFromException(HttpActionExecutedContext context)
{

    // Cast the exception as an HttpException
    var exception = context.Exception as HttpException;

    // If there is still an exception, return the code
    if (exception != null)
        return (HttpStatusCode)exception.GetHttpCode();

    // Otherwise, work out what type of error we have
    switch(context.Exception.GetType().ToString())
    {
        case "NullReferenceException":
            return HttpStatusCode.BadRequest;
        default:
            return HttpStatusCode.InternalServerError;
    }
}
private static HttpStatusCode GetStatusCodeFromException(HttpActionExecutedContext context)
{

    // Cast the exception as an HttpException
    var exception = context.Exception as HttpException;

    // If there is still an exception, return the code
    if (exception != null)
        return (HttpStatusCode)exception.GetHttpCode();

    // Witch on the exception type
    switch (context.Exception)
    {
        case ObjectNotFoundException ex:
            return HttpStatusCode.NotFound;
        default:
            return HttpStatusCode.InternalServerError;
    }
}

我希望捕获
NullReferenceException
是一个输入错误。
NullReferenceException
是一个不错的请求。这太完美了
InternalServerError
。http的正常状态是200 Done。因此,您不希望为200创建异常。根据服务器的不同,状态代码也会有所不同,因此对于相同的错误,您可能不会总是得到500。维护服务器的人不希望黑客对错误消息进行反向工程,以便他们提供尽可能少的关于真实错误的信息。这只是一个例子,我想为所有异常类型设置。例如,我想返回404的NotFoundException…我可以不作为switch语句来执行吗?似乎做一个if语句将是巨大的。搜索“带模式的开关语句”。请验证此操作是否有效。。。因为我不能完全理解它在抱怨什么?“类名在这一点上是无效的”无论你放在什么情况下,每个返回匹配都有一个以上的情况,你会明白我的意思。