Browse Source

Merge pull request #24049 from gdlcf88/patch-10

pull/24546/head
Ma Liming 10 months ago
committed by GitHub
parent
commit
634d8052ac
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 38
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpDateTimeModelBinder.cs
  2. 2
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpDateTimeModelBinderProvider.cs
  3. 49
      framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpDateTimeConverter.cs
  4. 69
      framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs
  5. 116
      framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverterBase.cs
  6. 67
      framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs
  7. 39
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ModelBinding/ModelBindingController.cs
  8. 104
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ModelBinding/ModelBindingController_Tests.cs

38
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpDateTimeModelBinder.cs

@ -2,27 +2,57 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
using Microsoft.Extensions.Logging;
using Volo.Abp.Timing;
namespace Volo.Abp.AspNetCore.Mvc.ModelBinding;
public class AbpDateTimeModelBinder : IModelBinder
{
private readonly ILogger<AbpDateTimeModelBinder> _logger;
private readonly DateTimeModelBinder _dateTimeModelBinder;
private readonly IClock _clock;
private readonly ICurrentTimezoneProvider _currentTimezoneProvider;
private readonly ITimezoneProvider _timezoneProvider;
public AbpDateTimeModelBinder(IClock clock, DateTimeModelBinder dateTimeModelBinder)
public AbpDateTimeModelBinder(
ILogger<AbpDateTimeModelBinder> logger,
DateTimeModelBinder dateTimeModelBinder,
IClock clock,
ICurrentTimezoneProvider currentTimezoneProvider,
ITimezoneProvider timezoneProvider)
{
_clock = clock;
_logger = logger;
_dateTimeModelBinder = dateTimeModelBinder;
_clock = clock;
_currentTimezoneProvider = currentTimezoneProvider;
_timezoneProvider = timezoneProvider;
}
public async Task BindModelAsync(ModelBindingContext bindingContext)
{
await _dateTimeModelBinder.BindModelAsync(bindingContext);
if (bindingContext.Result.IsModelSet && bindingContext.Result.Model is DateTime dateTime)
if (!bindingContext.Result.IsModelSet || bindingContext.Result.Model is not DateTime dateTime)
{
bindingContext.Result = ModelBindingResult.Success(_clock.Normalize(dateTime));
return;
}
if (dateTime.Kind == DateTimeKind.Unspecified &&
_clock.SupportsMultipleTimezone &&
!_currentTimezoneProvider.TimeZone.IsNullOrWhiteSpace())
{
try
{
var timezoneInfo = _timezoneProvider.GetTimeZoneInfo(_currentTimezoneProvider.TimeZone);
dateTime = new DateTimeOffset(dateTime, timezoneInfo.GetUtcOffset(dateTime)).UtcDateTime;
}
catch
{
_logger.LogWarning("Could not convert DateTime with unspecified Kind using timezone '{TimeZone}'.", _currentTimezoneProvider.TimeZone);
}
}
bindingContext.Result = ModelBindingResult.Success(_clock.Normalize(dateTime));
}
}

2
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpDateTimeModelBinderProvider.cs

@ -50,6 +50,6 @@ public class AbpDateTimeModelBinderProvider : IModelBinderProvider
{
const DateTimeStyles supportedStyles = DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.AdjustToUniversal;
var dateTimeModelBinder = new DateTimeModelBinder(supportedStyles, context.Services.GetRequiredService<ILoggerFactory>());
return new AbpDateTimeModelBinder(context.Services.GetRequiredService<IClock>(), dateTimeModelBinder);
return ActivatorUtilities.CreateInstance<AbpDateTimeModelBinder>(context.Services, dateTimeModelBinder);
}
}

49
framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpDateTimeConverter.cs

