Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to reset $id in JSON response for each HTTP Request? JsonSerializerSettings = PreserveReferencesHandling.Objects

Tags:

XYZController.cs

[HttpPost]
public async Task<ActionResult> Post([FromBody] T inputContext)
{
       var outputContext = Process(inputContext);
       return StatusCode(200, outputContext );
}

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
     services.AddMvc().AddJsonOptions(options =>
            {
                UpdateJsonSettings.ConfigureJsonFormatter(options.SerializerSettings);
            });
}

UpdateJsonSettings.cs

internal static void ConfigureJsonFormatter(JsonSerializerSettings settings)
{
       settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
       settings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
       settings.Converters.Add(new StringEnumConverter());
}

HttpResponse for XYZ Controller Try 1:

{ "$id": "1", "bill": { "$id": "2", "type": "TYPE1",

HttpResponse for XYZ Controller Try 2: -- does not start with $id 1

{ "$id": "28", <--- NOT SURE WHY ON THE SECOND REQUEST $ID starts with 28 :( --> "bill": { "$id": "29", "type": "TYPE1",

HttpResponse for XYZ Controller Try 3: -- does not start with $id 1

{ "$id": "55", <--- NOT SURE WHY ON THE SECOND REQUEST $ID starts with 55 :( --> "bill": { "$id": "56", "type": "TYPE1",

I am using Newtonsoft.Json (11.0.2)

like image 531
Nainesh Patel Avatar asked Jan 21 '20 00:01

Nainesh Patel


2 Answers

I learned this the hard way!

Issue was in StatusCode method, it was returning ObjectResult. After changing method signature to IActionResult and returning JsonResult, it is working fine. Also, API performance is improved.

[HttpPost]
public async Task<IActionResult> Post([FromBody] T inputContext)
{
       var outputContext = Process(inputContext);
       var jsonResult = new JsonResult(outputContext);
       jsonResult.StatusCode = 200;
       return jsonResult;
}
like image 85
Nainesh Patel Avatar answered Oct 12 '22 23:10

Nainesh Patel


I opened a thread on Github to discuss this.

Basically, the problem with StatusCode caching the $id values is because this line of code.

For performance reasons, NewtonsoftJsonOutputFormatter chose to cache JsonSerializer used to serialize objects. This will also cache the DefaultReferenceResolver and its inner counter.

As I said in the Github issue, there is a way to workaround this for each request using a custom IReferenceResolver. But, it would be a long way to work out for each request since the resolver is also cached in a singleton / static context.

like image 36
weichch Avatar answered Oct 12 '22 21:10

weichch