Browse Source

Merge pull request #898 from colinin/fix-wrapper

Fix wrapper
pull/914/head
yx lin 2 years ago
committed by GitHub
parent
commit
972e6231d2
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      aspnet-core/LINGYUN.MicroService.SingleProject.sln
  2. 2
      aspnet-core/framework/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/AbpAspNetCoreMvcWrapperModule.cs
  3. 153
      aspnet-core/framework/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/ApiExploring/AbpWrapResultApiDescriptionProvider.cs
  4. 5
      aspnet-core/framework/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/IWrapResultChecker.cs
  5. 53
      aspnet-core/framework/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/WrapResultChecker.cs
  6. 36
      aspnet-core/framework/settings/LINGYUN.Abp.SettingManagement.Application.Contracts/LINGYUN/Abp/SettingManagement/AbpSettingManagementApplicationContractsModule.cs
  7. 13
      aspnet-core/framework/settings/LINGYUN.Abp.SettingManagement.Application.Contracts/LINGYUN/Abp/SettingManagement/SettingManagementMergeOptions.cs
  8. 70
      aspnet-core/services/LY.MicroService.Applications.Single/Controllers/SettingMergeController.cs
  9. 45
      aspnet-core/services/LY.MicroService.Applications.Single/Controllers/UserSettingMergeController.cs
  10. 2
      aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.Configure.cs
  11. 74
      aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/Controllers/SettingMergeController.cs
  12. 49
      aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/Controllers/UserSettingMergeController.cs

2
aspnet-core/LINGYUN.MicroService.SingleProject.sln

@ -494,7 +494,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.Mvc.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.Wrapper", "framework\common\LINGYUN.Abp.AspNetCore.Wrapper\LINGYUN.Abp.AspNetCore.Wrapper.csproj", "{FDBA1B4A-CC5D-4710-AB8C-FA5A91B91BDE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.OpenIddict.AspNetCore", "modules\openIddict\LINGYUN.Abp.OpenIddict.AspNetCore\LINGYUN.Abp.OpenIddict.AspNetCore.csproj", "{6026DAE3-F2AD-4F6B-99EF-EEAAA5873861}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OpenIddict.AspNetCore", "modules\openIddict\LINGYUN.Abp.OpenIddict.AspNetCore\LINGYUN.Abp.OpenIddict.AspNetCore.csproj", "{6026DAE3-F2AD-4F6B-99EF-EEAAA5873861}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution

2
aspnet-core/framework/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/AbpAspNetCoreMvcWrapperModule.cs

@ -5,7 +5,9 @@ using LINGYUN.Abp.Wrapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using System.Collections.Generic;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.ApiExploring;
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
using Volo.Abp.AspNetCore.Mvc.ProxyScripting;
using Volo.Abp.Content;

153
aspnet-core/framework/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/ApiExploring/AbpWrapResultApiDescriptionProvider.cs

@ -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);
}
}
}

5
aspnet-core/framework/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/IWrapResultChecker.cs

