Sailing Judo
Sailing Judo

Reputation: 11233

How to stop self-referencing loop in .Net Core Web API?

I'm having some issues which I'm guessing are related to self-referencing using .NET Core Web API and Entity Framework Core. My Web API starting choking when I added .Includes for some navigation properties.

I found what appears to be a solution in the older Web API but I don't know how to implement the same thing for .NET Core Web API (I'm still in the early learning stages).

The older solution was sticking this in the Application_Start() of the Global.asax:

 GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;

I suspect this is handled in the StartUp's ConfigureService() method but I don't know much beyond there.

Or is there a more appropriate way to handle this issue?

Upvotes: 25

Views: 25970

Answers (4)

giorgi02
giorgi02

Reputation: 1073

If you have a Minimal API this will be useful:

using System.Text.Json.Serialization;

builder.Services.Configure<Microsoft.AspNetCore.Http.Json.JsonOptions>(opt =>
{
    opt.SerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
});

Upvotes: 2

Eduard Braun
Eduard Braun

Reputation: 378

If you are using ASP.NET Core 3.0, and experience that problem please install the NuGET package: Microsoft.AspNetCore.Mvc.NewtonsoftJson 3.0.0.

To replace the new System.Text.Json which does not yet have the Reference Loop Handling do this in the Startup.cs, make sure that in the ConfigureServices, is included:

If using the latest .Net Core 3.0 way:

services.AddControllers().AddNewtonsoftJson(options =>
{
    options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});

or the old way:

services.AddMvc(option => option.EnableEndpointRouting = false)
       .AddNewtonsoftJson(options => 
                 options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore)
       .SetCompatibilityVersion(CompatibilityVersion.Version_3_0);

Upvotes: 20

Robert Perry
Robert Perry

Reputation: 1954

ReferenceLoopHandling.Ignore “hides” the problem, not solves it. What you really need to be doing is building layers. Create domain objects to sit on top of your entities and wrap them in some sort of service/business layer. Look up the repository pattern and apply that if it helps. You’ll need to map between your entities and domain objects, and this gives you the chance to fit in some sort of mapper (automapper) and validation layer..

If your domain objects and entities are exactly the same, then you need to think more about what your doing.

For example: Do your entities have soft deletes? (IsDeleted) flag? If so, this doesn’t necessarily need to go back to the client over the web, so that’s a perfect example of where they would be different.

Either way, the answer is not to override it in JSON, it’s to change your architecture..

Upvotes: 7

Sailing Judo
Sailing Judo

Reputation: 11233

Okay... I finally found some reference material on this. The solution is:

public void ConfigureServices(IServiceCollection services)
{
    ...

    services.AddMvc()
        .AddJsonOptions(
            options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
        );

    ...
}

I got this from here

Upvotes: 43

Related Questions