Breeze / breeze.server.net

Breeze support for .NET servers
MIT License
76 stars 62 forks source link

handling many-to-many relationships #96

Closed graphicsxp closed 4 years ago

graphicsxp commented 4 years ago

Doing a quick test with breeze .net core version for handling m-2-m relationships and I come across the object cycle issue with the returned json :

System.Text.Json.JsonException: A possible object cycle was detected which is not supported. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 32.

I can solve the problem with the following setup :

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

But this seems odd. With .net version of breeze the returned json data would contain $ref to avoid duplicating data in the payload. Whereas now I'm just getting the real data in the intermediate entities.

For instance I have the following code for mapping entities involved in a m-2-m association :

  protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<PublishingCompanyFreelancer>().HasKey(pf => new { pf.PublishingCompanyId, pf.FreelancerId });
        modelBuilder.Entity<PublishingCompanyFreelancer>().HasOne(pf => pf.Freelancer)
            .WithMany(f => f.PublishingCompanyFreelancers)
            .HasForeignKey(pf => pf.FreelancerId);
        modelBuilder.Entity<PublishingCompanyFreelancer>().HasOne(pf => pf.PublishingCompany)
            .WithMany(p => p.PublishingCompanyFreelancers)
            .HasForeignKey(pf => pf.PublishingCompanyId);
    }
}

And the resulting Json is as attached. Thanks to the ReferenceLoopHandling.Ignore the loop ends and publishingCompanyFreelancers is not populated on freelancer object.

I don't think this is correct though. Any thoughts ?

image

graphicsxp commented 4 years ago

after some more research I was able to fix this with

 services.AddControllers().AddNewtonsoftJson(options =>
                    options.SerializerSettings.PreserveReferencesHandling = 
                 Newtonsoft.Json.PreserveReferencesHandling.Objects
);

(I removed ReferenceLoopHandling, which becomes irrelevant ). Now the results look better .

image

Now, I am almost certain I didn't have to do that with .net version of breeze, but I guess this is related to how json serializing is handled in .net core, so not related to breeze in the end.

steveschmitt commented 4 years ago

You are right, you need to configure the JSON serialization settings. We have an UpdateWithDefaults helper function that sets the proper Breeze settings, so you can do:

    services.AddControllers().AddNewtonsoftJson(opt => {
        // Set Breeze defaults for entity serialization
        var ss = JsonSerializationFns.UpdateWithDefaults(opt.SerializerSettings);
    });

You can see an example of this in our .NET Core server samples, in the Startup.cs

It's mentioned in the walkthrough of the sample app, but we need to add it to the main Breeze documentation.