Browse Source

Merge pull request #11081 from abpframework/IObjectToPath

Add `IObjectToPath`.
pull/11087/head
liangshiwei 4 years ago
committed by GitHub
parent
commit
89c4598fc6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/AbpHttpClientProxyingOptions.cs
  2. 6
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyRequestPayloadBuilder.cs
  3. 59
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyUrlBuilder.cs
  4. 3
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/IObjectToFormData.cs
  5. 10
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/IObjectToPath.cs
  6. 3
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/IObjectToQueryString.cs
  7. 1
      framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpClientTestModule.cs
  8. 4
      framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/IRegularTestController.cs
  9. 16
      framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestController.cs
  10. 17
      framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs
  11. 3
      framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/TestObjectToFormData.cs
  12. 23
      framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/TestObjectToPath.cs
  13. 3
      framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/TestObjectToQueryString.cs

3
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/AbpHttpClientProxyingOptions.cs

@ -9,10 +9,13 @@ namespace Volo.Abp.Http.Client.ClientProxying
public Dictionary<Type, Type> FormDataConverts { get; set; }
public Dictionary<Type, Type> PathConverts { get; set; }
public AbpHttpClientProxyingOptions()
{
QueryStringConverts = new Dictionary<Type, Type>();
FormDataConverts = new Dictionary<Type, Type>();
PathConverts = new Dictionary<Type, Type>();
}
}
}

6
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyRequestPayloadBuilder.cs

@ -113,6 +113,8 @@ namespace Volo.Abp.Http.Client.ClientProxying
.Invoke(this, new object[]
{
scope.ServiceProvider.GetRequiredService(HttpClientProxyingOptions.FormDataConverts[value.GetType()]),
action,
parameter,
value
});
@ -168,9 +170,9 @@ namespace Volo.Abp.Http.Client.ClientProxying
return formData;
}
protected virtual async Task<List<KeyValuePair<string, HttpContent>>> ObjectToFormDataAsync<T>(IObjectToFormData<T> converter, T value)
protected virtual async Task<List<KeyValuePair<string, HttpContent>>> ObjectToFormDataAsync<T>(IObjectToFormData<T> converter, ActionApiDescriptionModel actionApiDescription, ParameterApiDescriptionModel parameterApiDescription, T value)
{
return await converter.ConvertAsync(value);
return await converter.ConvertAsync(actionApiDescription, parameterApiDescription, value);
}
}
}

59
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyUrlBuilder.cs

