Home > Enterprise >  The JSON value could not be converted to Model Blazor
The JSON value could not be converted to Model Blazor

Time:05-21

First Blazor WASM app. I get an error while fetching data from Server:

System.Text.Json.JsonException: Deserialization failed for one of these reasons:

  1. Invalid property 'result' found within a JSON object that must only contain metadata >properties and the nested JSON array to be preserved.
  2. The JSON value could not be converted to WeatherBA.Shared.Dtos.ForecastReadDto[]. Path: >$.result | LineNumber: 0 | BytePositionInLine: 10.

FetchData.razor

@code {
private ForecastReadDto[]? forecasts;

protected override async Task OnInitializedAsync()
{
    forecasts = await Http.GetFromJsonAsync<ForecastReadDto[]>("api/Forecast");
}

ForecastController.cs

public class ForecastController : ControllerBase
{
    private readonly IMediator _mediator;
    public ForecastController(IMediator mediator)
    {
        _mediator = mediator;
    }

    [HttpGet]
    public ActionResult<IEnumerable<ForecastReadDto>> GetAllForecasts()
    {
        var request = new GetAllForecastsQuery();
        var result = _mediator.Send(request);
        return Ok(result);
    }
}

GetAllForecastsQueryHandler.cs

...
public async Task<List<ForecastReadDto>> Handle(GetAllForecastsQuery request, 
CancellationToken cancellationToken)
{
    var forecasts = await _repo.GetAllAsync();
    var forecastsOrdered = forecasts.OrderBy(x => x.Date);

    return _mapper.Map<List<ForecastReadDto>>(forecasts);
}

SqlForecastRepo.cs

...
public Task<List<Forecast>> GetAllAsync()
{
    return Task.FromResult(_context.Forecasts.ToList());
}

ForecastReadDto.cs

namespace WeatherBA.Shared.Dtos;
public class ForecastReadDto
{
    public int Id { get; set; }
    public DateTime Date { get; set; }
    public int TemperatureC { get; set; }
    public string? Summary { get; set; }
}

An API Endpoint returns:

{
"result": [
{
  "id": 3,
  "date": "2022-01-01T00:00:00",
  "temperatureC": 20,
  "summary": "Sunny"
}
],
"id": 4639,
"exception": null,
"status": 5,
"isCanceled": false,
"isCompleted": true,
"isCompletedSuccessfully": true,
"creationOptions": 0,
"asyncState": null,
"isFaulted": false
}

CodePudding user response:

The reason of your unexpected result is that you are serializing a Task instead of awaiting the end of the task and send result. I illustrate it in the sample below. This is how you are sending data, without awaiting the task:

using System.Text.Json;
namespace MyApp;

public class DTO
{
    public string Data {get; set;} = default!;
}
public class Program
{
    static void Main(string[] args)
    {
        var result = Task.FromResult(new DTO(){Data="Hi"});
        var options = new JsonSerializerOptions { WriteIndented = true };
        var result_serialized = JsonSerializer.Serialize(result, options);
        System.Console.WriteLine(result_serialized);
    }
}

Result:

{
  "Result": {
    "Data": "Hi"
  },
  "Id": 1,
  "Exception": null,
  "Status": 5,
  "IsCanceled": false,
  "IsCompleted": true,
  "IsCompletedSuccessfully": true,
  "CreationOptions": 0,
  "AsyncState": null,
  "IsFaulted": false
}

This is how to fix the issue. To get data, you should to await for Task result:

using System.Text.Json;
namespace MyApp;

public class DTO
{
    public string Data {get; set;} = default!;
}
public class Program
{
    static async Task Main(string[] args)
    {
        var result = await Task.FromResult(new DTO(){Data="Hi"}); //<-- HERE
        var options = new JsonSerializerOptions { WriteIndented = true };
        var result_serialized = JsonSerializer.Serialize(result, options);
        System.Console.WriteLine(result_serialized);
    }
}

Result:

{
  "Data": "Hi"
}
  • Related