C# 使用FilterAttributes处理Web API异常
我有一个过滤器可以捕获错误并记录它们,但我希望它返回正确的HttpStatusCode,以便我的客户端应用程序可以显示一条正确的错误消息。 目前,在我的filter属性的overridedOnException方法中,我试图通过将异常转换为HttpException来获取状态码。 这看起来像这样: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
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语句将是巨大的。搜索“带模式的开关语句”。请验证此操作是否有效。。。因为我不能完全理解它在抱怨什么?“类名在这一点上是无效的”无论你放在什么情况下,每个返回匹配都有一个以上的情况,你会明白我的意思。