0

I have a webapi project that written using C# and built on the top of ASP.NET Core/5 framework.

The API return JSON data.

Here is an example of one endpoint

[HttpGet]
public async Task<ActionResult<TModel[]>> QueryAsync(
   [FromQuery(Name = "filter")] string filter = null,
   [FromQuery(Name = "expand")] string expand = null)
{
    IQueryable<TModel> query = GetQuery(filter, expand);

    var models = await query.ToArrayAsync();

    return Ok(models);
}

In the above request, the expand will tell the server which navigation properties to expand. When the user request to expand a property, I get the following error

A possible object cycle was detected. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 32. Consider using ReferenceHandler.Preserve on JsonSerializerOptions to support cycles

Following the instruction from the error, I added the following to the Startup class

services.AddControllers().AddJsonOptions(options =>
{
    options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
    // added this
    options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve;
});

The above change did fix the problem! However, it introduced another problem. The new problem is that it changed the structure of the output.

The output went from something like this

{
  // properties
 
  "relations": [
     {
         // relation 1
         "parent": null
     },
     {
         // relation 2
         "parent": null
     }
   ]
}

to something like this

{
  "$id": "1",
  // properties
 
  "relations": {
     "$id": "2",
     "$values": [
         {
             // relation 1 properties
             "$id": "3",
             "parent": {
                 "$ref": 1
             }
         },
         {
            // relation 2 properties
            "$id": "3",
            "parent": {
                 "$ref": 1
             }
         }
     ]
   }
}

Is there a way to not change the structure of the output and instead ignore the circular reference?

Jay
  • 1,168
  • 13
  • 41

1 Answers1

0

There is a similar question here, where one of the answers mentions the same issue you're having: .Net Core 3.0 possible object cycle was detected which is not supported

Some of the things mentioned there:

If you're on .NET 6 you can use

JsonSerializerOptions options = new()
{
    ReferenceHandler = ReferenceHandler.IgnoreCycles,
    WriteIndented = true
};

alternatively, depending on what you need to achieve, you might want to just ignore looping properties altogether.

The proper solution though would be to find out where exactly your references are looping and exclude the property(s) in question from serialization, or supply them in a format that doesn't loop (such as an id or similar)

Shrimperator
  • 560
  • 3
  • 13
  • Thank you for that info. Indeed it seem to be what I need. I am using .NET so IgnoreCycles is not available. and ` options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore` does not seems to be available. Any idea how can I set ` options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore`? – Jay Oct 18 '21 at 18:28
  • In the link I provided above, Arsalan Haider has a solution to replace the default asp.net json serializer with newtonsoft, which provides the option you want. for more info, here is a more detailed solution: https://www.thecodebuzz.com/jsonexception-possible-object-cycle-detected-object-depth/comment-page-2/?unapproved=2319&moderation-hash=a3e4421ef39f669454eef3790e21cc08#comment-2319 – Shrimperator Oct 18 '21 at 20:57