Browse Source

Resolve #3339: Dynamic C# API Clients may not handle DateTime on QueryString when client and server cultures are different

pull/3475/head
Halil İbrahim Kalkan 6 years ago
parent
commit
70444944c7
  1. 15
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs
  2. 22
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/UrlBuilder.cs
  3. 5
      framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/IRegularTestController.cs
  4. 22
      framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestController.cs
  5. 46
      framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs

15
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs

@ -56,7 +56,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying
IJsonSerializer jsonSerializer,
IRemoteServiceHttpClientAuthenticator clientAuthenticator,
ICancellationTokenProvider cancellationTokenProvider,
ICorrelationIdProvider correlationIdProvider,
ICorrelationIdProvider correlationIdProvider,
IOptions<AbpCorrelationIdOptions> correlationIdOptions,
ICurrentTenant currentTenant)
{
@ -110,7 +110,14 @@ namespace Volo.Abp.Http.Client.DynamicProxying
//TODO: Think on that
if (TypeHelper.IsPrimitiveExtended(typeof(T), true))
{
return (T)Convert.ChangeType(responseAsString, typeof(T));
if (typeof(DateTime).IsAssignableFrom(typeof(T)))
{
return (T)(object)DateTime.Parse(responseAsString.Trim('\"'), CultureInfo.InvariantCulture);
}
else
{
return (T)Convert.ChangeType(responseAsString, typeof(T));
}
}
return JsonSerializer.Deserialize<T>(responseAsString);
@ -151,8 +158,8 @@ namespace Volo.Abp.Http.Client.DynamicProxying
}
return await response.Content.ReadAsStringAsync();
}
}
private ApiVersionInfo GetApiVersionInfo(ActionApiDescriptionModel action)
{
var apiVersion = FindBestApiVersion(action);

22
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/UrlBuilder.cs

@ -1,9 +1,12 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using JetBrains.Annotations;
using Volo.Abp.Http.Modeling;
using Volo.Abp.Http.ProxyScripting.Generators;
using Volo.Abp.Reflection;
namespace Volo.Abp.Http.Client.DynamicProxying
{
@ -88,10 +91,25 @@ namespace Volo.Abp.Http.Client.DynamicProxying
}
}
private static void AddQueryStringParameter(StringBuilder urlBuilder, bool isFirstParam, string name, object value)
private static void AddQueryStringParameter(
StringBuilder urlBuilder,
bool isFirstParam,
string name,
[NotNull] object value)
{
urlBuilder.Append(isFirstParam ? "?" : "&");
urlBuilder.Append(name + "=" + System.Net.WebUtility.UrlEncode(value.ToString()));
urlBuilder.Append(name + "=" + System.Net.WebUtility.UrlEncode(ConvertValueToString(value)));
}
private static string ConvertValueToString([NotNull] object value)
{
if (value is DateTime dateTimeValue)
{
return dateTimeValue.ToUniversalTime().ToString("u");
}
return value.ToString();
}
}
}

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

@ -1,4 +1,5 @@
using System.Threading.Tasks;
using System;
using System.Threading.Tasks;
namespace Volo.Abp.Http.DynamicProxying
{
@ -8,6 +9,8 @@ namespace Volo.Abp.Http.DynamicProxying
Task GetException1Async();
Task<DateTime> GetWithDateTimeParameterAsync(DateTime dateTime1);
Task<string> PostValueWithHeaderAndQueryStringAsync(string headerValue, string qsValue);
Task<string> PostValueWithBodyAsync(string bodyValue);

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

@ -1,4 +1,6 @@
using System.Threading.Tasks;
using System;
using System.Globalization;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.Application.Services;
using Volo.Abp.AspNetCore.Mvc;
@ -25,6 +27,14 @@ namespace Volo.Abp.Http.DynamicProxying
throw new UserFriendlyException("This is an error message!");
}
[HttpGet]
[Route("get-with-datetime-parameter")]
public Task<DateTime> GetWithDateTimeParameterAsync(DateTime dateTime1)
{
var culture = CultureInfo.CurrentCulture;
return Task.FromResult(dateTime1);
}
[HttpPost]
[Route("post-with-header-and-qs")]
public Task<string> PostValueWithHeaderAndQueryStringAsync([FromHeader] string headerValue, [FromQuery] string qsValue)
@ -48,7 +58,7 @@ namespace Volo.Abp.Http.DynamicProxying
[HttpPost]
[Route("post-object-with-query")]
public Task<Car> PostObjectWithQueryAsync( Car bodyValue)
public Task<Car> PostObjectWithQueryAsync(Car bodyValue)
{
return Task.FromResult(bodyValue);
}
@ -59,7 +69,7 @@ namespace Volo.Abp.Http.DynamicProxying
{
return Task.FromResult(bodyValue);
}
[HttpGet]
[Route("post-object-and-id-with-url/{id}")]
public Task<Car> GetObjectandIdAsync(int id, [FromBody] Car bodyValue)
@ -67,7 +77,7 @@ namespace Volo.Abp.Http.DynamicProxying
bodyValue.Year = id;
return Task.FromResult(bodyValue);
}
[HttpGet]
[Route("post-object-and-id-with-url-and-query/{id}")]
public Task<Car> GetObjectAndIdWithQueryAsync(int id, Car bodyValue)
@ -116,7 +126,11 @@ namespace Volo.Abp.Http.DynamicProxying
{
[FromQuery]
public int Year { get; set; }
[FromQuery]
public string Model { get; set; }
[FromQuery]
public DateTime FirstReleaseDate { get; set; }
}
}

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

