committed by
GitHub
18 changed files with 365 additions and 35 deletions
@ -0,0 +1,40 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Wrapper |
||||
|
{ |
||||
|
public class AbpWrapperOptions |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 未处理异常代码
|
||||
|
/// 默认: 500
|
||||
|
/// </summary>
|
||||
|
public string CodeWithUnhandled { get; set; } |
||||
|
|
||||
|
internal IDictionary<Type, IExceptionWrapHandler> ExceptionHandles { get; } |
||||
|
|
||||
|
public AbpWrapperOptions() |
||||
|
{ |
||||
|
CodeWithUnhandled = "500"; |
||||
|
ExceptionHandles = new Dictionary<Type, IExceptionWrapHandler>(); |
||||
|
} |
||||
|
|
||||
|
public void AddHandler<TException>(IExceptionWrapHandler handler) |
||||
|
where TException : Exception |
||||
|
{ |
||||
|
AddHandler(typeof(TException), handler); |
||||
|
} |
||||
|
|
||||
|
public void AddHandler(Type exceptionType, IExceptionWrapHandler handler) |
||||
|
{ |
||||
|
ExceptionHandles[exceptionType] = handler; |
||||
|
} |
||||
|
|
||||
|
public IExceptionWrapHandler GetHandler(Type exceptionType) |
||||
|
{ |
||||
|
ExceptionHandles.TryGetValue(exceptionType, out IExceptionWrapHandler handler); |
||||
|
|
||||
|
return handler; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,36 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using System; |
||||
|
using Volo.Abp.ExceptionHandling; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Wrapper |
||||
|
{ |
||||
|
public class DefaultExceptionWrapHandler : IExceptionWrapHandler |
||||
|
{ |
||||
|
public void Wrap(ExceptionWrapContext context) |
||||
|
{ |
||||
|
if (context.Exception is IHasErrorCode exceptionWithErrorCode) |
||||
|
{ |
||||
|
string errorCode; |
||||
|
if (!exceptionWithErrorCode.Code.IsNullOrWhiteSpace() && |
||||
|
exceptionWithErrorCode.Code.Contains(":")) |
||||
|
{ |
||||
|
errorCode = exceptionWithErrorCode.Code.Split(':')[1]; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
errorCode = exceptionWithErrorCode.Code; |
||||
|
} |
||||
|
|
||||
|
context.WithCode(errorCode); |
||||
|
} |
||||
|
|
||||
|
// 没有处理的异常代码统一用配置代码处理
|
||||
|
if (context.ErrorInfo.Code.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
var wrapperOptions = context.ServiceProvider.GetRequiredService<IOptions<AbpWrapperOptions>>().Value; |
||||
|
context.WithCode(wrapperOptions.CodeWithUnhandled); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,45 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Http; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Wrapper |
||||
|
{ |
||||
|
public class ExceptionWrapContext |
||||
|
{ |
||||
|
public Exception Exception { get; } |
||||
|
public IServiceProvider ServiceProvider { get; } |
||||
|
public RemoteServiceErrorInfo ErrorInfo { get; } |
||||
|
public ExceptionWrapContext( |
||||
|
Exception exception, |
||||
|
RemoteServiceErrorInfo errorInfo, |
||||
|
IServiceProvider serviceProvider) |
||||
|
{ |
||||
|
Exception = exception; |
||||
|
ErrorInfo = errorInfo; |
||||
|
ServiceProvider = serviceProvider; |
||||
|
} |
||||
|
|
||||
|
public ExceptionWrapContext WithCode(string code) |
||||
|
{ |
||||
|
ErrorInfo.Code = code; |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
public ExceptionWrapContext WithMessage(string message) |
||||
|
{ |
||||
|
ErrorInfo.Message = message; |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
public ExceptionWrapContext WithDetails(string details) |
||||
|
{ |
||||
|
ErrorInfo.Details = details; |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
public ExceptionWrapContext WithData(string key, object value) |
||||
|
{ |
||||
|
ErrorInfo.Data[key] = value; |
||||
|
return this; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
using Microsoft.Extensions.Options; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Wrapper |
||||
|
{ |
||||
|
public class ExceptionWrapHandlerFactory : IExceptionWrapHandlerFactory, ITransientDependency |
||||
|
{ |
||||
|
private readonly AbpWrapperOptions _options; |
||||
|
|
||||
|
public ExceptionWrapHandlerFactory( |
||||
|
IOptions<AbpWrapperOptions> options) |
||||
|
{ |
||||
|
_options = options.Value; |
||||
|
} |
||||
|
|
||||
|
public IExceptionWrapHandler CreateFor(ExceptionWrapContext context) |
||||
|
{ |
||||
|
var exceptionType = context.Exception.GetType(); |
||||
|
var handler = _options.GetHandler(exceptionType); |
||||
|
if (handler == null) |
||||
|
{ |
||||
|
handler = new DefaultExceptionWrapHandler(); |
||||
|
_options.AddHandler(exceptionType, handler); |
||||
|
return handler; |
||||
|
} |
||||
|
|
||||
|
return handler; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
namespace LINGYUN.Abp.Wrapper |
||||
|
{ |
||||
|
public interface IExceptionWrapHandler |
||||
|
{ |
||||
|
void Wrap(ExceptionWrapContext context); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Wrapper |
||||
|
{ |
||||
|
public interface IExceptionWrapHandlerFactory |
||||
|
{ |
||||
|
IExceptionWrapHandler CreateFor(ExceptionWrapContext context); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AspNetCore.Mvc.Results |
||||
|
{ |
||||
|
public class ThrowMiddleware : IMiddleware, ITransientDependency |
||||
|
{ |
||||
|
public async Task InvokeAsync(HttpContext context, RequestDelegate next) |
||||
|
{ |
||||
|
if (context.Request.Path.ToString().StartsWith("/use-throw-middleware")) |
||||
|
{ |
||||
|
throw new BusinessException("Test:1001"); |
||||
|
} |
||||
|
await next(context); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net5.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
<IsPackable>false</IsPackable> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\modules\common\LINGYUN.Abp.Wrapper\LINGYUN.Abp.Wrapper.csproj" /> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.TestBase\LINGYUN.Abp.TestsBase.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,8 @@ |
|||||
|
using LINGYUN.Abp.Tests; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Wrapper |
||||
|
{ |
||||
|
public abstract class AbpWrapperTestsBase: AbpTestsBase<AbpWrapperTestsModule> |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
using LINGYUN.Abp.Tests; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Wrapper |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(AbpWrapperModule), |
||||
|
typeof(AbpTestsBaseModule))] |
||||
|
public class AbpWrapperTestsModule: AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpWrapperOptions>(options => |
||||
|
{ |
||||
|
options.AddHandler<FakeException>(new FakeExceptionWrapHandler()); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using Volo.Abp; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Wrapper |
||||
|
{ |
||||
|
public class FakeException: AbpException |
||||
|
{ |
||||
|
public FakeException() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public FakeException(string message) |
||||
|
: base(message) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
namespace LINGYUN.Abp.Wrapper |
||||
|
{ |
||||
|
public class FakeExceptionWrapHandler : IExceptionWrapHandler |
||||
|
{ |
||||
|
public void Wrap(ExceptionWrapContext context) |
||||
|
{ |
||||
|
context.WithCode("1001") |
||||
|
.WithMessage("自定义异常处理消息") |
||||
|
.WithDetails("自定义异常处理消息明细"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,75 @@ |
|||||
|
using Shouldly; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Http; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Wrapper.Tests |
||||
|
{ |
||||
|
public class FakeExceptionWrapHandler_Tests: AbpWrapperTestsBase |
||||
|
{ |
||||
|
private readonly IExceptionWrapHandlerFactory _exceptionWrapHandlerFactory; |
||||
|
|
||||
|
public FakeExceptionWrapHandler_Tests() |
||||
|
{ |
||||
|
_exceptionWrapHandlerFactory = GetRequiredService<IExceptionWrapHandlerFactory>(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_Return_Wraped_Result_With_Fake_Exception() |
||||
|
{ |
||||
|
var exception = new FakeException(); |
||||
|
var exceptionWrapContext = new ExceptionWrapContext( |
||||
|
exception, |
||||
|
new RemoteServiceErrorInfo(), |
||||
|
ServiceProvider); |
||||
|
|
||||
|
var handler = _exceptionWrapHandlerFactory.CreateFor(exceptionWrapContext); |
||||
|
handler.Wrap(exceptionWrapContext); |
||||
|
|
||||
|
exceptionWrapContext.ErrorInfo.Code.ShouldBe("1001"); |
||||
|
exceptionWrapContext.ErrorInfo.Message.ShouldBe("自定义异常处理消息"); |
||||
|
exceptionWrapContext.ErrorInfo.Details.ShouldBe("自定义异常处理消息明细"); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_Return_Wraped_Result_With_Default_Exception() |
||||
|
{ |
||||
|
var exception = new AbpException(); |
||||
|
var errorInfo = new RemoteServiceErrorInfo( |
||||
|
"默认异常处理消息", |
||||
|
"默认异常处理消息明细", |
||||
|
"1000"); |
||||
|
var exceptionWrapContext = new ExceptionWrapContext( |
||||
|
exception, |
||||
|
errorInfo, |
||||
|
ServiceProvider); |
||||
|
|
||||
|
var handler = _exceptionWrapHandlerFactory.CreateFor(exceptionWrapContext); |
||||
|
handler.Wrap(exceptionWrapContext); |
||||
|
|
||||
|
exceptionWrapContext.ErrorInfo.Code.ShouldBe("1000"); |
||||
|
exceptionWrapContext.ErrorInfo.Message.ShouldBe("默认异常处理消息"); |
||||
|
exceptionWrapContext.ErrorInfo.Details.ShouldBe("默认异常处理消息明细"); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_Return_Wraped_Result_Code_500_With_Unhandled_Exception() |
||||
|
{ |
||||
|
var exception = new AbpException(); |
||||
|
var errorInfo = new RemoteServiceErrorInfo( |
||||
|
"默认异常处理消息", |
||||
|
"默认异常处理消息明细"); |
||||
|
var exceptionWrapContext = new ExceptionWrapContext( |
||||
|
exception, |
||||
|
errorInfo, |
||||
|
ServiceProvider); |
||||
|
|
||||
|
var handler = _exceptionWrapHandlerFactory.CreateFor(exceptionWrapContext); |
||||
|
handler.Wrap(exceptionWrapContext); |
||||
|
|
||||
|
exceptionWrapContext.ErrorInfo.Code.ShouldBe("500"); |
||||
|
exceptionWrapContext.ErrorInfo.Message.ShouldBe("默认异常处理消息"); |
||||
|
exceptionWrapContext.ErrorInfo.Details.ShouldBe("默认异常处理消息明细"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue