| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- using Diligent.WebAPI.Contracts.Exceptions;
- using Diligent.WebAPI.Contracts.Models;
- using Microsoft.AspNetCore.Mvc;
- using Microsoft.Extensions.Options;
- using Newtonsoft.Json;
- using Newtonsoft.Json.Serialization;
- using System.Diagnostics;
- using System.Net;
- using System.Runtime.Serialization;
-
- namespace Diligent.WebAPI.Host.Middlewares
- {
- public class DiligBadRequestException : Exception
- {
- public const string ExceptionMessage = "Bad request from custom middleware";
- public const string ExceptionCode = "DiligBadRequestException";
- public const HttpStatusCode HttpResponseCode = HttpStatusCode.BadRequest;
-
- public DiligBadRequestException() : base(ExceptionMessage) { }
- public DiligBadRequestException(string message) : base(message) { }
- public DiligBadRequestException(string message, Exception innerException) : base(message, innerException) { }
- public DiligBadRequestException(SerializationInfo info, StreamingContext context) : base(info, context) { }
- }
-
- public class DiligExceptionMiddleware
- {
- private readonly RequestDelegate _next;
- private readonly ILogger<DiligExceptionMiddleware> _logger;
- private readonly IWebHostEnvironment _env;
- private readonly ApiBehaviorOptions _options;
-
- public DiligExceptionMiddleware(RequestDelegate next, ILogger<DiligExceptionMiddleware> logger, IWebHostEnvironment env, IOptions<ApiBehaviorOptions> options)
- => (_next, _logger, _env, _options) = (next, logger, env, options.Value);
-
- public async Task InvokeAsync(HttpContext httpContext)
- {
- try
- {
- await _next(httpContext);
- }
- // Some custom Exceptions
- catch (EntityNotFoundException ex)
- {
- _logger.LogError(ex, DiligBadRequestException.ExceptionMessage);
- await HandleExceptionAsync(httpContext, ex, DiligBadRequestException.ExceptionMessage, HttpStatusCode.NotFound);
- }
- catch (Exception ex)
- {
- // Better solution is to use switch statement
- if(HasInternalExceptionOfType<DiligBadRequestException>(ex))
- {
- _logger.LogError(ex, DiligBadRequestException.ExceptionMessage);
- await HandleExceptionAsync(httpContext, ex, DiligBadRequestException.ExceptionMessage, DiligBadRequestException.HttpResponseCode);
- }
- else
- {
- await HandleSomethingWentWrongAsync(httpContext, ex);
- }
- }
- }
-
- private async Task HandleSomethingWentWrongAsync(HttpContext httpContext, Exception ex)
- {
- _logger.LogError(ex, "Something went wrong");
- await HandleExceptionAsync(httpContext, ex);
- }
-
- private bool HasInternalExceptionOfType<T>(Exception e)
- {
- if(e.InnerException != null)
- {
- return e is T || HasInternalExceptionOfType<T>(e.InnerException);
- }
- return e is T;
- }
-
- private Task HandleExceptionAsync(HttpContext context, Exception exception, string? message = null, HttpStatusCode? responseCode = null)
- {
- context.Response.ContentType = "application/json";
- context.Response.StatusCode = (int)(responseCode ?? HttpStatusCode.InternalServerError);
- string type = null;
-
- if (_options.ClientErrorMapping.TryGetValue(context.Response.StatusCode, out var clientErrorData))
- {
- type = clientErrorData.Link;
- }
-
- var errorTitle = message ?? (_env.IsDevelopment() ? exception.Message : "Internal server error");
- var errorMessage = _env.IsDevelopment() ? exception.StackTrace : "Something went wrong" ;
-
- var serializerSettings = new JsonSerializerSettings
- {
- ContractResolver = new CamelCasePropertyNamesContractResolver()
- };
- var resultError = new ResultError(errorTitle);
- var httpResultError = new HttpResultError()
- {
- ErrorMessage = errorMessage,
- ErrorCode = responseCode ?? HttpStatusCode.InternalServerError
- };
- resultError.AddCustomError(httpResultError);
- var responseString = JsonConvert.SerializeObject(
- new BaseResult<Exception>
- {
- // Type = type,
- // TraceId = Activity.Current?.Id ?? context?.TraceIdentifier,
- IsSuccess = false,
- Errors = { resultError }
- }, serializerSettings);
-
- return context.Response.WriteAsync(responseString);
- }
- }
-
- public static class DiligExceptionMiddlewareExtensions
- {
- public static IApplicationBuilder UseDiligExceptionHandler(this IApplicationBuilder app)
- {
- return app.UseMiddleware<DiligExceptionMiddleware>();
- }
- }
- }
|