Kit.Core/LibCommon/Kit.Core.Helpers/Middleware/ExceptionHandlerMiddleware.cs

156 lines
5.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
namespace Kit.Helpers;
public enum StackTraceModesJson
{
None = 0,
Text = 1,
Html = 2
}
public enum StackTraceModesHtml
{
None = 0,
Text = 1,
Html = 2,
CommentText = 3,
CommentHtml = 4,
}
public interface IConfigurationExceptionHandler
{
StackTraceModesJson StackTraceModeJson { get; }
StackTraceModesHtml StackTraceModeHtml { get; }
}
public class ConfigurationExceptionHandler : IConfigurationExceptionHandler
{
public StackTraceModesJson StackTraceModeJson { get; private set; }
public StackTraceModesHtml StackTraceModeHtml { get; private set; }
public ConfigurationExceptionHandler(Microsoft.Extensions.Configuration.IConfiguration configuration)
{
var helper = new ConfigurationHelper(configuration, "ExceptionHandler");
StackTraceModeJson = helper.GetAppSettingValue("StackTraceModeJson", required: false, defaultValue: StackTraceModesJson.None.ToString()).ParseToEnum<StackTraceModesJson>();
StackTraceModeHtml = helper.GetAppSettingValue("StackTraceModeHtml", required: false, defaultValue: StackTraceModesHtml.None.ToString()).ParseToEnum<StackTraceModesHtml>();
}
}
public static class ExceptionHandlerMiddlewareExt
{
public static IServiceCollection InitExceptionHandlerMiddleware(this IServiceCollection builder, IConfigurationExceptionHandler configuration)
{
ExceptionHandlerMiddleware.Init(configuration);
return builder;
}
}
public class ExceptionHandlerMiddleware
{
private static IConfigurationExceptionHandler? _exceptionHandler;
private static StackTraceModesJson _stackTraceModeJson => _exceptionHandler?.StackTraceModeJson ?? StackTraceModesJson.None;
private static StackTraceModesHtml _stackTraceModeHtml => _exceptionHandler?.StackTraceModeHtml ?? StackTraceModesHtml.None;
private readonly RequestDelegate _next;
public static void Init(IConfigurationExceptionHandler exceptionHandler)
{
_exceptionHandler = exceptionHandler;
}
public ExceptionHandlerMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
int statusCode = 0;
string errorMessage = string.Empty;
string errorStackTrace = string.Empty;
string? redirectUrl = null;
bool forceJson = false;
switch (ex)
{
case AuthenticationException exception:
statusCode = StatusCodes.Status401Unauthorized;
errorMessage = exception.Message;
redirectUrl = exception.RedirectUrl;
forceJson = true;
break;
case AuthorizationException exception:
statusCode = StatusCodes.Status403Forbidden;
errorMessage = exception.Message;
redirectUrl = exception.RedirectUrl;
forceJson = true;
break;
case InvalidOperationException exception:
statusCode = StatusCodes.Status409Conflict;
errorMessage = exception.Message;
break;
default:
statusCode = StatusCodes.Status500InternalServerError;
errorMessage = "На сервере произошла неизвестная ошибка" + Environment.NewLine + ex.Message;
break;
}
context.Response.StatusCode = statusCode;
if (forceJson || context.NeedResponseJsonResult(ex))
{
switch (_stackTraceModeJson)
{
case StackTraceModesJson.Text:
errorStackTrace = ex?.GetInfoAsPlainText() ?? string.Empty;
break;
case StackTraceModesJson.Html:
errorStackTrace = ex?.GetInfoAsHtml() ?? string.Empty;
break;
}
string json = new JsonResultError
{
ErrorMessage = errorMessage,
ErrorStackTrace = errorStackTrace,
RedirectUrl = redirectUrl
}.JsonSerialize(enableCyrillic: true, propertyNamingPolicy: System.Text.Json.JsonNamingPolicy.CamelCase);
context.Response.ContentType = "application/json; charset=utf-8";
await context.Response.WriteAsync(json, System.Text.Encoding.UTF8);
}
else
{
switch (_stackTraceModeHtml)
{
case StackTraceModesHtml.Text:
errorStackTrace = ex.GetInfoAsPlainText() ?? string.Empty;
break;
case StackTraceModesHtml.Html:
errorStackTrace = ex.GetInfoAsHtml() ?? string.Empty;
break;
case StackTraceModesHtml.CommentText:
errorStackTrace = "<!-- " + ex.GetInfoAsPlainText() ?? string.Empty + " -->";
break;
case StackTraceModesHtml.CommentHtml:
errorStackTrace = "<!-- " + ex.GetInfoAsHtml() ?? string.Empty + " -->";
break;
}
errorMessage += Environment.NewLine + errorStackTrace;
context.Response.ContentType = "text/html; charset=utf-8";
await context.Response.WriteAsync(errorMessage, System.Text.Encoding.UTF8);
}
}
}
}