Mat*_*att 170 c# error-handling asp.net-web-api
我正在为客户开发API服务层,并且我被要求在全局范围内捕获并记录所有错误.
因此,虽然通过使用ELMAH或通过向以下内容添加类似内容,可以轻松处理类似未知端点(或操作)的内容Global.asax
:
protected void Application_Error()
{
Exception unhandledException = Server.GetLastError();
//do more stuff
}
Run Code Online (Sandbox Code Playgroud)
...不会记录与路由无关的未处理错误.例如:
public class ReportController : ApiController
{
public int test()
{
var foo = Convert.ToInt32("a");//Will throw error but isn't logged!!
return foo;
}
}
Run Code Online (Sandbox Code Playgroud)
我还尝试[HandleError]
通过注册此过滤器来全局设置该属性:
filters.Add(new HandleErrorAttribute());
Run Code Online (Sandbox Code Playgroud)
但这也不会记录所有错误.
如何拦截错误,例如通过调用/test
上面生成的错误,以便我可以记录它们?似乎这个答案应该是显而易见的,但我已经尝试了迄今为止我能想到的一切.
理想情况下,我想在错误记录中添加一些内容,例如请求用户的IP地址,日期,时间等.我还希望能够在遇到错误时自动通过电子邮件发送支持人员.所有这些我都可以做到,只要我能在它们发生时拦截这些错误!
感谢Darin Dimitrov,我接受了他的回答,我弄清楚了. 的WebAPI并没有以同样的方式作为一个普通MVC控制器处理错误.
这是有效的:
1)在命名空间中添加自定义过滤器:
public class ExceptionHandlingAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
if (context.Exception is BusinessException)
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent(context.Exception.Message),
ReasonPhrase = "Exception"
});
}
//Log Critical errors
Debug.WriteLine(context.Exception);
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent("An error occurred, please try again or contact the administrator."),
ReasonPhrase = "Critical Exception"
});
}
}
Run Code Online (Sandbox Code Playgroud)
2)现在在WebApiConfig类中全局注册过滤器:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{action}/{id}", new { id = RouteParameter.Optional });
config.Filters.Add(new ExceptionHandlingAttribute());
}
}
Run Code Online (Sandbox Code Playgroud)
或者您可以跳过注册,只使用[ExceptionHandling]
属性装饰一个控制器.
Vla*_*mir 77
作为以前答案的补充.
昨天,ASP.NET Web API 2.1正式发布.
它提供了另一个处理全球异常的机会.
详细信息在样本中给出.
简而言之,您添加全局异常记录器和/或全局异常处理程序(只有一个).
您将它们添加到配置:
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
// There can be multiple exception loggers.
// (By default, no exception loggers are registered.)
config.Services.Add(typeof(IExceptionLogger), new ElmahExceptionLogger());
// There must be exactly one exception handler.
// (There is a default one that may be replaced.)
config.Services.Replace(typeof(IExceptionHandler), new GenericTextExceptionHandler());
}
Run Code Online (Sandbox Code Playgroud)
他们的实现:
public class ElmahExceptionLogger : ExceptionLogger
{
public override void Log(ExceptionLoggerContext context)
{
...
}
}
public class GenericTextExceptionHandler : ExceptionHandler
{
public override void Handle(ExceptionHandlerContext context)
{
context.Result = new InternalServerErrorTextPlainResult(
"An unhandled exception occurred; check the log for more information.",
Encoding.UTF8,
context.Request);
}
}
Run Code Online (Sandbox Code Playgroud)
Dar*_*rov 55
如果您的Web API托管在ASP.NET应用程序中,Application_Error
则将为您的代码中的所有未处理异常调用该事件,包括您显示的测试操作中的异常.因此,您所要做的就是在Application_Error事件中处理此异常.在您显示的示例代码中,您只处理类型的异常,HttpException
这显然不是Convert.ToInt32("a")
代码的情况.因此,请确保您记录并处理其中的所有异常:
protected void Application_Error()
{
Exception unhandledException = Server.GetLastError();
HttpException httpException = unhandledException as HttpException;
if (httpException == null)
{
Exception innerException = unhandledException.InnerException;
httpException = innerException as HttpException;
}
if (httpException != null)
{
int httpCode = httpException.GetHttpCode();
switch (httpCode)
{
case (int)HttpStatusCode.Unauthorized:
Response.Redirect("/Http/Error401");
break;
// TODO: don't forget that here you have many other status codes to test
// and handle in addition to 401.
}
else
{
// It was not an HttpException. This will be executed for your test action.
// Here you should log and handle this case. Use the unhandledException instance here
}
}
}
Run Code Online (Sandbox Code Playgroud)
Web API中的异常处理可以在各个级别完成.这是一个detailed article
解释不同的可能性:
自定义异常过滤器属性,可以注册为全局异常过滤器
[AttributeUsage(AttributeTargets.All)]
public class ExceptionHandlingAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
if (context.Exception is BusinessException)
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent(context.Exception.Message),
ReasonPhrase = "Exception"
});
}
//Log Critical errors
Debug.WriteLine(context.Exception);
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent("An error occurred, please try again or contact the administrator."),
ReasonPhrase = "Critical Exception"
});
}
}
Run Code Online (Sandbox Code Playgroud)自定义动作调用者
public class MyApiControllerActionInvoker : ApiControllerActionInvoker
{
public override Task<HttpResponseMessage> InvokeActionAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken)
{
var result = base.InvokeActionAsync(actionContext, cancellationToken);
if (result.Exception != null && result.Exception.GetBaseException() != null)
{
var baseException = result.Exception.GetBaseException();
if (baseException is BusinessException)
{
return Task.Run<HttpResponseMessage>(() => new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent(baseException.Message),
ReasonPhrase = "Error"
});
}
else
{
//Log critical error
Debug.WriteLine(baseException);
return Task.Run<HttpResponseMessage>(() => new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent(baseException.Message),
ReasonPhrase = "Critical Error"
});
}
}
return result;
}
}
Run Code Online (Sandbox Code Playgroud)为什么要重新抛出?这有效,它将使服务返回状态500等
public class LogExceptionFilter : ExceptionFilterAttribute
{
private static readonly ILog log = LogManager.GetLogger(typeof (LogExceptionFilter));
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
log.Error("Unhandeled Exception", actionExecutedContext.Exception);
base.OnException(actionExecutedContext);
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
78969 次 |
最近记录: |