Browse Source

feat(wrapper): 增加对于dapr的包装结果处理

pull/409/head
cKey 4 years ago
parent
commit
0abd02d162
  1. 9
      aspnet-core/LINGYUN.MicroService.Common.sln
  2. 18
      aspnet-core/modules/common/LINGYUN.Abp.HttpClient.Wrapper/LINGYUN.Abp.HttpClient.Wrapper.csproj
  3. 13
      aspnet-core/modules/common/LINGYUN.Abp.HttpClient.Wrapper/LINGYUN/Abp/HttpClient/Wrapper/AbpHttpClientWrapperModule.cs
  4. 153
      aspnet-core/modules/common/LINGYUN.Abp.HttpClient.Wrapper/LINGYUN/Abp/HttpClient/Wrapper/DynamicHttpProxyInterceptorWrapClientProxy.cs
  5. 2
      aspnet-core/modules/common/LINGYUN.Abp.Wrapper/LINGYUN/Abp/Wrapper/AbpHttpWrapConsts.cs
  6. 69
      aspnet-core/modules/common/LINGYUN.Abp.Wrapper/LINGYUN/Abp/Wrapper/AbpWrapperOptions.cs
  7. 4
      aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Actors.AspNetCore/LINGYUN.Abp.Dapr.Actors.AspNetCore.csproj
  8. 115
      aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Actors.AspNetCore/LINGYUN/Abp/Dapr/Actors/AspNetCore/AbpDaprActorsAspNetCoreModule.cs
  9. 48
      aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Actors/LINGYUN/Abp/Dapr/Actors/AbpDaprActorsModule.cs
  10. 1
      aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/LINGYUN.Abp.Dapr.Client.csproj
  11. 6
      aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/LINGYUN/Abp/Dapr/Client/AbpDaprClientModule.cs
  12. 654
      aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/LINGYUN/Abp/Dapr/Client/DynamicProxying/DynamicDaprClientProxyInterceptor.cs
  13. 2
      aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/AbpAspNetCoreMvcWrapperModule.cs
  14. 70
      aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/AbpAspNetCoreMvcWrapperOptions.cs
  15. 4
      aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/ExceptionHandling/AbpExceptionPageWrapResultFilter.cs
  16. 4
      aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/ExceptionHandling/AbpExceptionWrapResultFilter.cs
  17. 1
      aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/Filters/AbpWrapResultFilter.cs
  18. 6
      aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/WrapResultChecker.cs
  19. 2
      aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/Wraping/EmptyActionResultWrapper.cs
  20. 4
      aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/Wraping/JsonActionResultWrapper.cs
  21. 12
      aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/Wraping/ObjectActionResultWrapper.cs
  22. 3
      aspnet-core/tests/LINGYUN.Abp.AspNetCore.Mvc.Tests/LINGYUN/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs
  23. 2
      aspnet-core/tests/LINGYUN.Abp.AspNetCore.Mvc.Tests/LINGYUN/Abp/AspNetCore/Mvc/Results/WrapResultController_Tests.cs
  24. 2
      aspnet-core/tests/LINGYUN.Abp.Dapr.AspNetCore.TestHost/LINGYUN.Abp.Dapr.AspNetCore.TestHost.csproj
  25. 90
      aspnet-core/tests/LINGYUN.Abp.Dapr.AspNetCore.TestHost/LINGYUN/Abp/Dapr/AbpDaprAspNetCoreTestHostModule.cs
  26. 94
      aspnet-core/tests/LINGYUN.Abp.Dapr.AspNetCore.TestHost/LINGYUN/Abp/Dapr/ServiceInvocation/TestAppService.cs
  27. 74
      aspnet-core/tests/LINGYUN.Abp.Dapr.Client.Tests/LINGYUN/Abp/Dapr/Client/Tests/TestAppServiceTests.cs
  28. 23
      aspnet-core/tests/LINGYUN.Abp.Dapr.Tests/LINGYUN/Abp/Dapr/AbpDaprTestModule.cs
  29. 30
      aspnet-core/tests/LINGYUN.Abp.Dapr.Tests/LINGYUN/Abp/Dapr/ServiceInvocation/ITestAppService.cs
  30. 7
      aspnet-core/tests/LINGYUN.Abp.Dapr.Tests/LINGYUN/Abp/Dapr/TestNeedWrapObject.cs

9
aspnet-core/LINGYUN.MicroService.Common.sln

@ -204,7 +204,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.Test
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.Mvc.Tests", "tests\LINGYUN.Abp.AspNetCore.Mvc.Tests\LINGYUN.Abp.AspNetCore.Mvc.Tests.csproj", "{AE5E6DE8-FC02-4633-BA49-C4B8ABADB502}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.Mvc.Tests", "tests\LINGYUN.Abp.AspNetCore.Mvc.Tests\LINGYUN.Abp.AspNetCore.Mvc.Tests.csproj", "{AE5E6DE8-FC02-4633-BA49-C4B8ABADB502}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Wrapper.Tests", "tests\LINGYUN.Abp.Wrapper.Tests\LINGYUN.Abp.Wrapper.Tests.csproj", "{31AED9ED-29BD-4F2F-8D3A-F00CBB9FC73C}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Wrapper.Tests", "tests\LINGYUN.Abp.Wrapper.Tests\LINGYUN.Abp.Wrapper.Tests.csproj", "{31AED9ED-29BD-4F2F-8D3A-F00CBB9FC73C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.HttpClient.Wrapper", "modules\common\LINGYUN.Abp.HttpClient.Wrapper\LINGYUN.Abp.HttpClient.Wrapper.csproj", "{F6CABEE7-DE34-458A-8787-95DFB1DA4762}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -536,6 +538,10 @@ Global
{31AED9ED-29BD-4F2F-8D3A-F00CBB9FC73C}.Debug|Any CPU.Build.0 = Debug|Any CPU {31AED9ED-29BD-4F2F-8D3A-F00CBB9FC73C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{31AED9ED-29BD-4F2F-8D3A-F00CBB9FC73C}.Release|Any CPU.ActiveCfg = Release|Any CPU {31AED9ED-29BD-4F2F-8D3A-F00CBB9FC73C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{31AED9ED-29BD-4F2F-8D3A-F00CBB9FC73C}.Release|Any CPU.Build.0 = Release|Any CPU {31AED9ED-29BD-4F2F-8D3A-F00CBB9FC73C}.Release|Any CPU.Build.0 = Release|Any CPU
{F6CABEE7-DE34-458A-8787-95DFB1DA4762}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F6CABEE7-DE34-458A-8787-95DFB1DA4762}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F6CABEE7-DE34-458A-8787-95DFB1DA4762}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F6CABEE7-DE34-458A-8787-95DFB1DA4762}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -639,6 +645,7 @@ Global
{BD4165DB-F8A4-4715-A05A-CC08F6A18D67} = {B86C21A4-73B7-471E-B73A-B4B905EC9435} {BD4165DB-F8A4-4715-A05A-CC08F6A18D67} = {B86C21A4-73B7-471E-B73A-B4B905EC9435}
{AE5E6DE8-FC02-4633-BA49-C4B8ABADB502} = {B86C21A4-73B7-471E-B73A-B4B905EC9435} {AE5E6DE8-FC02-4633-BA49-C4B8ABADB502} = {B86C21A4-73B7-471E-B73A-B4B905EC9435}
{31AED9ED-29BD-4F2F-8D3A-F00CBB9FC73C} = {B86C21A4-73B7-471E-B73A-B4B905EC9435} {31AED9ED-29BD-4F2F-8D3A-F00CBB9FC73C} = {B86C21A4-73B7-471E-B73A-B4B905EC9435}
{F6CABEE7-DE34-458A-8787-95DFB1DA4762} = {086BE5BE-8594-4DA7-8819-935FEF76DABD}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {06C707C6-02C0-411A-AD3B-2D0E13787CB8} SolutionGuid = {06C707C6-02C0-411A-AD3B-2D0E13787CB8}

18
aspnet-core/modules/common/LINGYUN.Abp.HttpClient.Wrapper/LINGYUN.Abp.HttpClient.Wrapper.csproj

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Http.Client" Version="5.0.0-rc.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.Wrapper\LINGYUN.Abp.Wrapper.csproj" />
</ItemGroup>
</Project>

13
aspnet-core/modules/common/LINGYUN.Abp.HttpClient.Wrapper/LINGYUN/Abp/HttpClient/Wrapper/AbpHttpClientWrapperModule.cs

@ -0,0 +1,13 @@
using LINGYUN.Abp.Wrapper;
using Volo.Abp.Http.Client;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.HttpClient.Wrapper
{
[DependsOn(
typeof(AbpHttpClientModule),
typeof(AbpWrapperModule))]
public class AbpHttpClientWrapperModule : AbpModule
{
}
}

153
aspnet-core/modules/common/LINGYUN.Abp.HttpClient.Wrapper/LINGYUN/Abp/HttpClient/Wrapper/DynamicHttpProxyInterceptorWrapClientProxy.cs

@ -0,0 +1,153 @@
using LINGYUN.Abp.Wrapper;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Content;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http;
using Volo.Abp.Http.Client;
using Volo.Abp.Http.Client.Authentication;
using Volo.Abp.Http.Client.ClientProxying;
using Volo.Abp.Http.Client.DynamicProxying;
namespace LINGYUN.Abp.HttpClient.Wrapper
{
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(DynamicHttpProxyInterceptorClientProxy<>))]
public class DynamicHttpProxyInterceptorWrapClientProxy<TService>
: DynamicHttpProxyInterceptorClientProxy<TService>, ITransientDependency
{
protected IOptions<AbpWrapperOptions> WrapperOptions => LazyServiceProvider.LazyGetRequiredService<IOptions<AbpWrapperOptions>>();
protected override async Task<T> RequestAsync<T>(ClientProxyRequestContext requestContext)
{
var response = await RequestAndGetResponseAsync(requestContext);
var responseContent = response.Content;
if (typeof(T) == typeof(IRemoteStreamContent) ||
typeof(T) == typeof(RemoteStreamContent))
{
/* returning a class that holds a reference to response
* content just to be sure that GC does not dispose of
* it before we finish doing our work with the stream */
return (T)(object)new RemoteStreamContent(
await responseContent.ReadAsStreamAsync(),
responseContent.Headers?.ContentDisposition?.FileNameStar ??
RemoveQuotes(responseContent.Headers?.ContentDisposition?.FileName).ToString(),
responseContent.Headers?.ContentType?.ToString(),
responseContent.Headers?.ContentLength);
}
var stringContent = await responseContent.ReadAsStringAsync();
if (stringContent.IsNullOrWhiteSpace())
{
return default;
}
// 对于包装后的结果需要处理
if (response.Headers.Contains(AbpHttpWrapConsts.AbpWrapResult))
{
var wrapResult = JsonSerializer.Deserialize<WrapResult<T>>(stringContent);
ThrowExceptionForResponse(wrapResult);
if (typeof(T) == typeof(string))
{
return (T)(object)wrapResult.Result;
}
return wrapResult.Result;
}
if (typeof(T) == typeof(string))
{
return (T)(object)stringContent;
}
if (stringContent.IsNullOrWhiteSpace())
{
return default;
}
return JsonSerializer.Deserialize<T>(stringContent);
}
public override async Task<HttpContent> CallRequestAsync(ClientProxyRequestContext requestContext)
{
var response = await RequestAndGetResponseAsync(requestContext);
// 对于包装后的结果需要处理
if (response.Headers.Contains(AbpHttpWrapConsts.AbpWrapResult))
{
var stringContent = await response.Content.ReadAsStringAsync();
var wrapResult = JsonSerializer.Deserialize<WrapResult>(stringContent);
ThrowExceptionForResponse(wrapResult);
}
return response.Content;
}
protected virtual void ThrowExceptionForResponse<T>(WrapResult<T> wrapResult)
{
if (!string.Equals(wrapResult.Code, WrapperOptions.Value.CodeWithSuccess))
{
var errorInfo = new RemoteServiceErrorInfo(
wrapResult.Message,
wrapResult.Details,
wrapResult.Code);
throw new AbpRemoteCallException(errorInfo)
{
HttpStatusCode = (int)WrapperOptions.Value.HttpStatusCode
};
}
}
protected virtual async Task<HttpResponseMessage> RequestAndGetResponseAsync(ClientProxyRequestContext requestContext)
{
var clientConfig = ClientOptions.Value.HttpClientProxies.GetOrDefault(requestContext.ServiceType) ?? throw new AbpException($"Could not get HttpClientProxyConfig for {requestContext.ServiceType.FullName}.");
var remoteServiceConfig = await RemoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync(clientConfig.RemoteServiceName);
var client = HttpClientFactory.Create(clientConfig.RemoteServiceName);
var apiVersion = await GetApiVersionInfoAsync(requestContext);
var url = remoteServiceConfig.BaseUrl.EnsureEndsWith('/') + await GetUrlWithParametersAsync(requestContext, apiVersion);
var requestMessage = new HttpRequestMessage(requestContext.Action.GetHttpMethod(), url)
{
Content = await ClientProxyRequestPayloadBuilder.BuildContentAsync(requestContext.Action, requestContext.Arguments, JsonSerializer, apiVersion)
};
AddHeaders(requestContext.Arguments, requestContext.Action, requestMessage, apiVersion);
if (requestContext.Action.AllowAnonymous != true)
{
await ClientAuthenticator.Authenticate(
new RemoteServiceHttpClientAuthenticateContext(
client,
requestMessage,
remoteServiceConfig,
clientConfig.RemoteServiceName
)
);
}
var response = await client.SendAsync(
requestMessage,
HttpCompletionOption.ResponseHeadersRead /*this will buffer only the headers, the content will be used as a stream*/,
GetCancellationToken(requestContext.Arguments)
);
if (!response.IsSuccessStatusCode)
{
await ThrowExceptionForResponseAsync(response);
}
return response;
}
}
}

2
aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/AbpHttpWrapConsts.cs → aspnet-core/modules/common/LINGYUN.Abp.Wrapper/LINGYUN/Abp/Wrapper/AbpHttpWrapConsts.cs

@ -1,4 +1,4 @@
namespace LINGYUN.Abp.AspNetCore.Mvc.Wrapper namespace LINGYUN.Abp.Wrapper
{ {
public static class AbpHttpWrapConsts public static class AbpHttpWrapConsts
{ {

69
aspnet-core/modules/common/LINGYUN.Abp.Wrapper/LINGYUN/Abp/Wrapper/AbpWrapperOptions.cs

@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net;
using Volo.Abp.Collections;
namespace LINGYUN.Abp.Wrapper namespace LINGYUN.Abp.Wrapper
{ {
@ -10,12 +12,79 @@ namespace LINGYUN.Abp.Wrapper
/// 默认: 500 /// 默认: 500
/// </summary> /// </summary>
public string CodeWithUnhandled { get; set; } public string CodeWithUnhandled { get; set; }
/// <summary>
/// 是否启用包装器
/// </summary>
public bool IsEnabled { get; set; }
/// <summary>
/// 成功时返回代码
/// 默认:0
/// </summary>
public string CodeWithSuccess { get; set; }
/// <summary>
/// 资源为空时是否提示错误
/// 默认: false
/// </summary>
public bool ErrorWithEmptyResult { get; set; }
/// <summary>
/// 资源为空时返回代码
/// 默认:404
/// </summary>
public Func<IServiceProvider, string> CodeWithEmptyResult { get; set; }
/// <summary>
/// 资源为空时返回错误消息
/// </summary>
public Func<IServiceProvider, string> MessageWithEmptyResult { get; set; }
/// <summary>
/// 包装后的返回状态码
/// 默认:200 HttpStatusCode.OK
/// </summary>
public HttpStatusCode HttpStatusCode { get; set; }
/// <summary>
/// 忽略Url开头类型
/// </summary>
public IList<string> IgnorePrefixUrls { get; }
/// <summary>
/// 忽略指定命名空间
/// </summary>
public IList<string> IgnoreNamespaces { get; }
/// <summary>
/// 忽略控制器
/// </summary>
public ITypeList IgnoreControllers { get; }
/// <summary>
/// 忽略返回值
/// </summary>
public ITypeList IgnoreReturnTypes { get; }
/// <summary>
/// 忽略异常
/// </summary>
public ITypeList<Exception> IgnoreExceptions { get; }
/// <summary>
/// 忽略服务类型
/// </summary>
public ITypeList IgnoreBaseTypes { get; }
internal IDictionary<Type, IExceptionWrapHandler> ExceptionHandles { get; } internal IDictionary<Type, IExceptionWrapHandler> ExceptionHandles { get; }
public AbpWrapperOptions() public AbpWrapperOptions()
{ {
CodeWithUnhandled = "500"; CodeWithUnhandled = "500";
CodeWithSuccess = "0";
HttpStatusCode = HttpStatusCode.OK;
ErrorWithEmptyResult = false;
IgnorePrefixUrls = new List<string>();
IgnoreNamespaces = new List<string>();
IgnoreControllers = new TypeList();
IgnoreReturnTypes = new TypeList();
IgnoreBaseTypes = new TypeList();
IgnoreExceptions = new TypeList<Exception>();
CodeWithEmptyResult = (_) => "404";
MessageWithEmptyResult = (_) => "Not Found";
ExceptionHandles = new Dictionary<Type, IExceptionWrapHandler>(); ExceptionHandles = new Dictionary<Type, IExceptionWrapHandler>();
} }

4
aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Actors.AspNetCore/LINGYUN.Abp.Dapr.Actors.AspNetCore.csproj

@ -12,4 +12,8 @@
<PackageReference Include="Volo.Abp.AspNetCore" Version="4.4.0" /> <PackageReference Include="Volo.Abp.AspNetCore" Version="4.4.0" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\common\LINGYUN.Abp.Wrapper\LINGYUN.Abp.Wrapper.csproj" />
</ItemGroup>
</Project> </Project>

115
aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Actors.AspNetCore/LINGYUN/Abp/Dapr/Actors/AspNetCore/AbpDaprActorsAspNetCoreModule.cs

@ -1,54 +1,61 @@
using Dapr.Actors; using Dapr.Actors;
using Dapr.Actors.Runtime; using Dapr.Actors.Runtime;
using Microsoft.AspNetCore.Builder; using LINGYUN.Abp.Wrapper;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection; using Microsoft.AspNetCore.Routing;
using System; using Microsoft.Extensions.DependencyInjection;
using System.Collections.Generic; using System;
using Volo.Abp.AspNetCore; using System.Collections.Generic;
using Volo.Abp.Modularity; using Volo.Abp.AspNetCore;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Dapr.Actors.AspNetCore
{ namespace LINGYUN.Abp.Dapr.Actors.AspNetCore
[DependsOn( {
typeof(AbpAspNetCoreModule))] [DependsOn(
public class AbpDaprActorsAspNetCoreModule : AbpModule typeof(AbpAspNetCoreModule),
{ typeof(AbpWrapperModule))]
public override void PreConfigureServices(ServiceConfigurationContext context) public class AbpDaprActorsAspNetCoreModule : AbpModule
{ {
AddDefinitionActor(context.Services); public override void PreConfigureServices(ServiceConfigurationContext context)
} {
AddDefinitionActor(context.Services);
public override void ConfigureServices(ServiceConfigurationContext context) }
{
Configure<AbpEndpointRouterOptions>(options => public override void ConfigureServices(ServiceConfigurationContext context)
{ {
options.EndpointConfigureActions.Add(endpointContext => Configure<AbpEndpointRouterOptions>(options =>
{ {
endpointContext.Endpoints.MapActorsHandlers(); options.EndpointConfigureActions.Add(endpointContext =>
}); {
}); endpointContext.Endpoints.MapActorsHandlers();
} });
});
private static void AddDefinitionActor(IServiceCollection services)
{ Configure<AbpWrapperOptions>(options =>
var actorRegistrations = new List<ActorRegistration>(); {
options.IgnoreBaseTypes.TryAdd<IActor>();
services.OnRegistred(context => });
{ }
if (typeof(IActor).IsAssignableFrom(context.ImplementationType) &&
!actorRegistrations.Contains(context.ImplementationType)) private static void AddDefinitionActor(IServiceCollection services)
{ {
var actorRegistration = new ActorRegistration(context.ImplementationType.GetActorTypeInfo()); var actorRegistrations = new List<ActorRegistration>();
actorRegistrations.Add(actorRegistration); services.OnRegistred(context =>
} {
}); if (typeof(IActor).IsAssignableFrom(context.ImplementationType) &&
!actorRegistrations.Contains(context.ImplementationType))
services.AddActors(options => {
{ var actorRegistration = new ActorRegistration(context.ImplementationType.GetActorTypeInfo());
options.Actors.AddIfNotContains(actorRegistrations);
}); actorRegistrations.Add(actorRegistration);
} }
} });
}
services.AddActors(options =>
{
options.Actors.AddIfNotContains(actorRegistrations);
});
}
}
}

48
aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Actors/LINGYUN/Abp/Dapr/Actors/AbpDaprActorsModule.cs

@ -1,24 +1,24 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Http.Client; using Volo.Abp.Http.Client;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Dapr.Actors namespace LINGYUN.Abp.Dapr.Actors
{ {
[DependsOn( [DependsOn(
typeof(AbpHttpClientModule) typeof(AbpHttpClientModule)
)] )]
public class AbpDaprActorsModule : AbpModule public class AbpDaprActorsModule : AbpModule
{ {
/// <summary> /// <summary>
/// 与AbpHttpClient集成,创建一个命名HttpClient /// 与AbpHttpClient集成,创建一个命名HttpClient
/// </summary> /// </summary>
internal const string DaprHttpClient = "_AbpDaprActorsClient"; internal const string DaprHttpClient = "_AbpDaprActorsClient";
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
var configuration = context.Services.GetConfiguration(); var configuration = context.Services.GetConfiguration();
Configure<AbpDaprRemoteServiceOptions>(configuration); Configure<AbpDaprRemoteServiceOptions>(configuration);
context.Services.AddHttpClient(DaprHttpClient); context.Services.AddHttpClient(DaprHttpClient);
} }
} }
} }

1
aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/LINGYUN.Abp.Dapr.Client.csproj

@ -12,6 +12,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\common\LINGYUN.Abp.Wrapper\LINGYUN.Abp.Wrapper.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.Dapr\LINGYUN.Abp.Dapr.csproj" /> <ProjectReference Include="..\LINGYUN.Abp.Dapr\LINGYUN.Abp.Dapr.csproj" />
</ItemGroup> </ItemGroup>

6
aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/LINGYUN/Abp/Dapr/Client/AbpDaprClientModule.cs

@ -1,11 +1,13 @@
using Microsoft.Extensions.DependencyInjection; using LINGYUN.Abp.Wrapper;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Http.Client; using Volo.Abp.Http.Client;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Dapr.Client namespace LINGYUN.Abp.Dapr.Client
{ {
[DependsOn( [DependsOn(
typeof(AbpHttpClientModule) typeof(AbpHttpClientModule),
typeof(AbpWrapperModule)
)] )]
public class AbpDaprClientModule : AbpModule public class AbpDaprClientModule : AbpModule
{ {

654
aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/LINGYUN/Abp/Dapr/Client/DynamicProxying/DynamicDaprClientProxyInterceptor.cs

@ -1,312 +1,342 @@
using Dapr.Client; using Dapr.Client;
using Microsoft.Extensions.Logging; using LINGYUN.Abp.Wrapper;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Logging.Abstractions;
using System; using Microsoft.Extensions.Options;
using System.Collections.Generic; using System;
using System.Globalization; using System.Collections.Generic;
using System.Linq; using System.Globalization;
using System.Net.Http; using System.Linq;
using System.Net.Http.Headers; using System.Net.Http;
using System.Reflection; using System.Net.Http.Headers;
using System.Threading; using System.Reflection;
using System.Threading.Tasks; using System.Threading;
using Volo.Abp; using System.Threading.Tasks;
using Volo.Abp.Content; using Volo.Abp;
using Volo.Abp.DependencyInjection; using Volo.Abp.Content;
using Volo.Abp.DynamicProxy; using Volo.Abp.DependencyInjection;
using Volo.Abp.Http; using Volo.Abp.DynamicProxy;
using Volo.Abp.Http.Client; using Volo.Abp.Http;
using Volo.Abp.Http.Client.Authentication; using Volo.Abp.Http.Client;
using Volo.Abp.Http.Client.DynamicProxying; using Volo.Abp.Http.Client.Authentication;
using Volo.Abp.Http.Modeling; using Volo.Abp.Http.Client.DynamicProxying;
using Volo.Abp.Http.ProxyScripting.Generators; using Volo.Abp.Http.Modeling;
using Volo.Abp.Json; using Volo.Abp.Http.ProxyScripting.Generators;
using Volo.Abp.MultiTenancy; using Volo.Abp.Json;
using Volo.Abp.Threading; using Volo.Abp.MultiTenancy;
using Volo.Abp.Tracing; using Volo.Abp.Threading;
using Volo.Abp.Tracing;
namespace LINGYUN.Abp.Dapr.Client.DynamicProxying
{ namespace LINGYUN.Abp.Dapr.Client.DynamicProxying
public class DynamicDaprClientProxyInterceptor<TService> : AbpInterceptor, ITransientDependency {
{ public class DynamicDaprClientProxyInterceptor<TService> : AbpInterceptor, ITransientDependency
protected static MethodInfo MakeRequestAndGetResultAsyncMethod { get; } {
protected static MethodInfo MakeRequestAndGetResultAsyncMethod { get; }
protected IDaprClientFactory DaprClientFactory { get; }
protected ICancellationTokenProvider CancellationTokenProvider { get; } protected IDaprClientFactory DaprClientFactory { get; }
protected ICorrelationIdProvider CorrelationIdProvider { get; } protected ICancellationTokenProvider CancellationTokenProvider { get; }
protected ICurrentTenant CurrentTenant { get; } protected ICorrelationIdProvider CorrelationIdProvider { get; }
protected AbpCorrelationIdOptions AbpCorrelationIdOptions { get; } protected ICurrentTenant CurrentTenant { get; }
protected IDynamicProxyHttpClientFactory HttpClientFactory { get; } protected AbpCorrelationIdOptions AbpCorrelationIdOptions { get; }
protected IDaprApiDescriptionFinder ApiDescriptionFinder { get; } protected IDynamicProxyHttpClientFactory HttpClientFactory { get; }
protected AbpDaprRemoteServiceOptions AbpRemoteServiceOptions { get; } protected IDaprApiDescriptionFinder ApiDescriptionFinder { get; }
protected AbpDaprClientProxyOptions ClientProxyOptions { get; } protected AbpDaprRemoteServiceOptions AbpRemoteServiceOptions { get; }
protected IJsonSerializer JsonSerializer { get; } protected AbpDaprClientProxyOptions ClientProxyOptions { get; }
protected IRemoteServiceHttpClientAuthenticator ClientAuthenticator { get; } protected AbpWrapperOptions WrapperOptions { get; }
protected IJsonSerializer JsonSerializer { get; }
public ILogger<DynamicDaprClientProxyInterceptor<TService>> Logger { get; set; } protected IRemoteServiceHttpClientAuthenticator ClientAuthenticator { get; }
static DynamicDaprClientProxyInterceptor() public ILogger<DynamicDaprClientProxyInterceptor<TService>> Logger { get; set; }
{
MakeRequestAndGetResultAsyncMethod = typeof(DynamicDaprClientProxyInterceptor<TService>) static DynamicDaprClientProxyInterceptor()
.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance) {
.First(m => m.Name == nameof(MakeRequestAndGetResultAsync) && m.IsGenericMethodDefinition); MakeRequestAndGetResultAsyncMethod = typeof(DynamicDaprClientProxyInterceptor<TService>)
} .GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
.First(m => m.Name == nameof(MakeRequestAndGetResultAsync) && m.IsGenericMethodDefinition);
public DynamicDaprClientProxyInterceptor( }
IDaprClientFactory daprClientFactory,
IOptions<AbpDaprClientProxyOptions> clientProxyOptions, public DynamicDaprClientProxyInterceptor(
IOptionsSnapshot<AbpDaprRemoteServiceOptions> remoteServiceOptions, IDaprClientFactory daprClientFactory,
IDaprApiDescriptionFinder apiDescriptionFinder, IOptions<AbpDaprClientProxyOptions> clientProxyOptions,
IJsonSerializer jsonSerializer, IOptionsSnapshot<AbpDaprRemoteServiceOptions> remoteServiceOptions,
IDynamicProxyHttpClientFactory dynamicProxyHttpClientFactory, IDaprApiDescriptionFinder apiDescriptionFinder,
IRemoteServiceHttpClientAuthenticator clientAuthenticator, IJsonSerializer jsonSerializer,
ICancellationTokenProvider cancellationTokenProvider, IDynamicProxyHttpClientFactory dynamicProxyHttpClientFactory,
ICorrelationIdProvider correlationIdProvider, IRemoteServiceHttpClientAuthenticator clientAuthenticator,
IOptions<AbpCorrelationIdOptions> correlationIdOptions, ICancellationTokenProvider cancellationTokenProvider,
ICurrentTenant currentTenant) ICorrelationIdProvider correlationIdProvider,
{ IOptions<AbpCorrelationIdOptions> correlationIdOptions,
DaprClientFactory = daprClientFactory; IOptions<AbpWrapperOptions> wrapperOptions,
CancellationTokenProvider = cancellationTokenProvider; ICurrentTenant currentTenant)
CorrelationIdProvider = correlationIdProvider; {
CurrentTenant = currentTenant; DaprClientFactory = daprClientFactory;
HttpClientFactory = dynamicProxyHttpClientFactory; CancellationTokenProvider = cancellationTokenProvider;
AbpCorrelationIdOptions = correlationIdOptions.Value; CorrelationIdProvider = correlationIdProvider;
ApiDescriptionFinder = apiDescriptionFinder; CurrentTenant = currentTenant;
JsonSerializer = jsonSerializer; HttpClientFactory = dynamicProxyHttpClientFactory;
ClientAuthenticator = clientAuthenticator; AbpCorrelationIdOptions = correlationIdOptions.Value;
ClientProxyOptions = clientProxyOptions.Value; ApiDescriptionFinder = apiDescriptionFinder;
AbpRemoteServiceOptions = remoteServiceOptions.Value; JsonSerializer = jsonSerializer;
ClientAuthenticator = clientAuthenticator;
Logger = NullLogger<DynamicDaprClientProxyInterceptor<TService>>.Instance; ClientProxyOptions = clientProxyOptions.Value;
} AbpRemoteServiceOptions = remoteServiceOptions.Value;
WrapperOptions = wrapperOptions.Value;
public override async Task InterceptAsync(IAbpMethodInvocation invocation)
{ Logger = NullLogger<DynamicDaprClientProxyInterceptor<TService>>.Instance;
if (invocation.Method.ReturnType.GenericTypeArguments.IsNullOrEmpty()) }
{
await MakeRequestAsync(invocation); public override async Task InterceptAsync(IAbpMethodInvocation invocation)
} {
else if (invocation.Method.ReturnType.GenericTypeArguments.IsNullOrEmpty())
{ {
var result = (Task)MakeRequestAndGetResultAsyncMethod await MakeRequestAsync(invocation);
.MakeGenericMethod(invocation.Method.ReturnType.GenericTypeArguments[0]) }
.Invoke(this, new object[] { invocation }); else
{
invocation.ReturnValue = await GetResultAsync( var result = (Task)MakeRequestAndGetResultAsyncMethod
result, .MakeGenericMethod(invocation.Method.ReturnType.GenericTypeArguments[0])
invocation.Method.ReturnType.GetGenericArguments()[0] .Invoke(this, new object[] { invocation });
);
} invocation.ReturnValue = await GetResultAsync(
} result,
invocation.Method.ReturnType.GetGenericArguments()[0]
private async Task<object> GetResultAsync(Task task, Type resultType) );
{ }
await task; }
return typeof(Task<>)
.MakeGenericType(resultType) private async Task<object> GetResultAsync(Task task, Type resultType)
.GetProperty(nameof(Task<object>.Result), BindingFlags.Instance | BindingFlags.Public) {
.GetValue(task); await task;
} return typeof(Task<>)
.MakeGenericType(resultType)
private async Task<T> MakeRequestAndGetResultAsync<T>(IAbpMethodInvocation invocation) .GetProperty(nameof(Task<object>.Result), BindingFlags.Instance | BindingFlags.Public)
{ .GetValue(task);
var responseContent = await MakeRequestAsync(invocation); }
if (typeof(T) == typeof(IRemoteStreamContent)) private async Task<T> MakeRequestAndGetResultAsync<T>(IAbpMethodInvocation invocation)
{ {
/* returning a class that holds a reference to response var response = await MakeRequestAsync(invocation);
* content just to be sure that GC does not dispose of var responseContent = response.Content;
* it before we finish doing our work with the stream */
return (T)(object)new RemoteStreamContent(await responseContent.ReadAsStreamAsync()) if (typeof(T) == typeof(IRemoteStreamContent))
{ {
ContentType = responseContent.Headers.ContentType?.ToString() /* returning a class that holds a reference to response
}; * content just to be sure that GC does not dispose of
} * it before we finish doing our work with the stream */
return (T)(object)new RemoteStreamContent(await responseContent.ReadAsStreamAsync())
var stringContent = await responseContent.ReadAsStringAsync(); {
if (typeof(T) == typeof(string)) ContentType = responseContent.Headers.ContentType?.ToString()
{ };
return (T)(object)stringContent; }
} var stringContent = await responseContent.ReadAsStringAsync();
if (stringContent.IsNullOrWhiteSpace()) if (stringContent.IsNullOrWhiteSpace())
{ {
return default; return default;
} }
return JsonSerializer.Deserialize<T>(stringContent); // 对于包装后的结果需要处理
} if (response.Headers.Contains(AbpHttpWrapConsts.AbpWrapResult))
{
private async Task<HttpContent> MakeRequestAsync(IAbpMethodInvocation invocation) var wrapResult = JsonSerializer.Deserialize<WrapResult<T>>(stringContent);
{
var clientConfig = ClientProxyOptions.DaprClientProxies.GetOrDefault(typeof(TService)) ?? throw new AbpException($"Could not get DynamicDaprClientProxyConfig for {typeof(TService).FullName}."); if (!string.Equals(wrapResult.Code, WrapperOptions.CodeWithSuccess))
var remoteServiceConfig = AbpRemoteServiceOptions.RemoteServices.GetConfigurationOrDefault(clientConfig.RemoteServiceName); {
var errorInfo = new RemoteServiceErrorInfo(
// 遵循远端 api/abp/api-definition wrapResult.Message,
var action = await ApiDescriptionFinder.FindActionAsync( wrapResult.Details,
clientConfig.RemoteServiceName, wrapResult.Code);
remoteServiceConfig.AppId, throw new AbpRemoteCallException(errorInfo)
typeof(TService), {
invocation.Method HttpStatusCode = (int)WrapperOptions.HttpStatusCode
); };
}
var apiVersion = GetApiVersionInfo(action);
if (typeof(T) == typeof(string))
// See: https://docs.dapr.io/reference/api/service_invocation_api/#examples {
// 需要合并端点作为dapr远程调用的方法名称 return (T)(object)wrapResult.Result;
var methodName = UrlBuilder.GenerateUrlWithParameters(action, invocation.ArgumentsDictionary, apiVersion); }
var daprClient = DaprClientFactory.CreateClient(clientConfig.RemoteServiceName); return wrapResult.Result;
var requestMessage = daprClient.CreateInvokeMethodRequest( }
action.GetHttpMethod(),
remoteServiceConfig.AppId, if (typeof(T) == typeof(string))
methodName); {
return (T)(object)stringContent;
requestMessage.Content = RequestPayloadBuilder.BuildContent(action, invocation.ArgumentsDictionary, JsonSerializer, apiVersion); }
AddHeaders(invocation, action, requestMessage, apiVersion); return JsonSerializer.Deserialize<T>(stringContent);
}
var httpClient = HttpClientFactory.Create(AbpDaprClientModule.DaprHttpClient);
await ClientAuthenticator.Authenticate( private async Task<HttpResponseMessage> MakeRequestAsync(IAbpMethodInvocation invocation)
new RemoteServiceHttpClientAuthenticateContext( {
httpClient, var clientConfig = ClientProxyOptions.DaprClientProxies.GetOrDefault(typeof(TService)) ?? throw new AbpException($"Could not get DynamicDaprClientProxyConfig for {typeof(TService).FullName}.");
requestMessage, var remoteServiceConfig = AbpRemoteServiceOptions.RemoteServices.GetConfigurationOrDefault(clientConfig.RemoteServiceName);
remoteServiceConfig,
clientConfig.RemoteServiceName // 遵循远端 api/abp/api-definition
) var action = await ApiDescriptionFinder.FindActionAsync(
); clientConfig.RemoteServiceName,
// 其他库可能将授权标头写入到HttpClient中 remoteServiceConfig.AppId,
if (requestMessage.Headers.Authorization == null && typeof(TService),
httpClient.DefaultRequestHeaders.Authorization != null) invocation.Method
{ );
requestMessage.Headers.Authorization = httpClient.DefaultRequestHeaders.Authorization;
} var apiVersion = GetApiVersionInfo(action);
var response = await daprClient.InvokeMethodWithResponseAsync(requestMessage, GetCancellationToken()); // See: https://docs.dapr.io/reference/api/service_invocation_api/#examples
// 需要合并端点作为dapr远程调用的方法名称
if (!response.IsSuccessStatusCode) var methodName = UrlBuilder.GenerateUrlWithParameters(action, invocation.ArgumentsDictionary, apiVersion);
{
await ThrowExceptionForResponseAsync(response); var daprClient = DaprClientFactory.CreateClient(clientConfig.RemoteServiceName);
} var requestMessage = daprClient.CreateInvokeMethodRequest(
action.GetHttpMethod(),
return response.Content; remoteServiceConfig.AppId,
} methodName);
private ApiVersionInfo GetApiVersionInfo(ActionApiDescriptionModel action) requestMessage.Content = RequestPayloadBuilder.BuildContent(action, invocation.ArgumentsDictionary, JsonSerializer, apiVersion);
{
var apiVersion = FindBestApiVersion(action); AddHeaders(invocation, action, requestMessage, apiVersion);
//TODO: Make names configurable? var httpClient = HttpClientFactory.Create(AbpDaprClientModule.DaprHttpClient);
var versionParam = action.Parameters.FirstOrDefault(p => p.Name == "apiVersion" && p.BindingSourceId == ParameterBindingSources.Path) ?? await ClientAuthenticator.Authenticate(
action.Parameters.FirstOrDefault(p => p.Name == "api-version" && p.BindingSourceId == ParameterBindingSources.Query); new RemoteServiceHttpClientAuthenticateContext(
httpClient,
return new ApiVersionInfo(versionParam?.BindingSourceId, apiVersion); requestMessage,
} remoteServiceConfig,
clientConfig.RemoteServiceName
private string FindBestApiVersion(ActionApiDescriptionModel action) )
{ );
var configuredVersion = GetConfiguredApiVersion(); // 其他库可能将授权标头写入到HttpClient中
if (requestMessage.Headers.Authorization == null &&
if (action.SupportedVersions.IsNullOrEmpty()) httpClient.DefaultRequestHeaders.Authorization != null)
{ {
return configuredVersion ?? "1.0"; requestMessage.Headers.Authorization = httpClient.DefaultRequestHeaders.Authorization;
} }
if (action.SupportedVersions.Contains(configuredVersion)) var response = await daprClient.InvokeMethodWithResponseAsync(requestMessage, GetCancellationToken());
{
return configuredVersion; if (!response.IsSuccessStatusCode)
} {
await ThrowExceptionForResponseAsync(response);
return action.SupportedVersions.Last(); //TODO: Ensure to get the latest version! }
}
return response;
protected virtual void AddHeaders( }
IAbpMethodInvocation invocation,
ActionApiDescriptionModel action, private ApiVersionInfo GetApiVersionInfo(ActionApiDescriptionModel action)
HttpRequestMessage requestMessage, {
ApiVersionInfo apiVersion) var apiVersion = FindBestApiVersion(action);
{
//API Version //TODO: Make names configurable?
if (!apiVersion.Version.IsNullOrEmpty()) var versionParam = action.Parameters.FirstOrDefault(p => p.Name == "apiVersion" && p.BindingSourceId == ParameterBindingSources.Path) ??
{ action.Parameters.FirstOrDefault(p => p.Name == "api-version" && p.BindingSourceId == ParameterBindingSources.Query);
//TODO: What about other media types?
requestMessage.Headers.Add("accept", $"{MimeTypes.Text.Plain}; v={apiVersion.Version}"); return new ApiVersionInfo(versionParam?.BindingSourceId, apiVersion);
requestMessage.Headers.Add("accept", $"{MimeTypes.Application.Json}; v={apiVersion.Version}"); }
requestMessage.Headers.Add("api-version", apiVersion.Version);
} private string FindBestApiVersion(ActionApiDescriptionModel action)
{
//Header parameters var configuredVersion = GetConfiguredApiVersion();
var headers = action.Parameters.Where(p => p.BindingSourceId == ParameterBindingSources.Header).ToArray();
foreach (var headerParameter in headers) if (action.SupportedVersions.IsNullOrEmpty())
{ {
var value = HttpActionParameterHelper.FindParameterValue(invocation.ArgumentsDictionary, headerParameter); return configuredVersion ?? "1.0";
if (value != null) }
{
requestMessage.Headers.Add(headerParameter.Name, value.ToString()); if (action.SupportedVersions.Contains(configuredVersion))
} {
} return configuredVersion;
}
//CorrelationId
requestMessage.Headers.Add(AbpCorrelationIdOptions.HttpHeaderName, CorrelationIdProvider.Get()); return action.SupportedVersions.Last(); //TODO: Ensure to get the latest version!
}
//TenantId
if (CurrentTenant.Id.HasValue) protected virtual void AddHeaders(
{ IAbpMethodInvocation invocation,
//TODO: Use AbpAspNetCoreMultiTenancyOptions to get the key ActionApiDescriptionModel action,
requestMessage.Headers.Add(TenantResolverConsts.DefaultTenantKey, CurrentTenant.Id.Value.ToString()); HttpRequestMessage requestMessage,
} ApiVersionInfo apiVersion)
{
//Culture //API Version
//TODO: Is that the way we want? Couldn't send the culture (not ui culture) if (!apiVersion.Version.IsNullOrEmpty())
var currentCulture = CultureInfo.CurrentUICulture.Name ?? CultureInfo.CurrentCulture.Name; {
if (!currentCulture.IsNullOrEmpty()) //TODO: What about other media types?
{ requestMessage.Headers.Add("accept", $"{MimeTypes.Text.Plain}; v={apiVersion.Version}");
requestMessage.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(currentCulture)); requestMessage.Headers.Add("accept", $"{MimeTypes.Application.Json}; v={apiVersion.Version}");
} requestMessage.Headers.Add("api-version", apiVersion.Version);
}
//X-Requested-With
requestMessage.Headers.Add("X-Requested-With", "XMLHttpRequest"); //Header parameters
} var headers = action.Parameters.Where(p => p.BindingSourceId == ParameterBindingSources.Header).ToArray();
foreach (var headerParameter in headers)
private string GetConfiguredApiVersion() {
{ var value = HttpActionParameterHelper.FindParameterValue(invocation.ArgumentsDictionary, headerParameter);
var clientConfig = ClientProxyOptions.DaprClientProxies.GetOrDefault(typeof(TService)) if (value != null)
?? throw new AbpException($"Could not get DynamicDaprClientProxyConfig for {typeof(TService).FullName}."); {
requestMessage.Headers.Add(headerParameter.Name, value.ToString());
return AbpRemoteServiceOptions.RemoteServices.GetOrDefault(clientConfig.RemoteServiceName)?.Version }
?? AbpRemoteServiceOptions.RemoteServices.Default?.Version; }
}
//CorrelationId
private async Task ThrowExceptionForResponseAsync(HttpResponseMessage response) requestMessage.Headers.Add(AbpCorrelationIdOptions.HttpHeaderName, CorrelationIdProvider.Get());
{
if (response.Headers.Contains(AbpHttpConsts.AbpErrorFormat)) //TenantId
{ if (CurrentTenant.Id.HasValue)
var errorResponse = JsonSerializer.Deserialize<RemoteServiceErrorResponse>( {
await response.Content.ReadAsStringAsync() //TODO: Use AbpAspNetCoreMultiTenancyOptions to get the key
); requestMessage.Headers.Add(TenantResolverConsts.DefaultTenantKey, CurrentTenant.Id.Value.ToString());
}
throw new AbpRemoteCallException(errorResponse.Error)
{ //Culture
HttpStatusCode = (int)response.StatusCode //TODO: Is that the way we want? Couldn't send the culture (not ui culture)
}; var currentCulture = CultureInfo.CurrentUICulture.Name ?? CultureInfo.CurrentCulture.Name;
} if (!currentCulture.IsNullOrEmpty())
{
throw new AbpRemoteCallException( requestMessage.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(currentCulture));
new RemoteServiceErrorInfo }
{
Message = response.ReasonPhrase, //X-Requested-With
Code = response.StatusCode.ToString() requestMessage.Headers.Add("X-Requested-With", "XMLHttpRequest");
} }
)
{ private string GetConfiguredApiVersion()
HttpStatusCode = (int)response.StatusCode {
}; var clientConfig = ClientProxyOptions.DaprClientProxies.GetOrDefault(typeof(TService))
} ?? throw new AbpException($"Could not get DynamicDaprClientProxyConfig for {typeof(TService).FullName}.");
protected virtual CancellationToken GetCancellationToken() return AbpRemoteServiceOptions.RemoteServices.GetOrDefault(clientConfig.RemoteServiceName)?.Version
{ ?? AbpRemoteServiceOptions.RemoteServices.Default?.Version;
return CancellationTokenProvider.Token; }
}
} private async Task ThrowExceptionForResponseAsync(HttpResponseMessage response)
} {
if (response.Headers.Contains(AbpHttpConsts.AbpErrorFormat))
{
var errorResponse = JsonSerializer.Deserialize<RemoteServiceErrorResponse>(
await response.Content.ReadAsStringAsync()
);
throw new AbpRemoteCallException(errorResponse.Error)
{
HttpStatusCode = (int)response.StatusCode
};
}
throw new AbpRemoteCallException(
new RemoteServiceErrorInfo
{
Message = response.ReasonPhrase,
Code = response.StatusCode.ToString()
}
)
{
HttpStatusCode = (int)response.StatusCode
};
}
protected virtual CancellationToken GetCancellationToken()
{
return CancellationTokenProvider.Token;
}
}
}

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

@ -41,7 +41,7 @@ namespace LINGYUN.Abp.AspNetCore.Mvc.Wrapper
mvcOptions.Filters.AddService(typeof(AbpWrapResultFilter)); mvcOptions.Filters.AddService(typeof(AbpWrapResultFilter));
}); });
Configure<AbpAspNetCoreMvcWrapperOptions>(options => Configure<AbpWrapperOptions>(options =>
{ {
// 即使重写端点也不包装返回结果 // 即使重写端点也不包装返回结果
// api/abp/api-definition // api/abp/api-definition

70
aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/AbpAspNetCoreMvcWrapperOptions.cs

@ -1,70 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net;
using Volo.Abp.Collections;
namespace LINGYUN.Abp.AspNetCore.Mvc.Wrapper
{
public class AbpAspNetCoreMvcWrapperOptions
{
/// <summary>
/// 是否启用包装器
/// </summary>
public bool IsEnabled { get; set; }
/// <summary>
/// 资源有效时返回代码
/// 默认:0
/// </summary>
public string CodeWithFound { get; set; }
/// <summary>
/// 资源为空时返回代码
/// 默认:404
/// </summary>
public Func<IServiceProvider, string> CodeWithEmptyResult { get; set; }
/// <summary>
/// 资源为空时返回错误消息
/// </summary>
public Func<IServiceProvider, string> MessageWithEmptyResult { get; set; }
/// <summary>
/// 包装后的返回状态码
/// 默认:200 HttpStatusCode.OK
/// </summary>
public HttpStatusCode HttpStatusCode { get; set; }
/// <summary>
/// 忽略Url开头类型
/// </summary>
public IList<string> IgnorePrefixUrls { get; }
/// <summary>
/// 忽略指定命名空间
/// </summary>
public IList<string> IgnoreNamespaces { get; }
/// <summary>
/// 忽略控制器
/// </summary>
public ITypeList IgnoreControllers { get; }
/// <summary>
/// 忽略返回值
/// </summary>
public ITypeList IgnoreReturnTypes { get; }
/// <summary>
/// 忽略异常
/// </summary>
public ITypeList<Exception> IgnoreExceptions { get; }
public AbpAspNetCoreMvcWrapperOptions()
{
CodeWithFound = "0";
HttpStatusCode = HttpStatusCode.OK;
IgnorePrefixUrls = new List<string>();
IgnoreNamespaces = new List<string>();
IgnoreControllers = new TypeList();
IgnoreReturnTypes = new TypeList();
IgnoreExceptions = new TypeList<Exception>();
CodeWithEmptyResult = (_) => "404";
MessageWithEmptyResult = (_) => "Not Found";
}
}
}

4
aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/ExceptionHandling/AbpExceptionPageWrapResultFilter.cs

@ -30,7 +30,7 @@ namespace LINGYUN.Abp.AspNetCore.Mvc.Wrapper.ExceptionHandling
return; return;
} }
var wrapResultOptions = context.GetRequiredService<IOptions<AbpAspNetCoreMvcWrapperOptions>>().Value; var wrapOptions = context.GetRequiredService<IOptions<AbpWrapperOptions>>().Value;
var exceptionHandlingOptions = context.GetRequiredService<IOptions<AbpExceptionHandlingOptions>>().Value; var exceptionHandlingOptions = context.GetRequiredService<IOptions<AbpExceptionHandlingOptions>>().Value;
var exceptionToErrorInfoConverter = context.GetRequiredService<IExceptionToErrorInfoConverter>(); var exceptionToErrorInfoConverter = context.GetRequiredService<IExceptionToErrorInfoConverter>();
var remoteServiceErrorInfo = exceptionToErrorInfoConverter.Convert(context.Exception, exceptionHandlingOptions.SendExceptionsDetailsToClients); var remoteServiceErrorInfo = exceptionToErrorInfoConverter.Convert(context.Exception, exceptionHandlingOptions.SendExceptionsDetailsToClients);
@ -58,7 +58,7 @@ namespace LINGYUN.Abp.AspNetCore.Mvc.Wrapper.ExceptionHandling
context.Result = new ObjectResult(wrapResult); context.Result = new ObjectResult(wrapResult);
context.HttpContext.Response.Headers.Add(AbpHttpWrapConsts.AbpWrapResult, "true"); context.HttpContext.Response.Headers.Add(AbpHttpWrapConsts.AbpWrapResult, "true");
context.HttpContext.Response.StatusCode = (int)wrapResultOptions.HttpStatusCode; context.HttpContext.Response.StatusCode = (int)wrapOptions.HttpStatusCode;
context.Exception = null; //Handled! context.Exception = null; //Handled!
} }

4
aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/ExceptionHandling/AbpExceptionWrapResultFilter.cs

@ -32,7 +32,7 @@ namespace LINGYUN.Abp.AspNetCore.Mvc.Wrapper.ExceptionHandling
return; return;
} }
//TODO: Trigger an AbpExceptionHandled event or something like that. //TODO: Trigger an AbpExceptionHandled event or something like that.
var wrapResultOptions = context.GetRequiredService<IOptions<AbpAspNetCoreMvcWrapperOptions>>().Value; var wrapOptions = context.GetRequiredService<IOptions<AbpWrapperOptions>>().Value;
var exceptionHandlingOptions = context.GetRequiredService<IOptions<AbpExceptionHandlingOptions>>().Value; var exceptionHandlingOptions = context.GetRequiredService<IOptions<AbpExceptionHandlingOptions>>().Value;
var exceptionToErrorInfoConverter = context.GetRequiredService<IExceptionToErrorInfoConverter>(); var exceptionToErrorInfoConverter = context.GetRequiredService<IExceptionToErrorInfoConverter>();
var remoteServiceErrorInfo = exceptionToErrorInfoConverter.Convert(context.Exception, exceptionHandlingOptions.SendExceptionsDetailsToClients); var remoteServiceErrorInfo = exceptionToErrorInfoConverter.Convert(context.Exception, exceptionHandlingOptions.SendExceptionsDetailsToClients);
@ -61,7 +61,7 @@ namespace LINGYUN.Abp.AspNetCore.Mvc.Wrapper.ExceptionHandling
context.Result = new ObjectResult(wrapResult); context.Result = new ObjectResult(wrapResult);
context.HttpContext.Response.Headers.Add(AbpHttpWrapConsts.AbpWrapResult, "true"); context.HttpContext.Response.Headers.Add(AbpHttpWrapConsts.AbpWrapResult, "true");
context.HttpContext.Response.StatusCode = (int)wrapResultOptions.HttpStatusCode; context.HttpContext.Response.StatusCode = (int)wrapOptions.HttpStatusCode;
context.Exception = null; //Handled! context.Exception = null; //Handled!
} }

1
aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/Filters/AbpWrapResultFilter.cs

@ -1,4 +1,5 @@
using LINGYUN.Abp.AspNetCore.Mvc.Wrapper.Wraping; using LINGYUN.Abp.AspNetCore.Mvc.Wrapper.Wraping;
using LINGYUN.Abp.Wrapper;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc;

6
aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/WrapResultChecker.cs

@ -6,18 +6,16 @@ using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using System; using System;
using System.Linq; using System.Linq;
using System.Reflection;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Http;
using Volo.Abp.Threading; using Volo.Abp.Threading;
namespace LINGYUN.Abp.AspNetCore.Mvc.Wrapper namespace LINGYUN.Abp.AspNetCore.Mvc.Wrapper
{ {
public class WrapResultChecker : IWrapResultChecker, ISingletonDependency public class WrapResultChecker : IWrapResultChecker, ISingletonDependency
{ {
protected AbpAspNetCoreMvcWrapperOptions Options { get; } protected AbpWrapperOptions Options { get; }
public WrapResultChecker(IOptionsMonitor<AbpAspNetCoreMvcWrapperOptions> optionsMonitor) public WrapResultChecker(IOptionsMonitor<AbpWrapperOptions> optionsMonitor)
{ {
Options = optionsMonitor.CurrentValue; Options = optionsMonitor.CurrentValue;
} }

2
aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/Wraping/EmptyActionResultWrapper.cs

@ -10,7 +10,7 @@ namespace LINGYUN.Abp.AspNetCore.Mvc.Wrapper.Wraping
{ {
public void Wrap(FilterContext context) public void Wrap(FilterContext context)
{ {
var options = context.GetRequiredService<IOptions<AbpAspNetCoreMvcWrapperOptions>>().Value; var options = context.GetRequiredService<IOptions<AbpWrapperOptions>>().Value;
var code = options.CodeWithEmptyResult(context.HttpContext.RequestServices); var code = options.CodeWithEmptyResult(context.HttpContext.RequestServices);
var message = options.MessageWithEmptyResult(context.HttpContext.RequestServices); var message = options.MessageWithEmptyResult(context.HttpContext.RequestServices);
switch (context) switch (context)

4
aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/Wraping/JsonActionResultWrapper.cs

@ -31,9 +31,9 @@ namespace LINGYUN.Abp.AspNetCore.Mvc.Wrapper.Wraping
if (!(jsonResult.Value is WrapResult)) if (!(jsonResult.Value is WrapResult))
{ {
var options = context.GetRequiredService<IOptions<AbpAspNetCoreMvcWrapperOptions>>().Value; var options = context.GetRequiredService<IOptions<AbpWrapperOptions>>().Value;
jsonResult.Value = new WrapResult(options.CodeWithFound, jsonResult.Value); jsonResult.Value = new WrapResult(options.CodeWithSuccess, jsonResult.Value);
} }
} }
} }

12
aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/Wraping/ObjectActionResultWrapper.cs

@ -31,18 +31,18 @@ namespace LINGYUN.Abp.AspNetCore.Mvc.Wrapper.Wraping
if (!(objectResult.Value is WrapResult)) if (!(objectResult.Value is WrapResult))
{ {
var options = context.GetRequiredService<IOptions<AbpAspNetCoreMvcWrapperOptions>>().Value; var options = context.GetRequiredService<IOptions<AbpWrapperOptions>>().Value;
if (objectResult.Value != null) if (objectResult.Value == null && options.ErrorWithEmptyResult)
{
objectResult.Value = new WrapResult(options.CodeWithFound, objectResult.Value);
}
else
{ {
var code = options.CodeWithEmptyResult(context.HttpContext.RequestServices); var code = options.CodeWithEmptyResult(context.HttpContext.RequestServices);
var message = options.MessageWithEmptyResult(context.HttpContext.RequestServices); var message = options.MessageWithEmptyResult(context.HttpContext.RequestServices);
objectResult.Value = new WrapResult(code, message); objectResult.Value = new WrapResult(code, message);
} }
else
{
objectResult.Value = new WrapResult(options.CodeWithSuccess, objectResult.Value);
}
objectResult.DeclaredType = typeof(WrapResult); objectResult.DeclaredType = typeof(WrapResult);
} }

3
aspnet-core/tests/LINGYUN.Abp.AspNetCore.Mvc.Tests/LINGYUN/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs

@ -2,6 +2,7 @@
using LINGYUN.Abp.AspNetCore.Mvc.Localization; using LINGYUN.Abp.AspNetCore.Mvc.Localization;
using LINGYUN.Abp.AspNetCore.Mvc.Results; using LINGYUN.Abp.AspNetCore.Mvc.Results;
using LINGYUN.Abp.AspNetCore.Mvc.Wrapper; using LINGYUN.Abp.AspNetCore.Mvc.Wrapper;
using LINGYUN.Abp.Wrapper;
using Localization.Resources.AbpUi; using Localization.Resources.AbpUi;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
@ -70,7 +71,7 @@ namespace LINGYUN.Abp.AspNetCore.Mvc
{ {
}); });
Configure<AbpAspNetCoreMvcWrapperOptions>(options => Configure<AbpWrapperOptions>(options =>
{ {
options.IsEnabled = true; options.IsEnabled = true;

2
aspnet-core/tests/LINGYUN.Abp.AspNetCore.Mvc.Tests/LINGYUN/Abp/AspNetCore/Mvc/Results/WrapResultController_Tests.cs

@ -86,7 +86,7 @@ namespace LINGYUN.Abp.AspNetCore.Mvc.Results
public async Task Should_Return_Wrap_Result_For_Empty_Object_Return_Value() public async Task Should_Return_Wrap_Result_For_Empty_Object_Return_Value()
{ {
var result = await GetResponseAsObjectAsync<WrapResult<TestResultObject>>("/api/wrap-result-test/wrap-empty"); var result = await GetResponseAsObjectAsync<WrapResult<TestResultObject>>("/api/wrap-result-test/wrap-empty");
result.Code.ShouldBe("404"); result.Code.ShouldBe("0");
result.Result.ShouldBeNull(); result.Result.ShouldBeNull();
} }

2
aspnet-core/tests/LINGYUN.Abp.Dapr.AspNetCore.TestHost/LINGYUN.Abp.Dapr.AspNetCore.TestHost.csproj

@ -11,7 +11,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\modules\common\LINGYUN.Abp.Wrapper\LINGYUN.Abp.Wrapper.csproj" />
<ProjectReference Include="..\..\modules\dapr\LINGYUN.Abp.Dapr.Actors.AspNetCore\LINGYUN.Abp.Dapr.Actors.AspNetCore.csproj" /> <ProjectReference Include="..\..\modules\dapr\LINGYUN.Abp.Dapr.Actors.AspNetCore\LINGYUN.Abp.Dapr.Actors.AspNetCore.csproj" />
<ProjectReference Include="..\..\modules\mvc\LINGYUN.Abp.AspNetCore.Mvc.Wrapper\LINGYUN.Abp.AspNetCore.Mvc.Wrapper.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.Dapr.Tests\LINGYUN.Abp.Dapr.Tests.csproj" /> <ProjectReference Include="..\LINGYUN.Abp.Dapr.Tests\LINGYUN.Abp.Dapr.Tests.csproj" />
</ItemGroup> </ItemGroup>

90
aspnet-core/tests/LINGYUN.Abp.Dapr.AspNetCore.TestHost/LINGYUN/Abp/Dapr/AbpDaprAspNetCoreTestHostModule.cs

@ -1,39 +1,51 @@
using LINGYUN.Abp.Dapr.Actors.AspNetCore; using LINGYUN.Abp.AspNetCore.Mvc.Wrapper;
using Microsoft.AspNetCore.Builder; using LINGYUN.Abp.Dapr.Actors.AspNetCore;
using Microsoft.Extensions.DependencyInjection; using LINGYUN.Abp.Dapr.ServiceInvocation;
using Volo.Abp; using LINGYUN.Abp.Wrapper;
using Volo.Abp.AspNetCore.Mvc; using Microsoft.AspNetCore.Builder;
using Volo.Abp.Modularity; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp;
namespace LINGYUN.Abp.Dapr using Volo.Abp.Application.Dtos;
{ using Volo.Abp.AspNetCore.Mvc;
[DependsOn( using Volo.Abp.Modularity;
typeof(AbpAspNetCoreMvcModule),
typeof(AbpDaprActorsAspNetCoreModule) namespace LINGYUN.Abp.Dapr
)] {
public class AbpDaprAspNetCoreTestHostModule : AbpModule [DependsOn(
{ typeof(AbpDaprActorsAspNetCoreModule),
public override void PreConfigureServices(ServiceConfigurationContext context) typeof(AbpAspNetCoreMvcWrapperModule)
{ )]
Configure<IMvcBuilder>(builder => public class AbpDaprAspNetCoreTestHostModule : AbpModule
{ {
builder.AddApplicationPart(typeof(AbpDaprAspNetCoreTestHostModule).Assembly); public override void PreConfigureServices(ServiceConfigurationContext context)
}); {
} Configure<IMvcBuilder>(builder =>
{
public override void ConfigureServices(ServiceConfigurationContext context) builder.AddApplicationPart(typeof(AbpDaprAspNetCoreTestHostModule).Assembly);
{ });
var hostingEnvironment = context.Services.GetHostingEnvironment(); }
var configuration = context.Services.GetConfiguration();
} public override void ConfigureServices(ServiceConfigurationContext context)
{
public override void OnApplicationInitialization(ApplicationInitializationContext context) var hostingEnvironment = context.Services.GetHostingEnvironment();
{ var configuration = context.Services.GetConfiguration();
var app = context.GetApplicationBuilder();
Configure<AbpWrapperOptions>(options =>
app.UseRouting(); {
app.UseAuditing(); options.IsEnabled = true;
app.UseConfiguredEndpoints();
} options.IgnoreReturnTypes.TryAdd<NameValue>();
} options.IgnoreReturnTypes.TryAdd<ListResultDto<NameValue>>();
} });
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
app.UseRouting();
app.UseAuditing();
app.UseConfiguredEndpoints();
}
}
}

94
aspnet-core/tests/LINGYUN.Abp.Dapr.AspNetCore.TestHost/LINGYUN/Abp/Dapr/ServiceInvocation/TestAppService.cs

@ -1,41 +1,53 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Dtos;
using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc;
namespace LINGYUN.Abp.Dapr.ServiceInvocation namespace LINGYUN.Abp.Dapr.ServiceInvocation
{ {
[RemoteService(Name = "TestDapr")] [RemoteService(Name = "TestDapr")]
[Route("api/dapr/test")] [Route("api/dapr/test")]
public class TestAppService : AbpController, ITestAppService public class TestAppService : AbpController, ITestAppService
{ {
private static int _inctement; private static int _inctement;
private readonly List<NameValue> _cache = new List<NameValue> private readonly List<NameValue> _cache = new List<NameValue>
{ {
new NameValue("name1", "value1"), new NameValue("name1", "value1"),
new NameValue("name2", "value2"), new NameValue("name2", "value2"),
new NameValue("name3", "value3"), new NameValue("name3", "value3"),
new NameValue("name4", "value4"), new NameValue("name4", "value4"),
new NameValue("name5", "value5") new NameValue("name5", "value5")
}; };
[HttpGet] [HttpGet]
public Task<ListResultDto<NameValue>> GetAsync() public Task<ListResultDto<NameValue>> GetAsync()
{ {
return Task.FromResult(new ListResultDto<NameValue>(_cache)); return Task.FromResult(new ListResultDto<NameValue>(_cache));
} }
[HttpPut] [HttpPut]
public Task<NameValue> UpdateAsync() public Task<NameValue> UpdateAsync()
{ {
Interlocked.Increment(ref _inctement); Interlocked.Increment(ref _inctement);
_cache[0].Value = $"value:updated:{_inctement}"; _cache[0].Value = $"value:updated:{_inctement}";
return Task.FromResult(_cache[0]); return Task.FromResult(_cache[0]);
} }
}
} [HttpGet]
[Route("{name}")]
public Task<TestNeedWrapObject> GetWrapedAsync(string name)
{
var obj = new TestNeedWrapObject
{
Name = name
};
return Task.FromResult(obj);
}
}
}

74
aspnet-core/tests/LINGYUN.Abp.Dapr.Client.Tests/LINGYUN/Abp/Dapr/Client/Tests/TestAppServiceTests.cs

@ -1,33 +1,41 @@
using LINGYUN.Abp.Dapr.ServiceInvocation; using LINGYUN.Abp.Dapr.ServiceInvocation;
using Shouldly; using Shouldly;
using System.Threading.Tasks; using System.Threading.Tasks;
using Xunit; using Xunit;
namespace LINGYUN.Abp.Dapr.Client.Tests namespace LINGYUN.Abp.Dapr.Client.Tests
{ {
public class TestAppServiceTests : AbpDaptClientTestBase public class TestAppServiceTests : AbpDaptClientTestBase
{ {
private readonly ITestAppService _service; private readonly ITestAppService _service;
public TestAppServiceTests() public TestAppServiceTests()
{ {
_service = GetRequiredService<ITestAppService>(); _service = GetRequiredService<ITestAppService>();
} }
[Fact] [Fact]
public async Task Get_Result_Items_Count_Should_5() public async Task Get_Result_Items_Count_Should_5()
{ {
var result = await _service.GetAsync(); var result = await _service.GetAsync();
result.Items.Count.ShouldBe(5); result.Items.Count.ShouldBe(5);
} }
[Fact] [Fact]
public async Task Update_Result_Value_Should_Value_Updated_1() public async Task Should_Get_Wraped_Object()
{ {
var result = await _service.UpdateAsync(); var result = await _service.GetWrapedAsync("Test");
result.Value.ShouldBe("value:updated:1"); result.Name.ShouldBe("Test");
} }
}
} [Fact]
public async Task Update_Result_Value_Should_Value_Updated_1()
{
var result = await _service.UpdateAsync();
result.Value.ShouldBe("value:updated:1");
}
}
}

23
aspnet-core/tests/LINGYUN.Abp.Dapr.Tests/LINGYUN/Abp/Dapr/AbpDaprTestModule.cs

@ -1,11 +1,12 @@
using Volo.Abp.Application; using Volo.Abp.Application;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Dapr namespace LINGYUN.Abp.Dapr
{ {
[DependsOn( [DependsOn(
typeof(AbpDddApplicationContractsModule))] typeof(AbpDddApplicationContractsModule))]
public class AbpDaprTestModule : AbpModule public class AbpDaprTestModule : AbpModule
{ {
}
} }
}

30
aspnet-core/tests/LINGYUN.Abp.Dapr.Tests/LINGYUN/Abp/Dapr/ServiceInvocation/ITestAppService.cs

@ -1,14 +1,16 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services; using Volo.Abp.Application.Services;
namespace LINGYUN.Abp.Dapr.ServiceInvocation namespace LINGYUN.Abp.Dapr.ServiceInvocation
{ {
public interface ITestAppService : IApplicationService public interface ITestAppService : IApplicationService
{ {
Task<ListResultDto<NameValue>> GetAsync(); Task<ListResultDto<NameValue>> GetAsync();
Task<NameValue> UpdateAsync(); Task<NameValue> UpdateAsync();
}
} Task<TestNeedWrapObject> GetWrapedAsync(string name);
}
}

7
aspnet-core/tests/LINGYUN.Abp.Dapr.Tests/LINGYUN/Abp/Dapr/TestNeedWrapObject.cs

@ -0,0 +1,7 @@
namespace LINGYUN.Abp.Dapr
{
public class TestNeedWrapObject
{
public string Name { get; set; }
}
}
Loading…
Cancel
Save