diff --git a/IRaCIS.Core.API/Progranm.cs b/IRaCIS.Core.API/Progranm.cs index 5c555bd6e..daddbfb55 100644 --- a/IRaCIS.Core.API/Progranm.cs +++ b/IRaCIS.Core.API/Progranm.cs @@ -79,8 +79,8 @@ var _configuration = builder.Configuration; //手动注册服务 builder.Services.ConfigureServices(_configuration); -//异常处理 -//builder.Services.AddExceptionHandler(); +//minimal api 异常处理 +builder.Services.AddExceptionHandler(); //builder.Services.AddProblemDetails(); //健康检查 @@ -148,7 +148,9 @@ builder.Services.AddMasaMinimalAPIs(options => options.DeletePrefixes = new List { "Delete", "Remove" }; options.RouteHandlerBuilder= t=> { - t.RequireAuthorization().AddEndpointFilter().WithGroupName("Institution"); + t.RequireAuthorization() + .AddEndpointFilter() + .WithGroupName("Institution"); }; options.DisableTrimMethodPrefix = true; //禁用去除方法前缀 options.DisableAutoMapRoute = false;//可通过配置true禁用全局自动路由映射或者删除此配置以启用全局自动路由映射 @@ -186,7 +188,8 @@ app.UseStatusCodePages(async context => }); -//app.UseExceptionHandler(o => { }); +//app.UseExceptionHandler(); +app.UseExceptionHandler(o => { }); //这里没生效,原因未知,官方文档也是这种写法,也用了GlobalExceptionHandler 尝试,还是不行,怀疑框架bug //app.UseExceptionHandler(configure => diff --git a/IRaCIS.Core.Application/BusinessFilter/GlobalExceptionHandler.cs b/IRaCIS.Core.Application/BusinessFilter/GlobalExceptionHandler.cs deleted file mode 100644 index 70688e7e2..000000000 --- a/IRaCIS.Core.Application/BusinessFilter/GlobalExceptionHandler.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Microsoft.AspNetCore.Diagnostics; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Logging; - - -namespace IRaCIS.Core.Application.BusinessFilter; - - -/// -/// 不生效,不知道为啥 -/// -public class GlobalExceptionHandler : IExceptionHandler -{ - private readonly ILogger _logger; - public GlobalExceptionHandler(ILogger logger) - { - this._logger = logger; - } - public ValueTask TryHandleAsync( - HttpContext httpContext, - Exception exception, - CancellationToken cancellationToken) - { - - - httpContext.Response.ContentType = "application/json"; - - - var ex = exception; - var errorInfo = $"Exception: {ex.Message}[{ex.StackTrace}]" + (ex.InnerException != null ? $" InnerException: {ex.InnerException.Message}[{ex.InnerException.StackTrace}]" : ""); - - httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk($"{ex?.Message}")); - - - - - - _logger.LogError(errorInfo); - - // return true to signal that this exception is handled - return ValueTask.FromResult(false); - } -} diff --git a/IRaCIS.Core.Application/BusinessFilter/LegacyController/ProjectExceptionFilter.cs b/IRaCIS.Core.Application/BusinessFilter/LegacyController/ProjectExceptionFilter.cs new file mode 100644 index 000000000..997aae9c8 --- /dev/null +++ b/IRaCIS.Core.Application/BusinessFilter/LegacyController/ProjectExceptionFilter.cs @@ -0,0 +1,66 @@ +using IRaCIS.Core.Domain.Share; +using IRaCIS.Core.Infrastructure; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; + +namespace IRaCIS.Core.Application.Filter; + +public class ProjectExceptionFilter(ILogger _logger, IStringLocalizer _localizer) : Attribute, IExceptionFilter +{ + + public void OnException(ExceptionContext context) + { + //context.ExceptionHandled;//记录当前这个异常是否已经被处理过了 + + var exception = context.Exception; + + if (!context.ExceptionHandled) + { + if (exception.GetType().Name == "DbUpdateConcurrencyException") + { + //---并发更新,当前不允许该操作 + context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + exception.Message)); + } + + if (exception.GetType() == typeof(BusinessValidationFailedException)) + { + var error = exception as BusinessValidationFailedException; + + var info = string.Empty; + + if (!string.IsNullOrWhiteSpace(error!.LocalizedKey) && StaticData.Log_Locoalize_Dic.ContainsKey(error!.LocalizedKey)) + { + info = $"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}"; + } + + + context.Result = new JsonResult(ResponseOutput.NotOk(exception.Message, "", error!.Code, localizedInfo: info)); + + } + else if (exception.GetType() == typeof(QueryBusinessObjectNotExistException)) + { + context.Result = new JsonResult(ResponseOutput.NotOk(exception.Message, ApiResponseCodeEnum.DataNotExist)); + } + else + { + context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (exception.InnerException is null ? (exception.Message) + : (exception.InnerException?.Message )), ApiResponseCodeEnum.ProgramException)); + + } + + context.ExceptionHandled = true;//标记当前异常已经被处理过了 + + + var errorInfo = $"Exception: {exception.Message}[{exception.StackTrace}]" + (exception.InnerException != null ? $" InnerException: {exception.InnerException.Message}[{exception.InnerException.StackTrace}]" : ""); + + _logger.LogError(errorInfo); + + } + else + { + //继续 + } + } +} diff --git a/IRaCIS.Core.Application/BusinessFilter/MinimalAPI/GlobalExceptionHandler.cs b/IRaCIS.Core.Application/BusinessFilter/MinimalAPI/GlobalExceptionHandler.cs new file mode 100644 index 000000000..688c2cd24 --- /dev/null +++ b/IRaCIS.Core.Application/BusinessFilter/MinimalAPI/GlobalExceptionHandler.cs @@ -0,0 +1,73 @@ +using DocumentFormat.OpenXml.InkML; +using IRaCIS.Core.Infrastructure; +using Microsoft.AspNetCore.Diagnostics; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; + + +namespace IRaCIS.Core.Application.BusinessFilter; + + +/// +/// minimal api 生效,但是传统控制器,没生效 +/// 参考处理链接: https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/error-handling?view=aspnetcore-8.0 +/// +public class GlobalExceptionHandler(IStringLocalizer _localizer, ILogger _logger) : IExceptionHandler +{ + + public ValueTask TryHandleAsync( + HttpContext httpContext, + Exception exception, + CancellationToken cancellationToken) + { + + httpContext.Response.StatusCode =StatusCodes.Status200OK; + + httpContext.Response.ContentType = "application/json"; + + if (exception.GetType().Name == "DbUpdateConcurrencyException") + { + //---并发更新,当前不允许该操作 + + httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + exception.Message)); + } + + if (exception.GetType() == typeof(BusinessValidationFailedException)) + { + var error = exception as BusinessValidationFailedException; + + var info = string.Empty; + + if (!string.IsNullOrWhiteSpace(error!.LocalizedKey) && StaticData.Log_Locoalize_Dic.ContainsKey(error!.LocalizedKey)) + { + info = $"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}"; + } + + httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk(exception.Message, "", error!.Code, localizedInfo: info)); + + + + //warning 级别记录 + //_logger.LogWarning($"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}"); + } + else if (exception.GetType() == typeof(QueryBusinessObjectNotExistException)) + { + httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk(exception.Message, ApiResponseCodeEnum.DataNotExist)); + } + else + { + httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (exception.InnerException is null ? (exception.Message ) + : (exception.InnerException?.Message)), ApiResponseCodeEnum.ProgramException)); + + } + + var errorInfo = $"Exception: {exception.Message}[{exception.StackTrace}]" + (exception.InnerException != null ? $" InnerException: {exception.InnerException.Message}[{exception.InnerException.StackTrace}]" : ""); + + _logger.LogError(errorInfo); + + // Return false to continue with the default behavior + // - or - return true to signal that this exception is handled + return ValueTask.FromResult(false); + } +} diff --git a/IRaCIS.Core.Application/BusinessFilter/ProjectExceptionFilter.cs b/IRaCIS.Core.Application/BusinessFilter/ProjectExceptionFilter.cs deleted file mode 100644 index 1825c3728..000000000 --- a/IRaCIS.Core.Application/BusinessFilter/ProjectExceptionFilter.cs +++ /dev/null @@ -1,75 +0,0 @@ -using IRaCIS.Core.Domain.Share; -using IRaCIS.Core.Infrastructure; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.Extensions.Localization; -using Microsoft.Extensions.Logging; - -namespace IRaCIS.Core.Application.Filter; - -public class ProjectExceptionFilter : Attribute, IExceptionFilter -{ - private readonly ILogger _logger; - - public IStringLocalizer _localizer; - - public ProjectExceptionFilter(IStringLocalizer localizer, ILogger logger) - { - _logger = logger; - _localizer = localizer; - } - public void OnException(ExceptionContext context) - { - //context.ExceptionHandled;//记录当前这个异常是否已经被处理过了 - - if (!context.ExceptionHandled) - { - if (context.Exception.GetType().Name == "DbUpdateConcurrencyException") - { - //---并发更新,当前不允许该操作 - context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + context.Exception.Message)); - } - - if (context.Exception.GetType() == typeof(BusinessValidationFailedException)) - { - var error = context.Exception as BusinessValidationFailedException; - - var info = string.Empty; - - if (!string.IsNullOrWhiteSpace(error!.LocalizedKey) && StaticData.Log_Locoalize_Dic.ContainsKey(error!.LocalizedKey)) - { - info = $"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}"; - } - - - context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, "", error!.Code, localizedInfo: info)); - - - //warning 级别记录 - //_logger.LogWarning($"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}"); - } - else if (context.Exception.GetType() == typeof(QueryBusinessObjectNotExistException)) - { - context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, ApiResponseCodeEnum.DataNotExist)); - } - else - { - context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (context.Exception.InnerException is null ? (context.Exception.Message /*+ context.Exception.StackTrace*/) - : (context.Exception.InnerException?.Message /*+ context.Exception.InnerException?.StackTrace*/)), ApiResponseCodeEnum.ProgramException)); - - _logger.LogError(context.Exception.InnerException is null ? (context.Exception.Message + context.Exception.StackTrace) : (context.Exception.InnerException?.Message + context.Exception.InnerException?.StackTrace)); - - } - - context.ExceptionHandled = true;//标记当前异常已经被处理过了 - - - //throw new Exception("test-result-exceptioin"); - - } - else - { - //继续 - } - } -} diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index 9924157c4..7900d19a5 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -12717,7 +12717,14 @@ - 不生效,不知道为啥 + minimal api 生效,但是传统控制器,没生效 + 参考处理链接: https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/error-handling?view=aspnetcore-8.0 + + + + + minimal api 生效,但是传统控制器,没生效 + 参考处理链接: https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/error-handling?view=aspnetcore-8.0 diff --git a/IRaCIS.Core.Application/TestService.cs b/IRaCIS.Core.Application/TestService.cs index 0ed9d9fb7..727dfb5b5 100644 --- a/IRaCIS.Core.Application/TestService.cs +++ b/IRaCIS.Core.Application/TestService.cs @@ -58,6 +58,8 @@ namespace IRaCIS.Core.Application.Service public IResponseOutput GetTest() { + throw new BusinessValidationFailedException("手动抛出的异常"); + return ResponseOutput.Ok(_userInfo.IP); } } @@ -167,6 +169,8 @@ namespace IRaCIS.Core.Application.Service public async Task TestJson() { + throw new BusinessValidationFailedException("传统控制器异常"); + var model1 = new TestModel() { TestId = NewId.NextSequentialGuid(), TestName = null }; var model2 = new TestModel2() { TestId = NewId.NextSequentialGuid(), TestName = "test2" };