@ -1,7 +1,9 @@
using System.Threading.Tasks;
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.Http.Client;
using Volo.Abp.Localization;
using Xunit;
namespace Volo.Abp.Http.DynamicProxying
@ -30,6 +32,25 @@ namespace Volo.Abp.Http.DynamicProxying
exception.Error.Message.ShouldBe("This is an error message!");
}
[Fact]
public async Task GetWithDateTimeParameterAsync()
{
var dateTime1 = new DateTime(2020, 04, 19, 19, 05, 01);
var result = await _controller.GetWithDateTimeParameterAsync(dateTime1);
result.ShouldBe(dateTime1);
}
[Fact]
public async Task GetWithDateTimeParameterAsync_With_Different_Culture()
{
using (CultureHelper.Use("es"))
{
var dateTime1 = new DateTime(2020, 04, 19, 19, 05, 01);
var result = await _controller.GetWithDateTimeParameterAsync(dateTime1);
result.ShouldBe(dateTime1);
}
}
[Fact]
public async Task PostValueWithHeaderAndQueryStringAsync()
{
@ -54,7 +75,7 @@ namespace Volo.Abp.Http.DynamicProxying
[Fact]
public async Task PostObjectWithBodyAsync()
{
var result = await _controller.PostObjectWithBodyAsync(new Car { Year = 1976, Model = "Ford" });
var result = await _controller.PostObjectWithBodyAsync(new Car { Year = 1976, Model = "Ford", FirstReleaseDate = new DateTime(1976, 02, 22, 15, 0, 6, 22) });
result.Year.ShouldBe(1976);
result.Model.ShouldBe("Ford");
}
@ -62,15 +83,26 @@ namespace Volo.Abp.Http.DynamicProxying
[Fact]
public async Task PostObjectWithQueryAsync()
{
var result = await _controller.PostObjectWithQueryAsync(new Car { Year = 1976, Model = "Ford" });
var result = await _controller.PostObjectWithQueryAsync(new Car { Year = 1976, Model = "Ford", FirstReleaseDate = new DateTime(1976, 02, 22, 15, 0, 6, 22) });
result.Year.ShouldBe(1976);
result.Model.ShouldBe("Ford");
}
[Fact]
public async Task PostObjectWithQueryAsync_With_Different_Culture()
{
using (CultureHelper.Use("tr"))
{
var result = await _controller.PostObjectWithQueryAsync(new Car { Year = 1976, Model = "Ford", FirstReleaseDate = new DateTime(1976, 02, 22, 15, 0, 6, 22) });
result.Year.ShouldBe(1976);
result.Model.ShouldBe("Ford");
}
}
[Fact]
public async Task GetObjectWithUrlAsync()
{
var result = await _controller.GetObjectWithUrlAsync(new Car { Year = 1976, Model = "Ford" });
var result = await _controller.GetObjectWithUrlAsync(new Car { Year = 1976, Model = "Ford", FirstReleaseDate = new DateTime(1976, 02, 22, 15, 0, 6, 22) });
result.Year.ShouldBe(1976);
result.Model.ShouldBe("Ford");
}
@ -78,7 +110,7 @@ namespace Volo.Abp.Http.DynamicProxying
[Fact]
public async Task GetObjectandIdAsync()
{
var result = await _controller.GetObjectandIdAsync(42, new Car { Year = 1976, Model = "Ford" });
var result = await _controller.GetObjectandIdAsync(42, new Car { Year = 1976, Model = "Ford", FirstReleaseDate = new DateTime(1976, 02, 22, 15, 0, 6, 22) });
result.Year.ShouldBe(42);
result.Model.ShouldBe("Ford");
}
@ -86,7 +118,7 @@ namespace Volo.Abp.Http.DynamicProxying
[Fact]
public async Task GetObjectAndIdWithQueryAsync()
{
var result = await _controller.GetObjectAndIdWithQueryAsync(42, new Car { Year = 1976, Model = "Ford" });
var result = await _controller.GetObjectAndIdWithQueryAsync(42, new Car { Year = 1976, Model = "Ford", FirstReleaseDate = new DateTime(1976, 02, 22, 15, 0, 6, 22) });
result.Year.ShouldBe(42);
result.Model.ShouldBe("Ford");
}
@ -97,7 +129,7 @@ namespace Volo.Abp.Http.DynamicProxying
var result = await _controller.PatchValueWithBodyAsync("mybody");
result.ShouldBe("mybody");
}
[Fact]
public async Task PutValueWithHeaderAndQueryStringAsync()
{

Loading…
Cancel
Save