using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Http; using System; using System.Net; using System.Net.Http; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using Microsoft.Extensions.Logging; using Sockeye.Util; using Sockeye.Biz; namespace Sockeye.Api.ControllerHelpers { /// /// This is essentially an unhandled exception handler /// public class ApiCustomExceptionFilter : IExceptionFilter { private readonly ILogger log; // public ApiCustomExceptionFilter(ILoggerFactory logger) // { // if (logger == null) // { // throw new ArgumentNullException(nameof(logger)); // } // this.log = logger.CreateLogger("Server Exception"); // } public ApiCustomExceptionFilter(ILogger logger) { if (logger == null) { throw new ArgumentNullException(nameof(logger)); } this.log = logger; } public void OnException(ExceptionContext context) { HttpStatusCode status = HttpStatusCode.InternalServerError; String message = String.Empty; #region If need to refine this further and deal with specific types // var exceptionType = context.Exception.GetType(); // if (exceptionType == typeof(UnauthorizedAccessException)) // { // message = "Unauthorized Access"; // status = HttpStatusCode.Unauthorized; // } // else if (exceptionType == typeof(NotImplementedException)) // { // message = "A server error occurred."; // status = HttpStatusCode.NotImplemented; // } // // else if (exceptionType == typeof(MyAppException)) // // { // // message = context.Exception.ToString(); // // status = HttpStatusCode.InternalServerError; // // } // else // { #endregion message = context.Exception.Message; status = HttpStatusCode.InternalServerError; //} //No need to log test exceptions to check and filter out bool loggableError = true; if (message.StartsWith("Test exception")) loggableError = false; //LOG IT if (loggableError) log.LogError(context.Exception, "Error"); //Notify ops notification issue NotifyEventHelper.AddOpsProblemEvent("Server API internal error, see log for more details", context.Exception).Forget();//.Wait(); HttpResponse response = context.HttpContext.Response; response.StatusCode = (int)status; response.ContentType = "application/json; charset=utf-8"; //This line is critical, without it the response is not proper and fails in various clients (postman, xunit tests with httpclient) context.ExceptionHandled = true; response.WriteAsync(JsonConvert.SerializeObject( new ApiErrorResponse(ApiErrorCode.API_SERVER_ERROR, "generalerror", "Server internal error; see server log for details"), new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() } )); } }//eoc }//eons