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

C# 在运行作业的应用程序中使用中间件的最佳方法,c#,.net,.net-core,invoke,asp.net-core-middleware,C#,.net,.net Core,Invoke,Asp.net Core Middleware,我有一个从外部API调用端点的服务。我开发了一个自定义中间件,用于处理来自这些API调用的可能异常并记录它们。但是,尽管中间件在调用方法中包含try-and-catch块,但是在catch块捕获异常后,我的应用程序的流被中断。虽然应用程序一直在运行,但流只是结束了。由于此应用程序正在执行同步数据的作业,因此我需要继续流(如我所述,记录可能的异常) 有人已经经历过这种情况,或者有任何线索可以让流程继续下去吗?有没有更好的方法?请允许我提出建议 这是我的代码: public class ApiExc

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

有人已经经历过这种情况,或者有任何线索可以让流程继续下去吗?有没有更好的方法?请允许我提出建议

这是我的代码:

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类错误
{
公共静态字符串DefaultErrorMessage=“Erro no processamento da requisiço.”;
公共字符串Id{get;}=Guid.NewGuid().ToString();
公共HttpStatusCode状态{get;set;}=HttpStatusCode.InternalServerError;
公共字符串标题{get;set;}=“API错误”;
公共字符串消息{get;set;}=DefaultErrorMessage;
公共IDictionary详细信息{get;set;}=new Dictionary();
}
公共静态类ApiExceptionExtensions
{        
公共静态IAApplicationBuilder UseApiExceptionHandler(此IAApplicationBuilder生成器)
{
var options=新的ApiExceptionOptions();
返回builder.useMediddleware(选项);
}
公共静态IAApplicationBuilder UseApiExceptionHandler(此IAApplicationBuilder,
操作(配置选项)
{
var options=新的ApiExceptionOptions();
配置选项(选项);
返回builder.useMediddleware(选项);
}
}

您所说的“此应用程序正在执行同步数据的作业”到底是什么意思?您是否正在使用
任务。运行
或类似操作?因为我没有使用Task.Run,我的作业方法是异步Task好的,我再次阅读了你的问题,我想我误解了。我还不清楚你在问什么。你能详细说明一下“我需要流程继续”吗?你的意思是当你
返回context.Response.WriteAsync(result)时在CreateResponse中,它将被中断。通常在启动时使用,并且通常有
等待下一步
使用其他中间件。
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);
        }
    }