@ -2,6 +2,8 @@
using System.Globalization;
using System.Linq;
using System.Reflection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
@ -15,15 +17,24 @@ namespace Volo.Abp.Json.Newtonsoft;
public class AbpDateTimeConverter : DateTimeConverterBase, ITransientDependency
{
private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";
public ILogger<AbpDateTimeConverter> Logger { get; set; }
private readonly DateTimeStyles _dateTimeStyles = DateTimeStyles.RoundtripKind;
private readonly CultureInfo _culture = CultureInfo.InvariantCulture;
private readonly IClock _clock;
private readonly AbpJsonOptions _options;
private readonly ICurrentTimezoneProvider _currentTimezoneProvider;
private readonly ITimezoneProvider _timezoneProvider;
private bool _skipDateTimeNormalization;
public AbpDateTimeConverter(IClock clock, IOptions<AbpJsonOptions> options)
public AbpDateTimeConverter(IClock clock, IOptions<AbpJsonOptions> options, ICurrentTimezoneProvider currentTimezoneProvider, ITimezoneProvider timezoneProvider)
{
Logger = NullLogger<AbpDateTimeConverter>.Instance;
_clock = clock;
_currentTimezoneProvider = currentTimezoneProvider;
_timezoneProvider = timezoneProvider;
_options = options.Value;
}
@ -41,19 +52,14 @@ public class AbpDateTimeConverter : DateTimeConverterBase, ITransientDependency
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
{
var nullable = Nullable.GetUnderlyingType(objectType) != null;
if (reader.TokenType == JsonToken.Null)
switch (reader.TokenType)
{
if (!nullable)
{
case JsonToken.Null when !nullable:
throw new JsonSerializationException($"Cannot convert null value to {objectType.FullName}.");
}
return null;
}
if (reader.TokenType == JsonToken.Date)
{
return Normalize(reader.Value!.To<DateTime>());
case JsonToken.Null:
return null;
case JsonToken.Date:
return Normalize(reader.Value!.To<DateTime>());
}
if (reader.TokenType != JsonToken.String)
@ -108,7 +114,7 @@ public class AbpDateTimeConverter : DateTimeConverterBase, ITransientDependency
}
}
static internal bool ShouldNormalize(MemberInfo member, JsonProperty property)
internal static bool ShouldNormalize(MemberInfo member, JsonProperty property)
{
if (property.PropertyType != typeof(DateTime) &&
property.PropertyType != typeof(DateTime?))
@ -121,6 +127,23 @@ public class AbpDateTimeConverter : DateTimeConverterBase, ITransientDependency
protected virtual DateTime Normalize(DateTime dateTime)
{
if (dateTime.Kind != DateTimeKind.Unspecified ||
!_clock.SupportsMultipleTimezone ||
_currentTimezoneProvider.TimeZone.IsNullOrWhiteSpace())
{
return _skipDateTimeNormalization ? dateTime : _clock.Normalize(dateTime);
}
try
{
var timezoneInfo = _timezoneProvider.GetTimeZoneInfo(_currentTimezoneProvider.TimeZone);
dateTime = new DateTimeOffset(dateTime, timezoneInfo.GetUtcOffset(dateTime)).UtcDateTime;
}
catch
{
Logger.LogWarning("Could not convert DateTime with unspecified Kind using timezone '{TimeZone}'.", _currentTimezoneProvider.TimeZone);
}
return _skipDateTimeNormalization
? dateTime
: _clock.Normalize(dateTime);

69
framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs

@ -1,84 +1,43 @@
using System;
using System.Globalization;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Timing;
namespace Volo.Abp.Json.SystemTextJson.JsonConverters;
public class AbpDateTimeConverter : JsonConverter<DateTime>, ITransientDependency
public class AbpDateTimeConverter : AbpDateTimeConverterBase<DateTime>, ITransientDependency
{
private readonly IClock _clock;
private readonly AbpJsonOptions _options;
private bool _skipDateTimeNormalization;
public AbpDateTimeConverter(IClock clock, IOptions<AbpJsonOptions> abpJsonOptions)
public AbpDateTimeConverter(
IClock clock,
IOptions<AbpJsonOptions> abpJsonOptions,
ICurrentTimezoneProvider currentTimezoneProvider,
ITimezoneProvider timezoneProvider)
: base(clock, abpJsonOptions, currentTimezoneProvider, timezoneProvider)
{
_clock = clock;
_options = abpJsonOptions.Value;
}
public virtual AbpDateTimeConverter SkipDateTimeNormalization()
{
_skipDateTimeNormalization = true;
IsSkipDateTimeNormalization = true;
return this;
}
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (_options.InputDateTimeFormats.Any())
{
if (reader.TokenType == JsonTokenType.String)
{
foreach (var format in _options.InputDateTimeFormats)
{
var s = reader.GetString();
if (DateTime.TryParseExact(s, format, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d1))
{
return Normalize(d1);
}
}
}
else
{
throw new JsonException("Reader's TokenType is not String!");
}
}
if (reader.TryGetDateTime(out var d3))
{
return Normalize(d3);
}
var dateText = reader.GetString();
if (!dateText.IsNullOrWhiteSpace())
if (Options.InputDateTimeFormats.Any() && reader.TokenType != JsonTokenType.String)
{
if (DateTime.TryParse(dateText, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d4))
{
return Normalize(d4);
}
throw new JsonException("Reader's TokenType is not String!");
}
throw new JsonException("Can't get datetime from the reader!");
return TryReadDateTime(ref reader, out var result)
? result
: throw new JsonException("Can't get datetime from the reader!");
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
if (_options.OutputDateTimeFormat.IsNullOrWhiteSpace())
{
writer.WriteStringValue(Normalize(value));
}
else
{
writer.WriteStringValue(Normalize(value).ToString(_options.OutputDateTimeFormat, CultureInfo.CurrentUICulture));
}
}
protected virtual DateTime Normalize(DateTime dateTime)
{
return _skipDateTimeNormalization ? dateTime : _clock.Normalize(dateTime);
WriteDateTime(writer, value);
}
}

116
framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverterBase.cs

@ -0,0 +1,116 @@
using System;
using System.Globalization;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Volo.Abp.Timing;
namespace Volo.Abp.Json.SystemTextJson.JsonConverters;
public abstract class AbpDateTimeConverterBase<T> : JsonConverter<T>
{
public ILogger<AbpDateTimeConverterBase<T>> Logger { get; set; }
protected IClock Clock { get; }
protected AbpJsonOptions Options { get; }
protected ICurrentTimezoneProvider CurrentTimezoneProvider { get; }
protected ITimezoneProvider TimezoneProvider { get; }
protected bool IsSkipDateTimeNormalization { get; set; }
protected AbpDateTimeConverterBase(
IClock clock,
IOptions<AbpJsonOptions> abpJsonOptions,
ICurrentTimezoneProvider currentTimezoneProvider,
ITimezoneProvider timezoneProvider)
{
Logger = NullLogger<AbpDateTimeConverterBase<T>>.Instance;
Clock = clock;
CurrentTimezoneProvider = currentTimezoneProvider;
TimezoneProvider = timezoneProvider;
Options = abpJsonOptions.Value;
}
protected bool TryReadDateTime(ref Utf8JsonReader reader, out DateTime value)
{
value = default;
if (Options.InputDateTimeFormats.Any())
{
if (reader.TokenType != JsonTokenType.String)
{
return false;
}
var s = reader.GetString();
foreach (var format in Options.InputDateTimeFormats)
{
if (!DateTime.TryParseExact(s, format, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d1))
{
continue;
}
value = Normalize(d1);
return true;
}
}
if (reader.TryGetDateTime(out var d2))
{
value = Normalize(d2);
return true;
}
var dateText = reader.GetString();
if (dateText.IsNullOrWhiteSpace())
{
return false;
}
if (!DateTime.TryParse(dateText, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d3))
{
return false;
}
value = Normalize(d3);
return true;
}
protected void WriteDateTime(Utf8JsonWriter writer, DateTime value)
{
if (Options.OutputDateTimeFormat.IsNullOrWhiteSpace())
{
writer.WriteStringValue(Normalize(value));
}
else
{
writer.WriteStringValue(Normalize(value).ToString(Options.OutputDateTimeFormat, CultureInfo.CurrentUICulture));
}
}
protected virtual DateTime Normalize(DateTime dateTime)
{
if (dateTime.Kind != DateTimeKind.Unspecified ||
!Clock.SupportsMultipleTimezone ||
CurrentTimezoneProvider.TimeZone.IsNullOrWhiteSpace())
{
return IsSkipDateTimeNormalization ? dateTime : Clock.Normalize(dateTime);
}
try
{
var timezoneInfo = TimezoneProvider.GetTimeZoneInfo(CurrentTimezoneProvider.TimeZone);
dateTime = new DateTimeOffset(dateTime, timezoneInfo.GetUtcOffset(dateTime)).UtcDateTime;
}
catch
{
Logger.LogWarning("Could not convert DateTime with unspecified Kind using timezone '{TimeZone}'.", CurrentTimezoneProvider.TimeZone);
}
return IsSkipDateTimeNormalization ? dateTime : Clock.Normalize(dateTime);
}
}

67
framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs

@ -1,65 +1,39 @@
using System;
using System.Globalization;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Timing;
namespace Volo.Abp.Json.SystemTextJson.JsonConverters;
public class AbpNullableDateTimeConverter : JsonConverter<DateTime?>, ITransientDependency
public class AbpNullableDateTimeConverter : AbpDateTimeConverterBase<DateTime?>, ITransientDependency
{
private readonly IClock _clock;
private readonly AbpJsonOptions _options;
private bool _skipDateTimeNormalization;
public AbpNullableDateTimeConverter(IClock clock, IOptions<AbpJsonOptions> abpJsonOptions)
public AbpNullableDateTimeConverter(
IClock clock,
IOptions<AbpJsonOptions> abpJsonOptions,
ICurrentTimezoneProvider currentTimezoneProvider,
ITimezoneProvider timezoneProvider)
: base(clock, abpJsonOptions, currentTimezoneProvider, timezoneProvider)
{
_clock = clock;
_options = abpJsonOptions.Value;
}
public virtual AbpNullableDateTimeConverter SkipDateTimeNormalization()
{
_skipDateTimeNormalization = true;
IsSkipDateTimeNormalization = true;
return this;
}
public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (_options.InputDateTimeFormats.Any())
{
if (reader.TokenType == JsonTokenType.String)
{
foreach (var format in _options.InputDateTimeFormats)
{
var s = reader.GetString();
if (DateTime.TryParseExact(s, format, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d1))
{
return Normalize(d1);
}
}
}
else
{
throw new JsonException("Reader's TokenType is not String!");
}
}
if (reader.TryGetDateTime(out var d2))
if (Options.InputDateTimeFormats.Any() && reader.TokenType != JsonTokenType.String)
{
return Normalize(d2);
throw new JsonException("Reader's TokenType is not String!");
}
var dateText = reader.GetString();
if (!dateText.IsNullOrWhiteSpace())
if (TryReadDateTime(ref reader, out var result))
{
if (DateTime.TryParse(dateText, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d3))
{
return Normalize(d3);
}
return result;
}
return null;
@ -70,22 +44,9 @@ public class AbpNullableDateTimeConverter : JsonConverter<DateTime?>, ITransient
if (value == null)
{
writer.WriteNullValue();
return;
}
else
{
if (_options.OutputDateTimeFormat.IsNullOrWhiteSpace())
{
writer.WriteStringValue(Normalize(value.Value));
}
else
{
writer.WriteStringValue(Normalize(value.Value).ToString(_options.OutputDateTimeFormat, CultureInfo.CurrentUICulture));
}
}
}
protected virtual DateTime Normalize(DateTime dateTime)
{
return _skipDateTimeNormalization ? dateTime : _clock.Normalize(dateTime);
WriteDateTime(writer, value.Value);
}
}

