运行作业的应用程序中中间件的最佳方法

问题描述

我有一个从外部API调用端点的服务。我开发了一个自定义的中间件,用于处理这些API调用中可能出现的异常并将它们记录下来。但是,尽管中间件在 Invoke方法中包含try and catch块,但是在catch块捕获了Exception之后,我的应用程序的流程被中断了。尽管应用程序继续运行,但是流程只是结束了。当此应用程序正在执行同步数据的作业时,我需要流程继续进行(并记录可能的异常,如上所述)。

任何人都已经经历过或有任何线索如何使流程继续进行?有更好的方法吗?我完全愿意征求意见。

这是我的代码:

public class ApiException
    {
        private readonly RequestDelegate _next;
        private readonly ILogger<ApiException> _logger;
        private readonly ApiExceptionOptions _options;

        public ApiException(ApiExceptionOptions options,RequestDelegate next,ILogger<ApiException> logger)
        {
            _next = next;
            _logger = logger;
            _options = options;
        }

        public async Task Invoke(HttpContext context /* other dependencies */)
        {
            try
            {
                await _next(context);
            }
            catch (Exception ex)
            {
                await HandleExceptionAsync(context,ex);
            }
        }

        private Task HandleExceptionAsync(HttpContext context,Exception exception)
        {
            ApiError error = _options.AddResponseDetails?.Invoke(exception)
                ?? ApiErrorFactory.New(exception);

            LogApiException(exception,error);

            return CreateResponse(context,error);
        }

        private static Task CreateResponse(HttpContext context,ApiError error)
        {
            var result = JsonSerializer.Serialize(error,new JsonSerializerOptions
                {
                    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,});
            context.Response.ContentType = "application/json";
            context.Response.StatusCode = (int)error.Status;
            return context.Response.WriteAsync(result);
        }

        private void LogApiException(Exception exception,ApiError error)
        {
            var innerExMessage = GetInnermostExceptionMessage(exception);
            var level = _options.DetermineLogLevel?.Invoke(exception) ?? GetLogLevel(exception);
            _logger.Log(level,exception,"ERROR: {message} -- {ErrorId}.",innerExMessage,error.Id);
        }

        private static LogLevel GetLogLevel(Exception exception) =>
            exception switch
            {
                InvalidInputException _ => LogLevel.Warning,_ => LogLevel.Error
            };

        private string GetInnermostExceptionMessage(Exception exception)
        {
            if (exception.InnerException != null)
                return GetInnermostExceptionMessage(exception.InnerException);

            return exception.Message;
        }
    }

public class ApiExceptionOptions
    {        
        public Func<Exception,ApiError> AddResponseDetails { get; set; }
        
        public Func<Exception,LogLevel> DetermineLogLevel { get; set; }
    }
public static class ApiErrorFactory
    {        
        public static ApiError New(Exception exception) =>
            exception switch
            {
                InvalidInputException e => new ApiError
                {
                    Details = e.Details,Message = e.Message,Status = BadRequest
                },_ => new ApiError()
            };
    }
public class ApiError
    {
        public static string DefaultErrorMessage = "Erro no processamento da requisição.";

        public string Id { get; } = Guid.NewGuid().ToString();
        public HttpStatusCode Status { get; set; } = HttpStatusCode.InternalServerError;
        public string Title { get; set; } = "API Error";
        public string Message { get; set; } = DefaultErrorMessage;
        public IDictionary<string,object> Details { get; set; } = new Dictionary<string,object>();
    }
public static class ApiExceptionExtensions
    {        
        public static IApplicationBuilder UseApiExceptionHandler(this IApplicationBuilder builder)
        {
            var options = new ApiExceptionOptions();
            return builder.UseMiddleware<ApiException>(options);
        }
        
        public static IApplicationBuilder UseApiExceptionHandler(this IApplicationBuilder builder,Action<ApiExceptionOptions> configureOptions)
        {
            var options = new ApiExceptionOptions();
            configureOptions(options);

            return builder.UseMiddleware<ApiException>(options);
        }
    }

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...