Last active
June 26, 2019 05:58
-
-
Save seangwright/139868f800503c118be9675cc8aa02c3 to your computer and use it in GitHub Desktop.
Error Handling in Web Api 2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ApiExceptionResult : IHttpActionResult | |
{ | |
private static readonly MediaTypeHeaderValue mediaType = new MediaTypeHeaderValue("application/json"); | |
private readonly ApiError errorResponse; | |
private readonly JsonMediaTypeFormatter jsonMediaTypeFormatter; | |
private readonly HttpRequestMessage requestMessage; | |
private readonly HttpStatusCode statusCode; | |
public ApiExceptionResult(HttpRequestMessage requestMessage, HttpStatusCode statusCode, ApiError errorResponse, JsonMediaTypeFormatter jsonMediaTypeFormatter) | |
{ | |
Guard.Against.Null(requestMessage, nameof(requestMessage)); | |
Guard.Against.Null(statusCode, nameof(statusCode)); | |
Guard.Against.Null(errorResponse, nameof(errorResponse)); | |
Guard.Against.Null(jsonMediaTypeFormatter, nameof(jsonMediaTypeFormatter)); | |
this.requestMessage = requestMessage; | |
this.statusCode = statusCode; | |
this.errorResponse = errorResponse; | |
this.jsonMediaTypeFormatter = jsonMediaTypeFormatter; | |
} | |
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) | |
{ | |
var response = requestMessage.CreateResponse(statusCode, errorResponse, jsonMediaTypeFormatter, mediaType); | |
return Task.FromResult(response); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class GlobalApiExceptionHandler : IExceptionHandler | |
{ | |
private readonly JsonMediaTypeFormatter jsonMediaTypeFormatter; | |
public GlobalApiExceptionHandler(JsonMediaTypeFormatter jsonMediaTypeFormatter) | |
{ | |
Guard.Against.Null(jsonMediaTypeFormatter, nameof(jsonMediaTypeFormatter)); | |
this.jsonMediaTypeFormatter = jsonMediaTypeFormatter; | |
} | |
public Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken) | |
{ | |
var exception = context.Exception; | |
var (code, error) = BuildError(exception); | |
// Use your logging framework of choice or Kentico's EventLogProvider.LogException() | |
// to log your error before sending the response | |
context.Result = new ApiExceptionResult(context.Request, code, error, jsonMediaTypeFormatter); | |
return Task.CompletedTask; | |
} | |
private (HttpStatusCode code, ApiError error) BuildError(Exception exception) | |
{ | |
var buildApiError = CaptureErrorId(Guid.NewGuid()); | |
switch (exception) | |
{ | |
case HttpException httpEx: | |
return ((HttpStatusCode)httpEx.GetHttpCode(), buildApiError("HTTP_EXCEPTION", "Server error")); | |
case NotAuthenticatedException notAuthNEx: | |
return (HttpStatusCode.Unauthorized, buildApiError("NOT_AUTHENTICATED", "This endpoint reuires authentication")); | |
case NotAuthorizedException notAuthZEx: | |
return (HttpStatusCode.Forbidden, buildApiError("NOT_AUTHORIZED", "The request was not authorized to perform that action")); | |
case BadRequestException badRequestEx: | |
return (HttpStatusCode.BadRequest, buildApiError("BAD_REQUEST", "The request was malformed")); | |
case NotFoundException notFoundEx: | |
return (HttpStatusCode.NotFound, buildApiError("NOT_FOUND", "The requested data could not be found")); | |
default: | |
return (HttpStatusCode.InternalServerError, buildApiError("APPLICATION_EXCEPTION", "Server error")); | |
} | |
} | |
private Func<string, string, ApiError> CaptureErrorId(Guid errorId) => | |
(string errorCode, string errorMessage) => | |
new ApiError(errorId, errorCode, errorMessage); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class WebApiConfig | |
{ | |
public static HttpConfiguration ConfigureWebApi(IContainer container) | |
{ | |
// ... | |
config.Services.Replace(typeof(IExceptionHandler), container.Resolve<GlobalApiExceptionHandler>()); | |
// ... | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment