Search code examples
c#asp.net-coreasp.net-core-webapi.net-6.0actionresult

object type is showing as an empty array in .net 6


I am migrating from .netcore 2.1 to .net 6. I have an endpoint that has a return type of Task I have a class that has properties of type object. And after some checks I am returning an ok result of my object i.e return Ok(myObj); This is working without any problems in .netcore 2.1 but in .net6 the object properties are returning empty arrays for some reason. I created a new app directly in .net 6 and tried to replicate the issue to see if it was some mistake I made while migrating or not but it seems that it doesn't work either. The new project looks like this :

 [HttpGet("test")]   
public IActionResult Test()
{
    var features = new Dictionary<string, bool>()
    {
        { "Foo", true },
        { "Bar", false }
    };
    var settings = new Dictionary<string, string>()
    {
        { "font-size", "16-px" },
        { "showOnStartUp", "no" }
    };
    var resp = new Result()
    {
        InnerDto = new InnerDto()
        {
            Foo = BuildObject(features.Select(f => new KeyValuePair<string, object>(f.Key, f.Value)).ToDictionary(k => k.Key, v => v.Value)),
            Bar = BuildObject(settings.Select(f => new KeyValuePair<string, object>(f.Key, f.Value)).ToDictionary(k => k.Key, v => v.Value))
        },
        S = "Test"
    };
    

    return Ok(resp);
}


private static object BuildObject(Dictionary<string, object> foo)
{

    var objects = foo.Select(f => new
    {
        Key = f.Key,
        Value = SetSettingsValueBasedOnType(f)
    }).ToList();

    var sb = new StringBuilder();
    sb.AppendLine("{");

    for (int i = 0; i < objects.Count; i++)
    {
        string val;
        var obj = objects[i];
        if (bool.TryParse(obj.Value.ToString(), out var parsedVal))
        {
            val = obj.Value.ToString()!.ToLower();
        }
        else
        {
            val = JsonConvert.SerializeObject(obj.Value);
        }

        var line = $@"""{obj.Key}"":{val}";
        sb.AppendLine(line);
        if (i < objects.Count - 1)
        {
            sb.Append(',');
        }
    }
    sb.AppendLine("}");
    var featuresObj = JsonConvert.DeserializeObject(sb.ToString());
    return featuresObj!;
}

private static object SetSettingsValueBasedOnType(KeyValuePair<string, object> bar)
{

    object val;
    if (bool.TryParse(bar.Value.ToString(), out var parseVal))
    {
        val = parseVal;
    }
    else
    {
        val = bar.Value;
    }

    return val;

}
}

   public class Result
{
   public string S { get; set; }
  public InnerDto InnerDto { get; set; }
}

public class InnerDto
{
    public object Foo { get; set; }
    public object Bar { get; set; }
}

the logic is working to the last line before the return as you can see here: enter image description here and the response I'm getting is like this: enter image description here

What is making this work on .netcore 2.1 and not on .net 6?


Solution

  • if you are using Newtonsoft.JSON, it is fine, just add serialized object to your object.

    Change this

    return Ok(resp);
    

    to

    return Ok(JsonConvert.SerializeObject(resp, Formatting.Indented));
    

    Now we know it works, we could add it globally to all controllers by doing this:

    builder.Services.AddControllers()
        .AddNewtonsoftJson();
    

    In this case, you might need to install the following package:

    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.13" />
    

    Then this will also work return Ok(resp);

    And here is your output:

    enter image description here

    Microsoft doc: https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.newtonsoftjsonmvcbuilderextensions.addnewtonsoftjson?view=aspnetcore-6.0