-
Notifications
You must be signed in to change notification settings - Fork 10.4k
Description
Describe the bug
Trying to deserialize a generic class or struct using the new ReadFromJsonAsync
from System.Net.Http.Json fails silently.
I tested it using either a struct or a class. Both work on their own, but not when they carry a generic payload. Making both Result and payload a class deserializes to an empty Result-object with a null payload.
To Reproduce
I used a struct for both used Types here as that is my specific use case, but the same happens when using classes instead.
-
Create a new hosted Blazor WebAssembly project with the default template as BlazorApp1.Client, .Shared and .Server respectively.
-
Add the following class to the .Shared Project:
public struct Result<T>
{
private Result(bool success, T data, string message = null)
{
Success = success;
Data = data;
Message = message;
}
public bool Success { get; private set; }
public T Data { get; private set; }
public string Message { get; private set; }
public static Result<T> Positive(T data, string message = null)
{
return new Result<T>(true, data, message);
}
public override string ToString()
{
return $"Result: {Success}, Data: {Data}, Message: {Message}";
}
}
- Add the following code to the WeatherForecastController to simply send a random WeatherForecast to the caller:
[HttpPost]
public Result<WeatherForecast> Post(string _)
{
var rng = new Random();
return Result<WeatherForecast>.Positive(Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
}).First());
}
- Add the following to the .Client's FetchData.razor html section:
<button @onclick="DataViaPost">Get data via post</button>
<h1>Data from POST</h1>
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
</tbody>
</table>
And this to the code section:
private WeatherForecast forecast;
async Task DataViaPost()
{
var response = await Http.PostAsJsonAsync<string>("WeatherForecast", "dummy");
Console.WriteLine($"Response: {response}");
string content = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Content as string: \n{content}");
var result = await response.Content.ReadFromJsonAsync<Result<WeatherForecast>>();
Console.WriteLine(result);
if (result.Success) forecast = result.Data;
}
- Start the .Server project
- Open the console to observe the browser output
- Go to the "Fetch data" page and click the button
The output in the console should look something like this:
The readout as string shows the correctly received data.
The deserialized object has no data.
Further technical details
dotnet core sdk: 3.1.201
Windows 10.0.18363 (Update 1909)
Visual Studio 2019 16.5.4
App is netstandard21/netcoreapp31
Included in default template are:
Microsoft.AspNetCore.Components.WebAssembly/.Build/.DevServer 3.2.0-preview4.20210.8
System.Net.Http.Json 3.2.0-preview5.20210.3