Est-il possible d’obtenir des objects Entity Framework complexes à partir d’une API REST dans .NET sans créer d’objects ViewModel?

Imaginez un ensemble d’entités Entity Framework:

public class Country { public ssortingng CountryCode { get; set; } public ssortingng Name { get; set; } public ssortingng Flag { get; set; } } public class Market { public ssortingng CountryCode { get; set; } public virtual Country Country { get; set; } public int ProductID { get; set; } public virtual Product Product { get; set; } } public class Product { public int ProductID { get; set; } public ssortingng Name { get; set; } public virtual ICollection Markets{ get; set; } } 

Imaginez aussi une API DOTNET 5 GET

 // GET api/product [HttpGet] public async Task GetProduct([FromRoute] int id) { return Ok(await _context.Products .Include(p => p.Markets) .SingleAsync(m => m.ProductID == id)); } 

S’il n’y a pas de marché lié à l’entité, les données sont renvoyées sans problème, mais dès que j’ai quelques éléments liés attachés, une erreur se produit:

Erreur HTTP 502.3 – Passerelle incorrecte
L’application CGI spécifiée a rencontré une erreur et le serveur a mis fin au processus.

Je me souviens vaguement d’une application précédente où chaque object EF complexe avait un object de type “primitives uniquement” pour envoyer et recevoir cet object au client, mais je me demande s’il existe un moyen de communiquer sans objects intermédiaires?

par exemple:

 public class ProductViewModel { public int ProductID { get; set; } public ssortingng Name { get; set; } public List Markets{ get; set; } } public class MarketViewModel { public int ProductID { get; set; } public Country Country { get; set; } } 

Ce qui me préoccupe, ce sont les frais de codage liés à la traduction de chaque object complexe du client (et je l’admets, je ne suis même pas sûr que ce soit une mauvaise chose, cela doit peut-être être fait de toute façon).

Comme les API échafaudées semblent prendre et renvoyer directement des entités, je me demande s’il existe un moyen de gérer directement la partie complexe de l’object.

Edit # 1:

Le commentaire de Noel ci-dessous, si je modifie le code à l’origine de l’erreur

  [HttpGet("{id}", Name = "GetProduct")] public async Task GetProduct([FromRoute] int id) { Product product = await _context.Products .Include(t => t.Markets) .SingleAsync(m => m.ProductID == id); throw new System.Exception("error sample"); return Ok(product); } 

la trace de la stack est correctement lancée. Si je supprime l’exception, l’erreur de passerelle 500 apparaît. Je conviens que cela ressemble probablement à une erreur de sérialisation, mais c’est difficile à dire.

EDIT 2 – par un commentaire de Oleg ci-dessous:

La solution à une mauvaise passerelle consiste à mettre explicitement à jour une version plus récente de NewtonSoft.Json dans les dépendances du fichier project.json :

 "dependencies": { "Newtonsoft.Json": "8.0.1-beta3", 

Ensuite, vous devez modifier le fichier Startup.cs .

  public void ConfigureServices(IServiceCollection services) { services.AddMvc() .AddJsonOptions(options => { options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; }); 

Avec ces deux parameters en place, la mauvaise passerelle ne se produit plus et un appel d’api renvoie avec succès l’object complexe comme prévu.

Il me semble que vous avez manqué d’ await l’appel de SingleAsync . Essayez d’utiliser

 [HttpGet] public async Task GetProduct([FromRoute] int id) { return Ok(await _context.Products .Include(p => p.Markets) .SingleAsync(m => m.ProductID == id)); } 

MISE À JOUR : j’ai trouvé le problème . Je vous recommanderais d’examiner Vous pouvez examiner package.lock.json pour voir quelle version sera chargée par la résolution automatique des dépendances. Ensuite, je vous recommanderais d’append explicitement Newtonsoft.Json dans la dernière version 8.0.1-beta3 aux dépendances de votre projet. De plus, vous devez append le paramètre à Newtonsoft.Json.ReferenceLoopHandling.Ignore dans la configuration de SerializerSettings.ReferenceLoopHandling . Voir le numéro pour plus de détails.

Vous pouvez retourner un object anonyme ou utiliser ExpandoObject / JsonObject:

 public HttpResponseMessage Get() { return this.Request.CreateResponse( HttpStatusCode.OK, new { Message = "Hello", Value = 123 }); } 

// JsonObject

 dynamic json = new JsonObject(); json.Message = "Hello"; json.Value = 123; return new HttpResponseMessage(json); 

// ExpandoObject

  dynamic expando = new ExpandoObject(); expando.message = "Hello"; expando.message2 = "World"; return expando;