iPackage/iPackage.Core.Web/WebFramework/Middlewares/ExceptionHandlerMiddleware.cs

141 lines
5.1 KiB
C#

using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using iPackage.Models.Api;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
namespace iPackage.Core.Web.WebFramework.Middlewares
{
public static class ExceptionHandlerMiddlewareExtensions
{
public static IApplicationBuilder UseExceptionHandlerMiddleware(this IApplicationBuilder applicationBuilder)
{
return applicationBuilder.UseMiddleware<ExceptionHandlerMiddleware>();
}
}
public class ExceptionHandlerMiddleware
{
private readonly RequestDelegate _next;
private readonly IHostingEnvironment _env;
private readonly ILogger<ExceptionHandlerMiddleware> _logger;
public ExceptionHandlerMiddleware(RequestDelegate next,
IHostingEnvironment env,
ILogger<ExceptionHandlerMiddleware> logger)
{
_next = next;
_env = env;
_logger = logger;
}
public async Task Invoke(HttpContext context)
{
string message = null;
HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError;
ApiResultStatusCode apiStatusCode = ApiResultStatusCode.ServerError;
try
{
await _next(context);
}
catch (AppException exception)
{
_logger.LogError(exception, exception.Message);
httpStatusCode = exception.HttpStatusCode;
apiStatusCode = exception.ApiStatusCode;
if (_env.IsDevelopment())
{
var dic = new Dictionary<string, string>
{
["Exception"] = exception.Message,
["StackTrace"] = exception.StackTrace,
};
if (exception.InnerException != null)
{
dic.Add("InnerException.Exception", exception.InnerException.Message);
dic.Add("InnerException.StackTrace", exception.InnerException.StackTrace);
}
if (exception.AdditionalData != null)
dic.Add("AdditionalData", JsonConvert.SerializeObject(exception.AdditionalData));
message = JsonConvert.SerializeObject(dic);
}
else
{
message = exception.Message;
}
await WriteToResponseAsync();
}
catch (SecurityTokenExpiredException exception)
{
_logger.LogError(exception, exception.Message);
SetUnAuthorizeResponse(exception);
await WriteToResponseAsync();
}
catch (UnauthorizedAccessException exception)
{
_logger.LogError(exception, exception.Message);
SetUnAuthorizeResponse(exception);
await WriteToResponseAsync();
}
catch (Exception exception)
{
_logger.LogError(exception, exception.Message);
if (_env.IsDevelopment())
{
var dic = new Dictionary<string, string>
{
["Exception"] = exception.Message,
["InnerException"] = exception.InnerException?.Message,
["StackTrace"] = exception.StackTrace,
};
message = JsonConvert.SerializeObject(dic);
}
await WriteToResponseAsync();
}
async Task WriteToResponseAsync()
{
if (context.Response.HasStarted)
throw new InvalidOperationException("The response has already started, the http status code middleware will not be executed.");
var result = new ApiResult(false, apiStatusCode, message);
var json = JsonConvert.SerializeObject(result);
context.Response.StatusCode = (int)httpStatusCode;
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(json);
}
void SetUnAuthorizeResponse(Exception exception)
{
httpStatusCode = HttpStatusCode.Unauthorized;
apiStatusCode = ApiResultStatusCode.UnAuthorized;
if (_env.IsDevelopment())
{
var dic = new Dictionary<string, string>
{
["Exception"] = exception.Message,
["StackTrace"] = exception.StackTrace
};
if (exception is SecurityTokenExpiredException tokenException)
dic.Add("Expires", tokenException.Expires.ToString());
message = JsonConvert.SerializeObject(dic);
}
}
}
}
}