I am trying to write a web api using abp.io and implementing NodaTime. Whenever I try to call the POST action, I get
The following errors were detected during validation.\r\n - The JSON value could not be converted to NodaTime.LocalDate.
I have configured NodaTime correctly in the module, I also tested it in a conventional .net 5 web api and is working correctly.
Here is my config:
private void ConfigureNodaSerialization()
{
Configure<JsonSerializer>(options =>
{
options.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
//options.Converters.Add(NodaConverters.LocalDateConverter);
});
}
I am using NodaTime.Serialization.JsonNet
I have also tried NodaTime.Serialization.SystemTextJson to no avail, same results.
..and here is the appservice:
[AllowAnonymous]
public class NodaTestAppService : TestAppService, INodaTestAppService
{
public Task PostNodaTest([FromBody]NodaTestDto dto)
{
return Task.CompletedTask;
}
public Task GetNodaTest(NodaTestDto dto)
{
return Task.CompletedTask;
}
}
The GET is working fine, problem is with POST.
This is the dto:
public class NodaTestDto
{
public LocalDate Date { get; set; }
public string NodaString { get; set; }
}
I suspect the problem is with Abp serialization.
I have my test solution on github here.
This is the curl for my attempted request:
curl -X 'POST'
'https://localhost:44333/api/app/noda-test/noda-test'
-H 'accept: /'
-H 'Content-Type: application/json'
-H 'RequestVerificationToken: CfDJ8N-JsQhR2mhIqO-RkZtn61KwWgiFfjD60I0EMa07QTooLF9dC8LPmQEDtTws8MpTUtl8b0gtuE-NAiBAXxHEu8IyU8-4w0MfVB4IeZTRsWwXIgzc7pQYReLYnV1IVp0icR5Aj-fMvBqRyvPaNTgVJBc'
-d '{ "date": "1991-08-28", "nodaString": "string" }'
The source code of ABP shows that Newtonsoft.Json
is being configured upon MvcNewtonsoftJsonOptions
(instead of JsonSerializer
):
services.Configure<MvcNewtonsoftJsonOptions>(jsonOptions => {
// configuration settings go here.
}
You might want to do in a similar way using NodaTime.Serialization.JsonNet
.
private void ConfigureNodaSerialization(ServiceConfigurationContext context)
{
context.Services.Configure<MvcNewtonsoftJsonOptions>(options =>
{
options.SerializerSettings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
});
}
I use the below package reference.
<PackageReference Include="NodaTime.Serialization.JsonNet" Version="3.0.0" />
UPDATE
The documentation states that ABP is using a hybrid approach using System.Text.Json
and falling back to Newtonsoft.Json
for unsupported types; it shows how you can keep using Newtonsoft.Json
for specific classes or all over the place.
I took the approach to only use Newtonsoft.Json
for the NodaTestDto
class, together with the NodaTime
configuration shown above.
Your ConfigureNodaSerialization
method within your TestHttpApiHostModule
should look like below.
private void ConfigureNodaSerialization()
{
// Use Newtonsoft.Json for NodaTestDto.
Configure<AbpSystemTextJsonSerializerOptions>(options =>
{
options.UnsupportedTypes.AddIfNotContains(typeof(NodaTestDto));
});
// Configure Nodatime (de)serialization.
Configure<MvcNewtonsoftJsonOptions>(jsonOptions =>
{
jsonOptions.SerializerSettings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
});
}
Now, when posting a { "date": "1991-08-28", "nodaString": "string" }
json
payload using the Swagger
UI, your NodaTestAppService
receives a valid LocalDate
instance: