Browse Source

Implemented payload body.

pull/113/head
Halil İbrahim Kalkan 9 years ago
parent
commit
c8301f37c1
  1. 16
      src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs
  2. 27
      src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/HttpActionParameterHelper.cs
  3. 38
      src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/RequestPayloadBuilder.cs
  4. 42
      src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/UrlBuilder.cs
  5. 2
      src/Volo.Abp/Volo/Abp/Json/IJsonSerializer.cs
  6. 2
      test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/App/AppModule.cs
  7. 24
      test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/PersonAppServiceClientProxy_Tests.cs

16
src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs

@ -1,13 +1,16 @@
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Mime;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Volo.Abp.DependencyInjection;
using Volo.Abp.DynamicProxy;
using Volo.Abp.Json;
using Volo.Abp.Threading;
namespace Volo.Abp.Http.Client.DynamicProxying
@ -21,6 +24,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying
private readonly IDynamicProxyHttpClientFactory _httpClientFactory;
private readonly IApiDescriptionFinder _apiDescriptionFinder;
private readonly AbpHttpClientOptions _options;
private readonly IJsonSerializer _jsonSerializer;
static DynamicHttpProxyInterceptor()
{
@ -32,10 +36,12 @@ namespace Volo.Abp.Http.Client.DynamicProxying
public DynamicHttpProxyInterceptor(
IDynamicProxyHttpClientFactory httpClientFactory,
IOptions<AbpHttpClientOptions> options,
IApiDescriptionFinder apiDescriptionFinder)
IApiDescriptionFinder apiDescriptionFinder,
IJsonSerializer jsonSerializer)
{
_httpClientFactory = httpClientFactory;
_apiDescriptionFinder = apiDescriptionFinder;
_jsonSerializer = jsonSerializer;
_options = options.Value;
}
@ -81,10 +87,16 @@ namespace Volo.Abp.Http.Client.DynamicProxying
{
var proxyConfig = GetProxyConfig();
var actionApiDescription = await _apiDescriptionFinder.FindActionAsync(proxyConfig, invocation.Method);
var url = proxyConfig.BaseUrl + UrlBuilder.GenerateUrlWithParameters(actionApiDescription, invocation.ArgumentsDictionary);
var requestMessage = new HttpRequestMessage(actionApiDescription.GetHttpMethod(), url);
var body = RequestPayloadBuilder.GenerateBody(actionApiDescription, invocation.ArgumentsDictionary, _jsonSerializer);
if (body != null)
{
requestMessage.Content = new StringContent(body, Encoding.UTF8, "application/json"); //TODO: application/json to a constant
}
var response = await client.SendAsync(requestMessage);
if (!response.IsSuccessStatusCode)

27
src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/HttpActionParameterHelper.cs

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Http.Modeling;
using Volo.Abp.Reflection;
namespace Volo.Abp.Http.Client.DynamicProxying
{
internal static class HttpActionParameterHelper
{
public static object FindParameterValue(IReadOnlyDictionary<string, object> methodArguments, ParameterApiDescriptionModel apiParameter)
{
var value = methodArguments[apiParameter.NameOnMethod];
if (value == null)
{
return null;
}
if (apiParameter.Name == apiParameter.NameOnMethod)
{
return value;
}
return ReflectionHelper.GetValueByPath(value, value.GetType(), apiParameter.Name);
}
}
}

38
src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/RequestPayloadBuilder.cs

@ -0,0 +1,38 @@
using System.Collections.Generic;
using System.Linq;
using Volo.Abp.Http.Modeling;
using Volo.Abp.Json;
namespace Volo.Abp.Http.Client.DynamicProxying
{
public static class RequestPayloadBuilder
{
public static string GenerateBody(ActionApiDescriptionModel action, IReadOnlyDictionary<string, object> methodArguments, IJsonSerializer jsonSerializer)
{
var parameters = action
.Parameters
.Where(p => p.BindingSourceId == "Body")
.ToArray();
if (parameters.Length <= 0)
{
return null;
}
if (parameters.Length > 1)
{
throw new AbpException(
$"Only one complex type allowed as argument to a controller action that's binding source is 'Body'. But action on URL: {action.Url} contains more than one!"
);
}
var value = HttpActionParameterHelper.FindParameterValue(methodArguments, parameters[0]);
if (value == null)
{
return null;
}
return jsonSerializer.Serialize(value);
}
}
}

42
src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/UrlBuilder.cs

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using Volo.Abp.Http.Modeling;
using Volo.Abp.Reflection;
namespace Volo.Abp.Http.Client.DynamicProxying
{
@ -32,7 +31,26 @@ namespace Volo.Abp.Http.Client.DynamicProxying
foreach (var pathParameter in pathParameters)
{
urlBuilder = urlBuilder.Replace($"{{{pathParameter.Name}}}", FindParameterValue(methodArguments, pathParameter));
var value = HttpActionParameterHelper.FindParameterValue(methodArguments, pathParameter);
if (value == null)
{
if (pathParameter.IsOptional)
{
urlBuilder = urlBuilder.Replace($"{{{pathParameter.Name}}}", "");
}
else if (pathParameter.DefaultValue != null)
{
urlBuilder = urlBuilder.Replace($"{{{pathParameter.Name}}}", pathParameter.DefaultValue.ToString());
}
else
{
throw new AbpException($"Missing path parameter value for {pathParameter.Name} ({pathParameter.NameOnMethod})");
}
}
else
{
urlBuilder = urlBuilder.Replace($"{{{pathParameter.Name}}}", value.ToString());
}
}
}
@ -50,33 +68,17 @@ namespace Volo.Abp.Http.Client.DynamicProxying
var isFirstParam = true;
foreach (var queryStringParameter in queryStringParameters)
{
var value = FindParameterValue(methodArguments, queryStringParameter);
var value = HttpActionParameterHelper.FindParameterValue(methodArguments, queryStringParameter);
if (value == null)
{
continue;
}
urlBuilder.Append(isFirstParam ? "?" : "&");
urlBuilder.Append(queryStringParameter.Name + "=" + System.Net.WebUtility.UrlEncode(value));
urlBuilder.Append(queryStringParameter.Name + "=" + System.Net.WebUtility.UrlEncode(value.ToString()));
isFirstParam = false;
}
}
private static string FindParameterValue(IReadOnlyDictionary<string, object> methodArguments, ParameterApiDescriptionModel apiParameter)
{
var value = methodArguments[apiParameter.NameOnMethod];
if (value == null)
{
return null;
}
if (apiParameter.Name == apiParameter.NameOnMethod)
{
return value.ToString();
}
return ReflectionHelper.GetValueByPath(value, value.GetType(), apiParameter.Name)?.ToString();
}
}
}

2
src/Volo.Abp/Volo/Abp/Json/IJsonSerializer.cs

@ -2,7 +2,7 @@
{
public interface IJsonSerializer
{
string Serialize(object obj, bool camelCase = false, bool indented = false);
string Serialize(object obj, bool camelCase = true, bool indented = false);
T Deserialize<T>(string jsonString);
}

2
test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/App/AppModule.cs

@ -39,7 +39,7 @@ namespace Volo.Abp.AspNetCore.App
["TenantId"] = manager.CurrentTenant == null ? "" : manager.CurrentTenant.Id.ToString()
};
var result = jsonSerializer.Serialize(dictionary);
var result = jsonSerializer.Serialize(dictionary, camelCase: false);
await ctx.Response.WriteAsync(result);
});
}

24
test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/PersonAppServiceClientProxy_Tests.cs

@ -1,4 +1,5 @@
using System.Linq;
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
@ -52,6 +53,27 @@ namespace Volo.Abp.Http.DynamicProxying
firstPerson.ShouldBeNull();
}
[Fact]
public async Task Create()
{
var uniquePersonName = Guid.NewGuid().ToString();
var person = await _peopleAppService.Create(new PersonDto
{
Name = uniquePersonName,
Age = 42
}
);
person.ShouldNotBeNull();
person.Id.ShouldNotBe(Guid.Empty);
person.Name.ShouldBe(uniquePersonName);
var personInDb = _personRepository.GetList().FirstOrDefault(p => p.Name == uniquePersonName);
personInDb.ShouldNotBeNull();
personInDb.Id.ShouldBe(person.Id);
}
[Fact]
public async Task GetWithComplexType()
{

Loading…
Cancel
Save