@ -21,11 +21,17 @@ namespace Volo.Abp.Http.Client.ClientProxying
{
protected static MethodInfo CallObjectToQueryStringAsyncMethod { get; }
protected static MethodInfo CallObjectToPathAsyncMethod { get; }
static ClientProxyUrlBuilder()
{
CallObjectToQueryStringAsyncMethod = typeof(ClientProxyUrlBuilder)
.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
.First(m => m.Name == nameof(ObjectToQueryStringAsync) && m.IsGenericMethodDefinition);
CallObjectToPathAsyncMethod = typeof(ClientProxyUrlBuilder)
.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
.First(m => m.Name == nameof(ObjectToPathAsync) && m.IsGenericMethodDefinition);
}
protected IServiceScopeFactory ServiceScopeFactory { get; }
@ -46,22 +52,22 @@ namespace Volo.Abp.Http.Client.ClientProxying
{
var urlBuilder = new StringBuilder(action.Url);
await ReplacePathVariablesAsync(urlBuilder, action.Parameters, methodArguments, apiVersion);
await AddQueryStringParametersAsync(urlBuilder, action.Parameters, methodArguments, apiVersion);
await ReplacePathVariablesAsync(urlBuilder, action, methodArguments, apiVersion);
await AddQueryStringParametersAsync(urlBuilder, action, methodArguments, apiVersion);
return urlBuilder.ToString();
}
}
protected virtual Task ReplacePathVariablesAsync(StringBuilder urlBuilder, IList<ParameterApiDescriptionModel> actionParameters, IReadOnlyDictionary<string, object> methodArguments, ApiVersionInfo apiVersion)
protected virtual async Task ReplacePathVariablesAsync(StringBuilder urlBuilder, ActionApiDescriptionModel action, IReadOnlyDictionary<string, object> methodArguments, ApiVersionInfo apiVersion)
{
var pathParameters = actionParameters
var pathParameters = action.Parameters
.Where(p => p.BindingSourceId == ParameterBindingSources.Path)
.ToArray();
if (!pathParameters.Any())
{
return Task.CompletedTask;
return;
}
if (pathParameters.Any(p => p.Name == "apiVersion"))
@ -81,7 +87,7 @@ namespace Volo.Abp.Http.Client.ClientProxying
}
else if (pathParameter.DefaultValue != null)
{
urlBuilder = urlBuilder.Replace($"{{{pathParameter.Name}}}", pathParameter.DefaultValue.ToString());
urlBuilder = urlBuilder.Replace($"{{{pathParameter.Name}}}", await ConvertValueToStringAsync(pathParameter.DefaultValue));
}
else
{
@ -90,16 +96,36 @@ namespace Volo.Abp.Http.Client.ClientProxying
}
else
{
urlBuilder = urlBuilder.Replace($"{{{pathParameter.Name}}}", value.ToString());
if (HttpClientProxyingOptions.PathConverts.ContainsKey(value.GetType()))
{
using (var scope = ServiceScopeFactory.CreateScope())
{
var path = await (Task<string>)CallObjectToPathAsyncMethod
.MakeGenericMethod(value.GetType())
.Invoke(this, new object[]
{
scope.ServiceProvider.GetRequiredService(HttpClientProxyingOptions.PathConverts[value.GetType()]),
action,
pathParameter,
value
});
if (path != null)
{
urlBuilder = urlBuilder.Replace($"{{{pathParameter.Name}}}", path);
continue;
}
}
}
urlBuilder = urlBuilder.Replace($"{{{pathParameter.Name}}}", await ConvertValueToStringAsync(value));
}
}
return Task.CompletedTask;
}
protected virtual async Task AddQueryStringParametersAsync(StringBuilder urlBuilder, IList<ParameterApiDescriptionModel> actionParameters, IReadOnlyDictionary<string, object> methodArguments, ApiVersionInfo apiVersion)
protected virtual async Task AddQueryStringParametersAsync(StringBuilder urlBuilder, ActionApiDescriptionModel action, IReadOnlyDictionary<string, object> methodArguments, ApiVersionInfo apiVersion)
{
var queryStringParameters = actionParameters
var queryStringParameters = action.Parameters
.Where(p => p.BindingSourceId.IsIn(ParameterBindingSources.ModelBinding, ParameterBindingSources.Query))
.ToArray();
@ -122,6 +148,8 @@ namespace Volo.Abp.Http.Client.ClientProxying
.Invoke(this, new object[]
{
scope.ServiceProvider.GetRequiredService(HttpClientProxyingOptions.QueryStringConverts[value.GetType()]),
action,
queryStringParameter,
value
});
@ -147,9 +175,14 @@ namespace Volo.Abp.Http.Client.ClientProxying
}
}
protected virtual async Task<string> ObjectToQueryStringAsync<T>(IObjectToQueryString<T> converter, T value)
protected virtual async Task<string> ObjectToQueryStringAsync<T>(IObjectToQueryString<T> converter, ActionApiDescriptionModel actionApiDescription, ParameterApiDescriptionModel parameterApiDescription, T value)
{
return await converter.ConvertAsync(actionApiDescription, parameterApiDescription, value);
}
protected virtual async Task<string> ObjectToPathAsync<T>(IObjectToPath<T> converter, ActionApiDescriptionModel actionApiDescription, ParameterApiDescriptionModel parameterApiDescription, T value)
{
return await converter.ConvertAsync(value);
return await converter.ConvertAsync(actionApiDescription, parameterApiDescription, value);
}
protected virtual async Task<bool> AddQueryStringParameterAsync(

3
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/IObjectToFormData.cs

@ -1,11 +1,12 @@
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Volo.Abp.Http.Modeling;
namespace Volo.Abp.Http.Client.ClientProxying
{
public interface IObjectToFormData<in TValue>
{
Task<List<KeyValuePair<string, HttpContent>>> ConvertAsync(TValue value);
Task<List<KeyValuePair<string, HttpContent>>> ConvertAsync(ActionApiDescriptionModel actionApiDescription, ParameterApiDescriptionModel parameterApiDescription, TValue value);
}
}

10
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/IObjectToPath.cs

@ -0,0 +1,10 @@
using System.Threading.Tasks;
using Volo.Abp.Http.Modeling;
namespace Volo.Abp.Http.Client.ClientProxying
{
public interface IObjectToPath<in TValue>
{
Task<string> ConvertAsync(ActionApiDescriptionModel actionApiDescription, ParameterApiDescriptionModel parameterApiDescription, TValue value);
}
}

3
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/IObjectToQueryString.cs

@ -1,9 +1,10 @@
using System.Threading.Tasks;
using Volo.Abp.Http.Modeling;
namespace Volo.Abp.Http.Client.ClientProxying
{
public interface IObjectToQueryString<in TValue>
{
Task<string> ConvertAsync(TValue value);
Task<string> ConvertAsync(ActionApiDescriptionModel actionApiDescription, ParameterApiDescriptionModel parameterApiDescription, TValue value);
}
}

1
framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpClientTestModule.cs

@ -59,6 +59,7 @@ namespace Volo.Abp.Http
{
options.QueryStringConverts.Add(typeof(List<GetParamsNameValue>), typeof(TestObjectToQueryString));
options.FormDataConverts.Add(typeof(List<GetParamsNameValue>), typeof(TestObjectToFormData));
options.PathConverts.Add(typeof(int), typeof(TestObjectToPath));
});
}
}

