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