Search code examples
c#jsonasp.net-web-apimicroservicesapi-gateway

Error when deserialize JSON microservice result in Gateway service


I have a gateway service and a microservice customer

The Gateway service call a method from Customer microservices.

The customer service entry point looks like this :

[HttpGet("GetAll", Name = nameof(GetAll))]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<List<CustomerListVm>>> GetAll()
{
    var dtos = await _mediator.Send(new GetCustomersListQuery());

    return Ok(dtos);
}

When I call this method from swagger the result is ok, no problem

Now I call the same entry point from the gateway service

[HttpGet("GetAll", Name = nameof(GetAll))]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<List<CustomerDto>> GetAll()
{
    var dtos = this.customerService.GetAll();

    return Ok(dtos);
}


public async Task<List<CustomerDto>> GetAll()
{
    var response = await this.httpClient.GetAsync("url customer service Getall entry point");

    var result = await response.ReadContentAs<List<CustomerDto>>();

    return result;
}

An extension method to convert answer from customer service json result to my object on gateway service side.

public static async Task<T> ReadContentAs<T>(this HttpResponseMessage response)
{
    if(!response.IsSuccessStatusCode)
        throw new ApplicationException($"Something went wrong calling the API: {response.ReasonPhrase}");

    var dataAsString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

    var obj = JsonSerializer.Deserialize<T>(
        dataAsString,
        new JsonSerializerOptions { PropertyNameCaseInsensitive = true });

    return obj;
}

dataAsString contain the right result coming from the customer service.

[{"customerId":
        "b0788d2f-8003-43c1-92a4-edc76a7c5dde",
        "reference":"2020001",
        "lastName":"MyLastName",
        "firstName":null,
        "email":null
}]

I'd like put the JSON result in this object

public class CustomerDto
{
    public Guid CustomerId { get; set; }

    public string Reference { get; set; }

    public string LastName { get; set; }

    public string FirstName { get; set; }

    public string Email { get; set; }
}

In Gateway service in the startup.cs, I have this :

services.AddControllers().AddNewtonsoftJson(options =>
    options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
);

But I get an error as result in swagger :

{
  "stateMachine": {
    "<>1__state": 0,
    "<>t__builder": {},
    "<>4__this": {}
  },
  "context": {},
  "moveNextAction": {
    "method": {
      "name": "MoveNext",
      "declaringType": "System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Collections.Generic.List`1[[Gateway.Web.Models.CustomerDto, Gateway.Web, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[Gateway.Web.Services.CustomerService+<GetAll>d__2, Gateway.Web, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
      "reflectedType": "System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Collections.Generic.List`1[[Gateway.Web.Models.CustomerDto, Gateway.Web, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[Gateway.Web.Services.CustomerService+<GetAll>d__2, Gateway.Web, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",

Solution

  • In this code:

    [HttpGet("GetAll", Name = nameof(GetAll))]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public ActionResult<List<CustomerDto>> GetAll()
    {
        var dtos = this.customerService.GetAll();
    
        return Ok(dtos);
    }
    

    It should be:

    [HttpGet("GetAll", Name = nameof(GetAll))]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<ActionResult<List<CustomerDto>>> GetAll()
    {
        var dtos = await this.customerService.GetAll();
    
        return Ok(dtos);
    }
    

    You aren't awaiting it -- that's why it's returning a serialized Task.