4
framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/IRegularTestController.cs

@ -26,6 +26,10 @@ namespace Volo.Abp.Http.DynamicProxying
Task<Car> GetObjectandIdAsync(int id, Car bodyValue);
Task<Car> GetObjectandFirstReleaseDateAsync(DateTime time, Car bodyValue);
Task<Car> GetObjectandCountAsync(int count, Car bodyValue);
Task<Car> GetObjectAndIdWithQueryAsync(int id, Car bodyValue);
Task<string> PutValueWithBodyAsync(string bodyValue);

16
framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestController.cs

@ -86,6 +86,22 @@ namespace Volo.Abp.Http.DynamicProxying
return Task.FromResult(bodyValue);
}
[HttpGet]
[Route("post-object-and-first-release-date-with-url/{time:datetime}")]
public Task<Car> GetObjectandFirstReleaseDateAsync(DateTime time, Car bodyValue)
{
bodyValue.FirstReleaseDate = time;
return Task.FromResult(bodyValue);
}
[HttpGet]
[Route("post-object-and-count-with-url/{count}")]
public Task<Car> GetObjectandCountAsync(int count, Car bodyValue)
{
bodyValue.Year = count;
return Task.FromResult(bodyValue);
}
[HttpGet]
[Route("post-object-and-id-with-url-and-query/{id}")]
public Task<Car> GetObjectAndIdWithQueryAsync(int id, Car bodyValue)

17
framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs

@ -124,6 +124,23 @@ namespace Volo.Abp.Http.DynamicProxying
result.Model.ShouldBe("Ford");
}
[Fact]
public async Task GetObjectandFirstReleaseDateAsync()
{
var time = DateTime.Now;
var result = await _controller.GetObjectandFirstReleaseDateAsync(time, new Car { Year = 1976, Model = "Ford", FirstReleaseDate = new DateTime(1976, 02, 22, 15, 0, 6, 22) });
result.FirstReleaseDate.ToUniversalTime().ShouldBe(time.ToUniversalTime());
result.Model.ShouldBe("Ford");
}
[Fact]
public async Task GetObjectandCountAsync()
{
var result = await _controller.GetObjectandCountAsync(-1, new Car { Year = 1976, Model = "Ford", FirstReleaseDate = new DateTime(1976, 02, 22, 15, 0, 6, 22) });
result.Year.ShouldBe(888);
result.Model.ShouldBe("Ford");
}
[Fact]
public async Task GetObjectAndIdWithQueryAsync()
{

3
framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/TestObjectToFormData.cs

@ -4,13 +4,14 @@ using System.Text;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Client.ClientProxying;
using Volo.Abp.Http.Modeling;
using Volo.Abp.TestApp.Application.Dto;
namespace Volo.Abp.Http.DynamicProxying
{
public class TestObjectToFormData : IObjectToFormData<List<GetParamsNameValue>>, ITransientDependency
{
public Task<List<KeyValuePair<string, HttpContent>>> ConvertAsync(List<GetParamsNameValue> values)
public Task<List<KeyValuePair<string, HttpContent>>> ConvertAsync(ActionApiDescriptionModel actionApiDescription, ParameterApiDescriptionModel parameterApiDescription, List<GetParamsNameValue> values)
{
if (values.IsNullOrEmpty())
{

23
framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/TestObjectToPath.cs

@ -0,0 +1,23 @@
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Client.ClientProxying;
using Volo.Abp.Http.Modeling;
namespace Volo.Abp.Http.DynamicProxying;
public class TestObjectToPath : IObjectToPath<int>, ITransientDependency
{
public Task<string> ConvertAsync(ActionApiDescriptionModel actionApiDescription, ParameterApiDescriptionModel parameterApiDescription, int value)
{
if (actionApiDescription.Name == nameof(IRegularTestController.GetObjectandCountAsync))
{
if (value <= 0)
{
value = 888;
}
return Task.FromResult(value.ToString());
}
return Task.FromResult<string>(null);
}
}

3
framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/TestObjectToQueryString.cs

@ -3,13 +3,14 @@ using System.Text;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Client.ClientProxying;
using Volo.Abp.Http.Modeling;
using Volo.Abp.TestApp.Application.Dto;
namespace Volo.Abp.Http.DynamicProxying
{
public class TestObjectToQueryString : IObjectToQueryString<List<GetParamsNameValue>>, ITransientDependency
{
public Task<string> ConvertAsync(List<GetParamsNameValue> values)
public Task<string> ConvertAsync(ActionApiDescriptionModel actionApiDescription, ParameterApiDescriptionModel parameterApiDescription, List<GetParamsNameValue> values)
{
if (values.IsNullOrEmpty())
{

Loading…
Cancel
Save