committed by
GitHub
12 changed files with 484 additions and 20 deletions
@ -0,0 +1,153 @@ |
|||
using LINGYUN.Abp.Wrapper; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.AspNetCore.Mvc.Abstractions; |
|||
using Microsoft.AspNetCore.Mvc.ApiExplorer; |
|||
using Microsoft.AspNetCore.Mvc.Controllers; |
|||
using Microsoft.AspNetCore.Mvc.Formatters; |
|||
using Microsoft.AspNetCore.Mvc.ModelBinding; |
|||
using Microsoft.Extensions.Options; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc.ApiExploring; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Reflection; |
|||
using Volo.Abp.Threading; |
|||
|
|||
namespace LINGYUN.Abp.AspNetCore.Mvc.Wrapper.ApiExploring; |
|||
public class AbpWrapResultApiDescriptionProvider : IApiDescriptionProvider, ITransientDependency |
|||
{ |
|||
private readonly MvcOptions _mvcOptions; |
|||
private readonly AbpWrapperOptions _wrapperOptions; |
|||
private readonly AbpRemoteServiceApiDescriptionProviderOptions _providerOptions; |
|||
private readonly IWrapResultChecker _wrapResultChecker; |
|||
private readonly IModelMetadataProvider _modelMetadataProvider; |
|||
|
|||
public AbpWrapResultApiDescriptionProvider( |
|||
IOptions<MvcOptions> mvcOptions, |
|||
IOptions<AbpWrapperOptions> wrapperOptions, |
|||
IOptions<AbpRemoteServiceApiDescriptionProviderOptions> providerOptions, |
|||
IWrapResultChecker wrapResultChecker, |
|||
IModelMetadataProvider modelMetadataProvider) |
|||
{ |
|||
_mvcOptions = mvcOptions.Value; |
|||
_wrapperOptions = wrapperOptions.Value; |
|||
_providerOptions = providerOptions.Value; |
|||
_wrapResultChecker = wrapResultChecker; |
|||
_modelMetadataProvider = modelMetadataProvider; |
|||
} |
|||
|
|||
public int Order => -999; |
|||
|
|||
public virtual void OnProvidersExecuted(ApiDescriptionProviderContext context) |
|||
{ |
|||
} |
|||
|
|||
public virtual void OnProvidersExecuting(ApiDescriptionProviderContext context) |
|||
{ |
|||
WrapperOKResponse(context); |
|||
} |
|||
|
|||
protected virtual void WrapperOKResponse(ApiDescriptionProviderContext context) |
|||
{ |
|||
foreach (var result in context.Results.Where(x => x.IsRemoteService())) |
|||
{ |
|||
var actionProducesResponseTypeAttributes = |
|||
ReflectionHelper.GetAttributesOfMemberOrDeclaringType<ProducesResponseTypeAttribute>( |
|||
result.ActionDescriptor.GetMethodInfo()); |
|||
if (actionProducesResponseTypeAttributes.Any(x => x.StatusCode == (int)_wrapperOptions.HttpStatusCode)) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
if (_wrapResultChecker.WrapOnAction(result.ActionDescriptor) && |
|||
result.ActionDescriptor is ControllerActionDescriptor actionDescriptor) |
|||
{ |
|||
var returnType = AsyncHelper.UnwrapTask(actionDescriptor.MethodInfo.ReturnType); |
|||
|
|||
Type wrapResultType = null; |
|||
if (returnType == null || returnType == typeof(void)) |
|||
{ |
|||
wrapResultType = typeof(WrapResult); |
|||
} |
|||
else |
|||
{ |
|||
wrapResultType = typeof(WrapResult<>).MakeGenericType(returnType); |
|||
} |
|||
|
|||
var responseType = new ApiResponseType |
|||
{ |
|||
Type = wrapResultType, |
|||
StatusCode = (int)_wrapperOptions.HttpStatusCode, |
|||
ModelMetadata = _modelMetadataProvider.GetMetadataForType(wrapResultType) |
|||
}; |
|||
|
|||
foreach (var responseTypeMetadataProvider in _mvcOptions.OutputFormatters.OfType<IApiResponseTypeMetadataProvider>()) |
|||
{ |
|||
var formatterSupportedContentTypes = responseTypeMetadataProvider.GetSupportedContentTypes(null, wrapResultType); |
|||
if (formatterSupportedContentTypes == null) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
foreach (var formatterSupportedContentType in formatterSupportedContentTypes) |
|||
{ |
|||
responseType.ApiResponseFormats.Add(new ApiResponseFormat |
|||
{ |
|||
Formatter = (IOutputFormatter)responseTypeMetadataProvider, |
|||
MediaType = formatterSupportedContentType |
|||
}); |
|||
} |
|||
} |
|||
// TODO: 是否有必要对其他响应代码定义包装结果?
|
|||
// 例外1: 当用户传递 _AbpDontWrapResult 请求头时, 响应结果与预期不一致
|
|||
// 例外2: 当控制器Url在被忽略Url中, 响应结果与预期不一致
|
|||
// 例外3: 当引发异常在被忽略异常中, 响应结果为 RemoteServiceErrorResponse 对象, 与预期不一致
|
|||
|
|||
result.SupportedResponseTypes.RemoveAll(x => x.StatusCode == responseType.StatusCode); |
|||
result.SupportedResponseTypes.AddIfNotContains( |
|||
x => x.StatusCode == responseType.StatusCode, |
|||
() => responseType); |
|||
WrapperErrorResponse(result); |
|||
} |
|||
} |
|||
} |
|||
|
|||
protected virtual void WrapperErrorResponse(ApiDescription description) |
|||
{ |
|||
foreach (var apiResponse in _providerOptions.SupportedResponseTypes) |
|||
{ |
|||
var wrapResultType = typeof(WrapResult); |
|||
var responseType = new ApiResponseType |
|||
{ |
|||
Type = wrapResultType, |
|||
StatusCode = apiResponse.StatusCode, |
|||
ModelMetadata = _modelMetadataProvider.GetMetadataForType(wrapResultType) |
|||
}; |
|||
|
|||
foreach (var responseTypeMetadataProvider in _mvcOptions.OutputFormatters.OfType<IApiResponseTypeMetadataProvider>()) |
|||
{ |
|||
var formatterSupportedContentTypes = responseTypeMetadataProvider.GetSupportedContentTypes(null, responseType.Type); |
|||
if (formatterSupportedContentTypes == null) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
foreach (var formatterSupportedContentType in formatterSupportedContentTypes) |
|||
{ |
|||
responseType.ApiResponseFormats.Add(new ApiResponseFormat |
|||
{ |
|||
Formatter = (IOutputFormatter)responseTypeMetadataProvider, |
|||
MediaType = formatterSupportedContentType |
|||
}); |
|||
} |
|||
} |
|||
|
|||
description.SupportedResponseTypes.RemoveAll(x => x.StatusCode == responseType.StatusCode); |
|||
description.SupportedResponseTypes.AddIfNotContains( |
|||
x => x.StatusCode == responseType.StatusCode, |
|||
() => responseType); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using Volo.Abp.Collections; |
|||
|
|||
namespace LINGYUN.Abp.SettingManagement; |
|||
public class SettingManagementMergeOptions |
|||
{ |
|||
public ITypeList<IUserSettingAppService> UserSettingProviders { get; } |
|||
public ITypeList<IReadonlySettingAppService> GlobalSettingProviders { get; } |
|||
public SettingManagementMergeOptions() |
|||
{ |
|||
UserSettingProviders = new TypeList<IUserSettingAppService>(); |
|||
GlobalSettingProviders = new TypeList<IReadonlySettingAppService>(); |
|||
} |
|||
} |
|||
@ -0,0 +1,70 @@ |
|||
using LINGYUN.Abp.SettingManagement; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace LY.MicroService.Applications.Single.Controllers; |
|||
|
|||
[ExposeServices( |
|||
typeof(SettingController), |
|||
typeof(SettingMergeController))] |
|||
public class SettingMergeController : SettingController |
|||
{ |
|||
private readonly SettingManagementMergeOptions _mergeOptions; |
|||
public SettingMergeController( |
|||
ISettingAppService settingAppService, |
|||
ISettingTestAppService settingTestAppService, |
|||
IOptions<SettingManagementMergeOptions> mergeOptions) |
|||
: base(settingAppService, settingTestAppService) |
|||
{ |
|||
_mergeOptions = mergeOptions.Value; |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Route("by-current-tenant")] |
|||
public async override Task<SettingGroupResult> GetAllForCurrentTenantAsync() |
|||
{ |
|||
var result = new SettingGroupResult(); |
|||
var markTypeMap = new List<Type> |
|||
{ |
|||
typeof(SettingMergeController), |
|||
}; |
|||
foreach (var serviceType in _mergeOptions.GlobalSettingProviders |
|||
.Where(type => !markTypeMap.Any(markType => type.IsAssignableFrom(markType)))) |
|||
{ |
|||
var settingService = LazyServiceProvider.LazyGetRequiredService(serviceType).As<IReadonlySettingAppService>(); |
|||
var currentResult = await settingService.GetAllForCurrentTenantAsync(); |
|||
foreach (var group in currentResult.Items) |
|||
{ |
|||
result.AddGroup(group); |
|||
} |
|||
markTypeMap.Add(serviceType); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Route("by-global")] |
|||
public async override Task<SettingGroupResult> GetAllForGlobalAsync() |
|||
{ |
|||
var result = new SettingGroupResult(); |
|||
var markTypeMap = new List<Type> |
|||
{ |
|||
typeof(SettingMergeController), |
|||
}; |
|||
foreach (var serviceType in _mergeOptions.GlobalSettingProviders |
|||
.Where(type => !markTypeMap.Any(markType => type.IsAssignableFrom(markType)))) |
|||
{ |
|||
var settingService = LazyServiceProvider.LazyGetRequiredService(serviceType).As<IReadonlySettingAppService>(); |
|||
var currentResult = await settingService.GetAllForGlobalAsync(); |
|||
foreach (var group in currentResult.Items) |
|||
{ |
|||
result.AddGroup(group); |
|||
} |
|||
markTypeMap.Add(serviceType); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
@ -0,0 +1,45 @@ |
|||
using LINGYUN.Abp.SettingManagement; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace LY.MicroService.Applications.Single.Controllers; |
|||
|
|||
[ExposeServices( |
|||
typeof(UserSettingController), |
|||
typeof(UserSettingMergeController))] |
|||
public class UserSettingMergeController : UserSettingController |
|||
{ |
|||
private readonly SettingManagementMergeOptions _mergeOptions; |
|||
public UserSettingMergeController( |
|||
IUserSettingAppService service, |
|||
IOptions<SettingManagementMergeOptions> mergeOptions) |
|||
: base(service) |
|||
{ |
|||
_mergeOptions = mergeOptions.Value; |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Route("by-current-user")] |
|||
public async override Task<SettingGroupResult> GetAllForCurrentUserAsync() |
|||
{ |
|||
var result = new SettingGroupResult(); |
|||
var markTypeMap = new List<Type> |
|||
{ |
|||
typeof(UserSettingMergeController), |
|||
}; |
|||
foreach (var serviceType in _mergeOptions.UserSettingProviders |
|||
.Where(type => !markTypeMap.Any(markType => type.IsAssignableFrom(markType)))) |
|||
{ |
|||
var settingService = LazyServiceProvider.LazyGetRequiredService(serviceType).As<IUserSettingAppService>(); |
|||
var currentResult = await settingService.GetAllForCurrentUserAsync(); |
|||
foreach (var group in currentResult.Items) |
|||
{ |
|||
result.AddGroup(group); |
|||
} |
|||
markTypeMap.Add(serviceType); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
@ -0,0 +1,74 @@ |
|||
using LINGYUN.Abp.SettingManagement; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.Extensions.Options; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace LY.MicroService.BackendAdmin.Controllers; |
|||
|
|||
[ExposeServices( |
|||
typeof(SettingController), |
|||
typeof(SettingMergeController))] |
|||
public class SettingMergeController : SettingController |
|||
{ |
|||
private readonly SettingManagementMergeOptions _mergeOptions; |
|||
public SettingMergeController( |
|||
ISettingAppService settingAppService, |
|||
ISettingTestAppService settingTestAppService, |
|||
IOptions<SettingManagementMergeOptions> mergeOptions) |
|||
: base(settingAppService, settingTestAppService) |
|||
{ |
|||
_mergeOptions = mergeOptions.Value; |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Route("by-current-tenant")] |
|||
public async override Task<SettingGroupResult> GetAllForCurrentTenantAsync() |
|||
{ |
|||
var result = new SettingGroupResult(); |
|||
var markTypeMap = new List<Type> |
|||
{ |
|||
typeof(SettingMergeController), |
|||
}; |
|||
foreach (var serviceType in _mergeOptions.GlobalSettingProviders |
|||
.Where(type => !markTypeMap.Any(markType => type.IsAssignableFrom(markType)))) |
|||
{ |
|||
var settingService = LazyServiceProvider.LazyGetRequiredService(serviceType).As<IReadonlySettingAppService>(); |
|||
var currentResult = await settingService.GetAllForCurrentTenantAsync(); |
|||
foreach (var group in currentResult.Items) |
|||
{ |
|||
result.AddGroup(group); |
|||
} |
|||
markTypeMap.Add(serviceType); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Route("by-global")] |
|||
public async override Task<SettingGroupResult> GetAllForGlobalAsync() |
|||
{ |
|||
var result = new SettingGroupResult(); |
|||
var markTypeMap = new List<Type> |
|||
{ |
|||
typeof(SettingMergeController), |
|||
}; |
|||
foreach (var serviceType in _mergeOptions.GlobalSettingProviders |
|||
.Where(type => !markTypeMap.Any(markType => type.IsAssignableFrom(markType)))) |
|||
{ |
|||
var settingService = LazyServiceProvider.LazyGetRequiredService(serviceType).As<IReadonlySettingAppService>(); |
|||
var currentResult = await settingService.GetAllForGlobalAsync(); |
|||
foreach (var group in currentResult.Items) |
|||
{ |
|||
result.AddGroup(group); |
|||
} |
|||
markTypeMap.Add(serviceType); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
using LINGYUN.Abp.SettingManagement; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.Extensions.Options; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace LY.MicroService.BackendAdmin.Controllers; |
|||
|
|||
[ExposeServices( |
|||
typeof(UserSettingController), |
|||
typeof(UserSettingMergeController))] |
|||
public class UserSettingMergeController : UserSettingController |
|||
{ |
|||
private readonly SettingManagementMergeOptions _mergeOptions; |
|||
public UserSettingMergeController( |
|||
IUserSettingAppService service, |
|||
IOptions<SettingManagementMergeOptions> mergeOptions) |
|||
: base(service) |
|||
{ |
|||
_mergeOptions = mergeOptions.Value; |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Route("by-current-user")] |
|||
public async override Task<SettingGroupResult> GetAllForCurrentUserAsync() |
|||
{ |
|||
var result = new SettingGroupResult(); |
|||
var markTypeMap = new List<Type> |
|||
{ |
|||
typeof(UserSettingMergeController), |
|||
}; |
|||
foreach (var serviceType in _mergeOptions.UserSettingProviders |
|||
.Where(type => !markTypeMap.Any(markType => type.IsAssignableFrom(markType)))) |
|||
{ |
|||
var settingService = LazyServiceProvider.LazyGetRequiredService(serviceType).As<IUserSettingAppService>(); |
|||
var currentResult = await settingService.GetAllForCurrentUserAsync(); |
|||
foreach (var group in currentResult.Items) |
|||
{ |
|||
result.AddGroup(group); |
|||
} |
|||
markTypeMap.Add(serviceType); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
Loading…
Reference in new issue