39
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ModelBinding/ModelBindingController.cs

@ -13,12 +13,24 @@ public class ModelBindingController : AbpController
return input.Kind.ToString().ToLower();
}
[HttpGet("DateTimeKind_WithResult")]
public string DateTimeKind_WithResult(DateTime input)
{
return input.Kind.ToString().ToLower() + "_" + input.ToString("O").ToLower();
}
[HttpGet("NullableDateTimeKind")]
public string NullableDateTimeKind(DateTime? input)
{
return input.Value.Kind.ToString().ToLower();
}
[HttpGet("NullableDateTimeKind_WithResult")]
public string NullableDateTimeKind_WithResult(DateTime? input)
{
return input.Value.Kind.ToString().ToLower() + "_" + input.Value.ToString("O").ToLower();
}
[HttpGet("DisableDateTimeNormalizationDateTimeKind")]
public string DisableDateTimeNormalizationDateTimeKind([DisableDateTimeNormalization] DateTime input)
{
@ -40,6 +52,19 @@ public class ModelBindingController : AbpController
input.InnerModel.Time4.Kind.ToString().ToLower();
}
[HttpGet("ComplexTypeDateTimeKind_WithResult")]
public string ComplexTypeDateTimeKind_WithResult(GetDateTimeKindModel input)
{
return input.Time1.Kind.ToString().ToLower() + "_" +
input.Time1.ToString("O").ToLower() + "_" +
input.Time2.Kind.ToString().ToLower() + "_" +
input.Time2.ToString("O").ToLower() + "_" +
input.Time3.Value.Kind.ToString().ToLower() + "_" +
input.Time3.Value.ToString("O").ToLower() + "_" +
input.InnerModel.Time4.Kind.ToString().ToLower() + "_" +
input.InnerModel.Time4.ToString("O").ToLower();
}
//JSON input and output.
[HttpPost("ComplexTypeDateTimeKind_JSON")]
public string ComplexTypeDateTimeKind_JSON([FromBody] GetDateTimeKindModel input)
@ -50,6 +75,20 @@ public class ModelBindingController : AbpController
input.InnerModel.Time4.Kind.ToString().ToLower();
}
//JSON input and output.
[HttpPost("ComplexTypeDateTimeKind_JSON_WithResult")]
public string ComplexTypeDateTimeKind_JSON_WithResult([FromBody] GetDateTimeKindModel input)
{
return input.Time1.Kind.ToString().ToLower() + "_" +
input.Time1.ToString("O").ToLower() + "_" +
input.Time2.Kind.ToString().ToLower() + "_" +
input.Time2.ToString("O").ToLower() + "_" +
input.Time3.Value.Kind.ToString().ToLower() + "_" +
input.Time3.Value.ToString("O").ToLower() + "_" +
input.InnerModel.Time4.Kind.ToString().ToLower() + "_" +
input.InnerModel.Time4.ToString("O").ToLower();
}
[HttpPost("Guid_Json_Test")]
public GuidJsonModel Guid_Json_Test([FromBody] GuidJsonModel input)
{

104
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ModelBinding/ModelBindingController_Tests.cs

@ -19,34 +19,79 @@ public abstract class ModelBindingController_Tests : AspNetCoreMvcTestBase
[Fact]
public async Task DateTimeKind_Test()
{
var response = await Client.GetAsync("/api/model-Binding-test/DateTimeKind?input=2010-01-01T00:00:00Z");
var response = await Client.GetAsync("/api/model-Binding-test/DateTimeKind?input=2020-01-01T00:00:00Z");
response.StatusCode.ShouldBe(HttpStatusCode.OK);
var resultAsString = await response.Content.ReadAsStringAsync();
resultAsString.ShouldBe(Kind.ToString().ToLower());
}
[Fact]
public async Task DateTimeKind_WithTimezone_Test()
{
var response = await Client.GetAsync("/api/model-Binding-test/DateTimeKind_WithResult?input=2020-01-01T00:00:00&__timezone=Europe/Istanbul");
response.StatusCode.ShouldBe(HttpStatusCode.OK);
var resultAsString = await response.Content.ReadAsStringAsync();
var dateTime = new DateTime(2020, 1, 1, 0, 0, 0, DateTimeKind.Unspecified);
switch (Kind)
{
case DateTimeKind.Utc:
dateTime = new DateTime(2019, 12, 31, 21, 0, 0, DateTimeKind.Utc); //Turkey is UTC+3
break;
case DateTimeKind.Local:
dateTime = new DateTime(2020, 1, 1, 0, 0, 0, DateTimeKind.Local);
break;
}
resultAsString.ShouldBe($"{Kind.ToString().ToLower()}_{dateTime.ToString("O").ToLower()}");
}
[Fact]
public async Task NullableDateTimeKind_Test()
{
var response =
await Client.GetAsync("/api/model-Binding-test/NullableDateTimeKind?input=2010-01-01T00:00:00Z");
await Client.GetAsync("/api/model-Binding-test/NullableDateTimeKind?input=2020-01-01T00:00:00Z");
response.StatusCode.ShouldBe(HttpStatusCode.OK);
var resultAsString = await response.Content.ReadAsStringAsync();
resultAsString.ShouldBe(Kind.ToString().ToLower());
}
[Fact]
public async Task NullableDateTimeKind_WithTimezone_Test()
{
var response =
await Client.GetAsync("/api/model-Binding-test/NullableDateTimeKind_WithResult?input=2020-01-01T00:00:00&__timezone=Europe/Istanbul");
response.StatusCode.ShouldBe(HttpStatusCode.OK);
var resultAsString = await response.Content.ReadAsStringAsync();
var dateTime = new DateTime(2020, 1, 1, 0, 0, 0, DateTimeKind.Unspecified);
switch (Kind)
{
case DateTimeKind.Utc:
dateTime = new DateTime(2019, 12, 31, 21, 0, 0, DateTimeKind.Utc); //Turkey is UTC+3
break;
case DateTimeKind.Local:
dateTime = new DateTime(2020, 1, 1, 0, 0, 0, DateTimeKind.Local);
break;
}
resultAsString.ShouldBe($"{Kind.ToString().ToLower()}_{dateTime.ToString("O").ToLower()}");
}
[Fact]
public async Task DisableDateTimeNormalizationDateTimeKind_Test()
{
var response =
await Client.GetAsync(
"/api/model-Binding-test/DisableDateTimeNormalizationDateTimeKind?input=2010-01-01T00:00:00Z");
"/api/model-Binding-test/DisableDateTimeNormalizationDateTimeKind?input=2020-01-01T00:00:00Z");
response.StatusCode.ShouldBe(HttpStatusCode.OK);
var resultAsString = await response.Content.ReadAsStringAsync();
//Time parameter(2010-01-01T00:00:00Z) with time zone information, so the default Kind is UTC
//Time parameter(2020-01-01T00:00:00Z) with time zone information, so the default Kind is UTC
//https://docs.microsoft.com/en-us/aspnet/core/migration/31-to-50?view=aspnetcore-3.1&tabs=visual-studio#datetime-values-are-model-bound-as-utc-times
resultAsString.ShouldBe(DateTimeKind.Utc.ToString().ToLower());
}
@ -56,11 +101,11 @@ public abstract class ModelBindingController_Tests : AspNetCoreMvcTestBase
{
var response =
await Client.GetAsync(
"/api/model-Binding-test/DisableDateTimeNormalizationNullableDateTimeKind?input=2010-01-01T00:00:00Z");
"/api/model-Binding-test/DisableDateTimeNormalizationNullableDateTimeKind?input=2020-01-01T00:00:00Z");
response.StatusCode.ShouldBe(HttpStatusCode.OK);
var resultAsString = await response.Content.ReadAsStringAsync();
//Time parameter(2010-01-01T00:00:00Z) with time zone information, so the default Kind is UTC
//Time parameter(2020-01-01T00:00:00Z) with time zone information, so the default Kind is UTC
//https://docs.microsoft.com/en-us/aspnet/core/migration/31-to-50?view=aspnetcore-3.1&tabs=visual-studio#datetime-values-are-model-bound-as-utc-times
resultAsString.ShouldBe(DateTimeKind.Utc.ToString().ToLower());
}
@ -69,14 +114,14 @@ public abstract class ModelBindingController_Tests : AspNetCoreMvcTestBase
public async Task ComplexTypeDateTimeKind_Test()
{
var response = await Client.GetAsync("/api/model-Binding-test/ComplexTypeDateTimeKind?" +
"Time1=2010-01-01T00:00:00Z&" +
"Time2=2010-01-01T00:00:00Z&" +
"Time3=2010-01-01T00:00:00Z&" +
"InnerModel.Time4=2010-01-01T00:00:00Z");
"Time1=2020-01-01T00:00:00Z&" +
"Time2=2020-01-01T00:00:00Z&" +
"Time3=2020-01-01T00:00:00Z&" +
"InnerModel.Time4=2020-01-01T00:00:00Z");
response.StatusCode.ShouldBe(HttpStatusCode.OK);
var resultAsString = await response.Content.ReadAsStringAsync();
//Time parameter(2010-01-01T00:00:00Z) with time zone information, so the default Kind is UTC
//Time parameter(2020-01-01T00:00:00Z) with time zone information, so the default Kind is UTC
//https://docs.microsoft.com/en-us/aspnet/core/migration/31-to-50?view=aspnetcore-3.1&tabs=visual-studio#datetime-values-are-model-bound-as-utc-times
resultAsString.ShouldBe($"utc_{Kind.ToString().ToLower()}_{Kind.ToString().ToLower()}_utc");
}
@ -84,7 +129,7 @@ public abstract class ModelBindingController_Tests : AspNetCoreMvcTestBase
[Fact]
public async Task ComplexTypeDateTimeKind_JSON_Test()
{
var time = DateTime.Parse("2010-01-01T00:00:00Z");
var time = DateTime.Parse("2020-01-01T00:00:00Z");
var response = await Client.PostAsync("/api/model-Binding-test/ComplexTypeDateTimeKind_JSON",
new StringContent(JsonSerializer.Serialize(
new GetDateTimeKindModel
@ -104,6 +149,41 @@ public abstract class ModelBindingController_Tests : AspNetCoreMvcTestBase
resultAsString.ShouldBe($"local_{Kind.ToString().ToLower()}_{Kind.ToString().ToLower()}_local");
}
[Fact]
public async Task ComplexTypeDateTimeKind_JSON_WithTimezone_Test()
{
var time = DateTime.Parse("2020-01-01T00:00:00");
var response = await Client.PostAsync("/api/model-Binding-test/ComplexTypeDateTimeKind_JSON_WithResult?__timezone=Europe/Istanbul",
new StringContent(JsonSerializer.Serialize(
new GetDateTimeKindModel
{
Time1 = time,
Time2 = time,
Time3 = time,
InnerModel = new GetDateTimeKindModel.GetDateTimeKindInnerModel
{
Time4 = time
}
}
), Encoding.UTF8, MimeTypes.Application.Json));
response.StatusCode.ShouldBe(HttpStatusCode.OK);
var resultAsString = await response.Content.ReadAsStringAsync();
var dateTime = new DateTime(2020, 1, 1, 0, 0, 0, DateTimeKind.Unspecified);
switch (Kind)
{
case DateTimeKind.Utc:
dateTime = new DateTime(2019, 12, 31, 21, 0, 0, DateTimeKind.Utc); //Turkey is UTC+3
break;
case DateTimeKind.Local:
dateTime = new DateTime(2020, 1, 1, 0, 0, 0, DateTimeKind.Local);
break;
}
resultAsString.ShouldBe($"unspecified_{time.ToString("O").ToLower()}_{Kind.ToString().ToLower()}_{dateTime.ToString("O").ToLower()}_{Kind.ToString().ToLower()}_{dateTime.ToString("O").ToLower()}_unspecified_{time.ToString("O").ToLower()}");
}
[Fact]
public async Task Guid_Json_Test()
{

Loading…
Cancel
Save