I am developing an API Service Layer for a client and I have been requested to catch and log all errors globally.
So, while something like an un
If your web API is hosted inside an ASP.NET application, the Application_Error event will be called for all unhandled exceptions in your code, including the one in the test action you have shown. So all you have to do is handle this exception inside the Application_Error event. In the sample code you have shown you are only handling exception of type HttpException which is obviously not the case with the Convert.ToInt32("a") code. So make sure that you log and handle all exceptions in there:
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
}
}
}
Exception handling in the Web API could be done at various levels. Here's a detailed article explaining the different possibilities:
custom exception filter attribute which could be registered as a global exception filter
[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"
});
}
}
custom action invoker
public class MyApiControllerActionInvoker : ApiControllerActionInvoker
{
public override Task 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(() => new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent(baseException.Message),
ReasonPhrase = "Error"
});
}
else
{
//Log critical error
Debug.WriteLine(baseException);
return Task.Run(() => new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent(baseException.Message),
ReasonPhrase = "Critical Error"
});
}
}
return result;
}
}