@ -1,9 +1,12 @@
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Filters;
namespace LINGYUN.Abp.AspNetCore.Mvc.Wrapper
{
public interface IWrapResultChecker
{
bool WrapOnAction(ActionDescriptor actionDescriptor);
bool WrapOnExecution(FilterContext context);
bool WrapOnException(ExceptionContext context);

53
aspnet-core/framework/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/WrapResultChecker.cs

@ -20,6 +20,16 @@ namespace LINGYUN.Abp.AspNetCore.Mvc.Wrapper
Options = optionsMonitor.CurrentValue;
}
public virtual bool WrapOnAction(ActionDescriptor actionDescriptor)
{
if (!Options.IsEnabled)
{
return false;
}
return CheckForActionDescriptor(actionDescriptor);
}
public bool WrapOnException(ExceptionContext context)
{
if (!CheckForBase(context))
@ -32,6 +42,11 @@ namespace LINGYUN.Abp.AspNetCore.Mvc.Wrapper
public bool WrapOnException(PageHandlerExecutedContext context)
{
if (!CheckForBase(context))
{
return false;
}
return CheckForException(context.Exception);
}
@ -40,7 +55,6 @@ namespace LINGYUN.Abp.AspNetCore.Mvc.Wrapper
return CheckForBase(context);
}
protected virtual bool CheckForBase(FilterContext context)
{
if (!Options.IsEnabled)
@ -48,49 +62,56 @@ namespace LINGYUN.Abp.AspNetCore.Mvc.Wrapper
return false;
}
// 用户传递不包装
if (context.HttpContext.Request.Headers.ContainsKey(AbpHttpWrapConsts.AbpDontWrapResult))
{
return false;
}
if (context.ActionDescriptor is ControllerActionDescriptor descriptor)
// 用户传递需要包装
if (context.HttpContext.Request.Headers.ContainsKey(AbpHttpWrapConsts.AbpWrapResult))
{
if (!context.ActionDescriptor.HasObjectResult())
{
return false;
}
return true;
}
//if (!context.HttpContext.Request.CanAccept(MimeTypes.Application.Json))
//{
// return false;
//}
if (!CheckForUrl(context))
{
return false;
}
return CheckForActionDescriptor(context.ActionDescriptor);
}
if (!CheckForUrl(context))
protected virtual bool CheckForActionDescriptor(ActionDescriptor descriptor)
{
if (descriptor is ControllerActionDescriptor controllerActionDescriptor)
{
if (!descriptor.HasObjectResult())
{
return false;
}
if (!CheckForNamespace(descriptor))
if (!CheckForNamespace(controllerActionDescriptor))
{
return false;
}
if (!CheckForController(descriptor))
if (!CheckForController(controllerActionDescriptor))
{
return false;
}
if (!CheckForInterfaces(descriptor))
if (!CheckForInterfaces(controllerActionDescriptor))
{
return false;
}
if (!CheckForMethod(descriptor))
if (!CheckForMethod(controllerActionDescriptor))
{
return false;
}
if (!CheckForReturnType(descriptor))
if (!CheckForReturnType(controllerActionDescriptor))
{
return false;
}

36
aspnet-core/framework/settings/LINGYUN.Abp.SettingManagement.Application.Contracts/LINGYUN/Abp/SettingManagement/AbpSettingManagementApplicationContractsModule.cs

@ -1,4 +1,7 @@
using Volo.Abp.Application;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using Volo.Abp.Application;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.SettingManagement;
@ -11,6 +14,11 @@ namespace LINGYUN.Abp.SettingManagement
[DependsOn(typeof(AbpSettingManagementDomainSharedModule))]
public class AbpSettingManagementApplicationContractsModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
AutoAddSettingProviders(context.Services);
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
@ -25,5 +33,31 @@ namespace LINGYUN.Abp.SettingManagement
.AddVirtualJson("/LINGYUN/Abp/SettingManagement/Localization/ApplicationContracts");
});
}
private static void AutoAddSettingProviders(IServiceCollection services)
{
var userSettingProviders = new List<Type>();
var globalSettingProviders = new List<Type>();
services.OnRegistered(context =>
{
if (typeof(IUserSettingAppService).IsAssignableFrom(context.ImplementationType) &&
context.ImplementationType.Name.EndsWith("AppService"))
{
userSettingProviders.Add(context.ImplementationType);
}
if (typeof(IReadonlySettingAppService).IsAssignableFrom(context.ImplementationType) &&
context.ImplementationType.Name.EndsWith("AppService"))
{
globalSettingProviders.Add(context.ImplementationType);
}
});
services.Configure<SettingManagementMergeOptions>(options =>
{
options.UserSettingProviders.AddIfNotContains(userSettingProviders);
options.GlobalSettingProviders.AddIfNotContains(globalSettingProviders);
});
}
}
}

13
aspnet-core/framework/settings/LINGYUN.Abp.SettingManagement.Application.Contracts/LINGYUN/Abp/SettingManagement/SettingManagementMergeOptions.cs

@ -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>();
}
}

70
aspnet-core/services/LY.MicroService.Applications.Single/Controllers/SettingMergeController.cs

@ -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;
}
}

45
aspnet-core/services/LY.MicroService.Applications.Single/Controllers/UserSettingMergeController.cs

@ -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;
}
}

2
aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.Configure.cs

@ -722,7 +722,7 @@ public partial class MicroServiceApplicationsSingleModule
}
};
});
services.AddAlwaysAllowAuthorization();
if (isDevelopment)
{
services.AddAlwaysAllowAuthorization();

74
aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/Controllers/SettingMergeController.cs

@ -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;
}
}

49
aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/Controllers/UserSettingMergeController.cs

@ -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…
Cancel
Save