Los errores y excepciones fueron gestionados de una manera centralizada. No fueron capturados mediante Try - Catch así que ascienden la pila de llamadas hasta ser recogidos por un filtro personalizado que mapea el codigo de estado Http y responde a Front con un código de error para mostrar un mensaje dado. En la API se añadió el siguiente código para llevarlo a cabo:
public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAtribute()); } }
public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { ... FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); ... } }
GlobalConfiguration.Configure(WebApiConfig.Register); FilterConfig.RegisterWebApiFilters(GlobalConfiguration.Configuration.Filters)Y modificar la clase FilterConfig como:
public class FilterConfig { public static void RegisterWebApiFilters(HtttpFilterCollection filters) { filters.Add(new ExceptionHandlerFilter()); } }
public enum APIExceptionType { HttpException = 0, BadRequest = 1, InternalError = 2, // Seccion 1 TotalValueCalculationError = 3 }
public class APIException : Exception { public APIExceptionType ExceptionCode { get; private set; } public string ExtraInformation { get; private set; } public APIException(APIExceptionType exceptionCode, string extraInformation = null) { ExceptionCode = exceptionCode; ExtraInformation = extraInformation; } public string ToJson() { return string.Format("{{code : {0} , info: {1}}}", ExceptionCode, ExtraInformation); } }
public class ExceptionHandlerFilter : ExceptionFilterAttribute { public IDictionaryMappings { get; private set; } public ExceptionHandlerFilter() { Mappings = new Dictionary (); Mappings.Add(typeof(InvalidOperationException), HttpStatusCode.BadRequest); Mappings.Add(typeof(ArgumentOutOfRangeException), HttpStatusCode.BadRequest); Mappings.Add(typeof(ArgumentNullException), HttpStatusCode.BadRequest); Mappings.Add(typeof(ArgumentException), HttpStatusCode.BadRequest); } public override void OnException(HttpActionExecutedContext context) { if (context.Exception == null) return; var exception = context.Exception; if (exception is HttpException) { var httpException = (HttpException)exception; context.Response = context.Request.CreateResponse((HttpStatusCode)httpException.GetHttpCode(), APIExceptionType.HttpException); } else if (Mappings.ContainsKey(exception.GetType())) { var httpStatusCode = Mappings[exception.GetType()]; context.Response = context.Request.CreateResponse(httpStatusCode, APIExceptionType.BadRequest); } else if(exception is APIException) { var apiException = (APIException)exception; context.Response = context.Request.CreateResponse(HttpStatusCode.InternalServerError, apiException.ExceptionCode); //TODO: Exception as Json with {code : xxx, info: yyy} structure //context.Response = context.Request.CreateResponse(HttpStatusCode.InternalServerError, apiException.ToJson()); } else { context.Response = context.Request.CreateResponse(HttpStatusCode.InternalServerError, APIExceptionType.InternalError); } } }
if (calculoejemplo == false) throw new APIException(APIExceptionType.TotalValueCalculationError);
Anotar que algunos de los Tests se desarrollaron esperando una respuesta de Excepción. Para ello se decoraron con:
[ExpectedException(typeof(APIException))]