Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. using Diligent.WebAPI.Contracts.Exceptions;
  2. using Diligent.WebAPI.Contracts.Models;
  3. using Microsoft.AspNetCore.Mvc;
  4. using Microsoft.Extensions.Options;
  5. using Newtonsoft.Json;
  6. using Newtonsoft.Json.Serialization;
  7. using System.Diagnostics;
  8. using System.Net;
  9. using System.Runtime.Serialization;
  10. namespace Diligent.WebAPI.Host.Middlewares
  11. {
  12. public class DiligBadRequestException : Exception
  13. {
  14. public const string ExceptionMessage = "Bad request from custom middleware";
  15. public const string ExceptionCode = "DiligBadRequestException";
  16. public const HttpStatusCode HttpResponseCode = HttpStatusCode.BadRequest;
  17. public DiligBadRequestException() : base(ExceptionMessage) { }
  18. public DiligBadRequestException(string message) : base(message) { }
  19. public DiligBadRequestException(string message, Exception innerException) : base(message, innerException) { }
  20. public DiligBadRequestException(SerializationInfo info, StreamingContext context) : base(info, context) { }
  21. }
  22. public class DiligExceptionMiddleware
  23. {
  24. private readonly RequestDelegate _next;
  25. private readonly ILogger<DiligExceptionMiddleware> _logger;
  26. private readonly IWebHostEnvironment _env;
  27. private readonly ApiBehaviorOptions _options;
  28. public DiligExceptionMiddleware(RequestDelegate next, ILogger<DiligExceptionMiddleware> logger, IWebHostEnvironment env, IOptions<ApiBehaviorOptions> options)
  29. => (_next, _logger, _env, _options) = (next, logger, env, options.Value);
  30. public async Task InvokeAsync(HttpContext httpContext)
  31. {
  32. try
  33. {
  34. await _next(httpContext);
  35. }
  36. // Some custom Exceptions
  37. catch (EntityNotFoundException ex)
  38. {
  39. _logger.LogError(ex, DiligBadRequestException.ExceptionMessage);
  40. await HandleExceptionAsync(httpContext, ex, DiligBadRequestException.ExceptionMessage, HttpStatusCode.NotFound);
  41. }
  42. catch (Exception ex)
  43. {
  44. // Better solution is to use switch statement
  45. if(HasInternalExceptionOfType<DiligBadRequestException>(ex))
  46. {
  47. _logger.LogError(ex, DiligBadRequestException.ExceptionMessage);
  48. await HandleExceptionAsync(httpContext, ex, DiligBadRequestException.ExceptionMessage, DiligBadRequestException.HttpResponseCode);
  49. }
  50. else
  51. {
  52. await HandleSomethingWentWrongAsync(httpContext, ex);
  53. }
  54. }
  55. }
  56. private async Task HandleSomethingWentWrongAsync(HttpContext httpContext, Exception ex)
  57. {
  58. _logger.LogError(ex, "Something went wrong");
  59. await HandleExceptionAsync(httpContext, ex);
  60. }
  61. private bool HasInternalExceptionOfType<T>(Exception e)
  62. {
  63. if(e.InnerException != null)
  64. {
  65. return e is T || HasInternalExceptionOfType<T>(e.InnerException);
  66. }
  67. return e is T;
  68. }
  69. private Task HandleExceptionAsync(HttpContext context, Exception exception, string? message = null, HttpStatusCode? responseCode = null)
  70. {
  71. context.Response.ContentType = "application/json";
  72. context.Response.StatusCode = (int)(responseCode ?? HttpStatusCode.InternalServerError);
  73. string type = null;
  74. if (_options.ClientErrorMapping.TryGetValue(context.Response.StatusCode, out var clientErrorData))
  75. {
  76. type = clientErrorData.Link;
  77. }
  78. var errorTitle = message ?? (_env.IsDevelopment() ? exception.Message : "Internal server error");
  79. var errorMessage = _env.IsDevelopment() ? exception.StackTrace : "Something went wrong" ;
  80. var serializerSettings = new JsonSerializerSettings
  81. {
  82. ContractResolver = new CamelCasePropertyNamesContractResolver()
  83. };
  84. var resultError = new ResultError(errorTitle);
  85. var httpResultError = new HttpResultError()
  86. {
  87. ErrorMessage = errorMessage,
  88. ErrorCode = responseCode ?? HttpStatusCode.InternalServerError
  89. };
  90. resultError.AddCustomError(httpResultError);
  91. var responseString = JsonConvert.SerializeObject(
  92. new BaseResult<Exception>
  93. {
  94. // Type = type,
  95. // TraceId = Activity.Current?.Id ?? context?.TraceIdentifier,
  96. IsSuccess = false,
  97. Errors = { resultError }
  98. }, serializerSettings);
  99. return context.Response.WriteAsync(responseString);
  100. }
  101. }
  102. public static class DiligExceptionMiddlewareExtensions
  103. {
  104. public static IApplicationBuilder UseDiligExceptionHandler(this IApplicationBuilder app)
  105. {
  106. return app.UseMiddleware<DiligExceptionMiddleware>();
  107. }
  108. }
  109. }