diff --git a/aspnet-core/frameworks/src/Lion.AbpPro.Core/Lion/AbpPro/Core/WrapResult.cs b/aspnet-core/frameworks/src/Lion.AbpPro.Core/Lion/AbpPro/Core/WrapResult.cs index 292522bc..78520651 100644 --- a/aspnet-core/frameworks/src/Lion.AbpPro.Core/Lion/AbpPro/Core/WrapResult.cs +++ b/aspnet-core/frameworks/src/Lion.AbpPro.Core/Lion/AbpPro/Core/WrapResult.cs @@ -8,24 +8,24 @@ public class WrapResult public T Data { get; private set; } - public int Code { get; private set; } + public string Code { get; private set; } public WrapResult() { Success = true; Message = "Success"; Data = default; - Code = 200; + Code = "200"; } - public void SetSuccess(T data, string message = "Success", int code = 200) + public void SetSuccess(T data, string message = "Success", string code = "200") { Success = true; Data = data; Code = code; } - public void SetFail(string message = "Fail", int code = 500) + public void SetFail(string message = "Fail", string code = "500") { Success = false; Message = message; diff --git a/aspnet-core/frameworks/src/Lion.AbpPro.Localization/GlobalUsings.cs b/aspnet-core/frameworks/src/Lion.AbpPro.Localization/GlobalUsings.cs index 0558e9d8..f0f57690 100644 --- a/aspnet-core/frameworks/src/Lion.AbpPro.Localization/GlobalUsings.cs +++ b/aspnet-core/frameworks/src/Lion.AbpPro.Localization/GlobalUsings.cs @@ -1,7 +1,11 @@ // Global using directives global using Lion.AbpPro.Localization; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Localization; global using Volo.Abp.Autofac; +global using Volo.Abp.DependencyInjection; +global using Volo.Abp.ExceptionHandling; global using Volo.Abp.Localization; global using Volo.Abp.Localization.ExceptionHandling; global using Volo.Abp.Modularity; diff --git a/aspnet-core/frameworks/src/Lion.AbpPro.Localization/Lion/AbpPro/AbpProExceptionConverter.cs b/aspnet-core/frameworks/src/Lion.AbpPro.Localization/Lion/AbpPro/AbpProExceptionConverter.cs new file mode 100644 index 00000000..079d1d14 --- /dev/null +++ b/aspnet-core/frameworks/src/Lion.AbpPro.Localization/Lion/AbpPro/AbpProExceptionConverter.cs @@ -0,0 +1,58 @@ +using Microsoft.Extensions.Options; + +namespace Lion.AbpPro; + +public class AbpProExceptionConverter : IAbpProExceptionConverter, ITransientDependency +{ + private readonly AbpExceptionLocalizationOptions _options; + private readonly IStringLocalizerFactory _localizerFactory; + + public AbpProExceptionConverter( + IOptions options, + IStringLocalizerFactory localizerFactory) + { + _options = options.Value; + _localizerFactory = localizerFactory; + } + + public virtual string TryToLocalizeExceptionMessage(Exception exception) + { + if (!(exception is IHasErrorCode exceptionWithErrorCode)) + { + return exception.Message; + } + + if (exceptionWithErrorCode.Code.IsNullOrWhiteSpace() || + !exceptionWithErrorCode.Code.Contains(":")) + { + return exception.Message; + } + + var codeNamespace = exceptionWithErrorCode.Code.Split(':')[0]; + + var localizationResourceType = _options.ErrorCodeNamespaceMappings.GetOrDefault(codeNamespace); + if (localizationResourceType == null) + { + return exception.Message; + } + + var stringLocalizer = _localizerFactory.Create(localizationResourceType); + var localizedString = stringLocalizer[exceptionWithErrorCode.Code]; + if (localizedString.ResourceNotFound) + { + return exception.Message; + } + + var localizedValue = localizedString.Value; + + if (exception.Data != null && exception.Data.Count > 0) + { + foreach (var key in exception.Data.Keys) + { + localizedValue = localizedValue.Replace("{" + key + "}", exception.Data[key]?.ToString()); + } + } + + return localizedValue; + } +} \ No newline at end of file diff --git a/aspnet-core/frameworks/src/Lion.AbpPro.Localization/Lion/AbpPro/IAbpProExceptionConverter.cs b/aspnet-core/frameworks/src/Lion.AbpPro.Localization/Lion/AbpPro/IAbpProExceptionConverter.cs new file mode 100644 index 00000000..e2ab90a6 --- /dev/null +++ b/aspnet-core/frameworks/src/Lion.AbpPro.Localization/Lion/AbpPro/IAbpProExceptionConverter.cs @@ -0,0 +1,6 @@ +namespace Lion.AbpPro; + +public interface IAbpProExceptionConverter +{ + string TryToLocalizeExceptionMessage(Exception exception); +} \ No newline at end of file diff --git a/aspnet-core/frameworks/src/Lion.AbpPro.Localization/Lion/AbpPro/Localization/Resources/en.json b/aspnet-core/frameworks/src/Lion.AbpPro.Localization/Lion/AbpPro/Localization/Resources/en.json index 423998c3..8b709131 100644 --- a/aspnet-core/frameworks/src/Lion.AbpPro.Localization/Lion/AbpPro/Localization/Resources/en.json +++ b/aspnet-core/frameworks/src/Lion.AbpPro.Localization/Lion/AbpPro/Localization/Resources/en.json @@ -5,6 +5,11 @@ "Permission:Cap": "CAP Dashboard", "Lion.AbpPro:100001": "The start page must be greater than or equal to 1", "Lion.AbpPro:100002": "The maximum number of records per page cannot exceed 100,000", - "Lion.AbpPro:100003": "{0} can not be empty" + "Lion.AbpPro:100003": "{0} can not be empty", + "Lion.AbpPro:PermissionDenied": "Permission Denied", + "Lion.AbpPro:ParameterValidationFailed": "Parameter Validation Failed", + "Lion.AbpPro:EntityNotFound": "Entity Not Found", + "Lion.AbpPro:Unimplemented ": "Unimplemented", + "Lion.AbpPro:DbUpdateConcurrency ": "The data has been modified, please resubmit" } } diff --git a/aspnet-core/frameworks/src/Lion.AbpPro.Localization/Lion/AbpPro/Localization/Resources/zh-Hans.json b/aspnet-core/frameworks/src/Lion.AbpPro.Localization/Lion/AbpPro/Localization/Resources/zh-Hans.json index 00607761..2906b806 100644 --- a/aspnet-core/frameworks/src/Lion.AbpPro.Localization/Lion/AbpPro/Localization/Resources/zh-Hans.json +++ b/aspnet-core/frameworks/src/Lion.AbpPro.Localization/Lion/AbpPro/Localization/Resources/zh-Hans.json @@ -5,6 +5,11 @@ "Permission:Cap": "CAP面板", "Lion.AbpPro:100001": "起始页必须大于等于1", "Lion.AbpPro:100002": "每页最大记录数不能超过100000", - "Lion.AbpPro:100003": "{0}不能为空" + "Lion.AbpPro:100003": "{0}不能为空", + "Lion.AbpPro:PermissionDenied": "权限不足", + "Lion.AbpPro:ParameterValidationFailed": "请求参数验证失败", + "Lion.AbpPro:EntityNotFound": "实体不存在", + "Lion.AbpPro:Unimplemented ": "未实现功能", + "Lion.AbpPro:DbUpdateConcurrency ": "数据已被修改,请重新提交." } } \ No newline at end of file diff --git a/aspnet-core/shared/Lion.AbpPro.Shared.Hosting.Microservices/Microsoft/AspNetCore/Mvc/Filters/AbpProExceptionFilter.cs b/aspnet-core/shared/Lion.AbpPro.Shared.Hosting.Microservices/Microsoft/AspNetCore/Mvc/Filters/AbpProExceptionFilter.cs index 6e5a4818..bcbff1ff 100644 --- a/aspnet-core/shared/Lion.AbpPro.Shared.Hosting.Microservices/Microsoft/AspNetCore/Mvc/Filters/AbpProExceptionFilter.cs +++ b/aspnet-core/shared/Lion.AbpPro.Shared.Hosting.Microservices/Microsoft/AspNetCore/Mvc/Filters/AbpProExceptionFilter.cs @@ -1,4 +1,9 @@ using System.Text; +using Lion.AbpPro; +using Lion.AbpPro.Localization; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; +using Volo.Abp.Localization.ExceptionHandling; namespace Microsoft.AspNetCore.Mvc.Filters; @@ -61,23 +66,46 @@ public sealed class AbpProExceptionFilter : IAsyncExceptionFilter, ITransientDep private WrapResult SimplifyMessage(ExceptionContext context) { var result = new WrapResult(); + var localizer = context.GetRequiredService>(); switch (context.Exception) { case AbpAuthorizationException: - result.SetFail("权限不足", 401); + result.SetFail(localizer["Lion.AbpPro:PermissionDenied"], "401"); break; - case AbpValidationException: - result.SetFail("请求参数验证失败", 400); + case AbpValidationException validationException: + var errorMessage = localizer["Lion.AbpPro:ParameterValidationFailed"] + ";" + validationException.ValidationErrors.JoinAsString(";"); + result.SetFail(errorMessage, "400"); break; case EntityNotFoundException: - result.SetFail("实体不存在", 506); + result.SetFail(localizer["Lion.AbpPro:EntityNotFound"], "506"); break; case NotImplementedException: - result.SetFail("未实现功能", 507); + result.SetFail(localizer["Lion.AbpPro:Unimplemented"], "507"); + break; + case DbUpdateConcurrencyException: + result.SetFail(localizer["Lion.AbpPro:DbUpdateConcurrency"], "508"); break; default: { - result.SetFail(context.Exception.Message); + if (context.Exception is IHasErrorCode codeException) + { + var exceptionConverter = context.GetRequiredService(); + var message = exceptionConverter.TryToLocalizeExceptionMessage(context.Exception); + if (codeException.Code.IsNullOrWhiteSpace()) + { + // TODO 没有code,不应该出现这个情况。 + result.SetFail(context.Exception.Message); + } + else + { + result.SetFail(message, codeException.Code); + } + } + else + { + result.SetFail(context.Exception.Message); + } + break; } }