Is it possible to get complex Entity Framework objects from a REST api in .NET without creating ViewModel objects?

Introduce the Entity Framework Entity Set:

public class Country { public string CountryCode { get; set; } public string Name { get; set; } public string Flag { get; set; } } public class Market { public string 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 string Name { get; set; } public virtual ICollection<Market> Markets{ get; set; } } 

Imagine also that DOTNET 5 api GET

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

If markets are not tied to an object, the data is returned without problems, but as soon as I have several related items, I get an error message:

HTTP Error 502.3 - Bad Gateway
The specified CGI application detected an error and the server terminated the process.

I vaguely recall the previous application in which each complex EF object had an object of type "only primitives" for sending and receiving this object to the client and back, but I wonder if there is a way to communicate without intermediary objects?

eg:

 public class ProductViewModel { public int ProductID { get; set; } public string Name { get; set; } public List<MarketViewModel> Markets{ get; set; } } public class MarketViewModel { public int ProductID { get; set; } public Country Country { get; set; } } 

My concern is the overhead of coding to translate each complex object back and forth from the client (which, I admit, I'm not sure if this is even bad, maybe it should be done anyway).

Since the forest APIs seem to take and return entities directly, I wonder if there is a way to handle the complex part of the object directly.

Edit # 1:

Per Noel's comment below if I change the code causing the error

  [HttpGet("{id}", Name = "GetProduct")] public async Task<IActionResult> 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); } 

The stack trace is correctly selected. If I remove the exception, a 500 gateway error will appear. I agree that this seems like a serialization error, but it's hard to say.

EDIT 2 - for a comment from Oleg below:

The bad gateway solution should first explicitly update the newer version of NewtonSoft.Json in the dependencies in the project.json file:

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

Next, you must modify the file Startup.cs

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

with these two settings, the bad gateway no longer occurs, and the api call successfully returns the complex object as expected.

+5
source share
2 answers

It seems to me that you just missed await in a call to SingleAsync . Try using

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

UPDATED . I found a problem . I would recommend you study. You can check package.lock.json to see which version will load by automatically resolving dependencies. Then I would recommend explicitly adding Newtonsoft.Json in the latest version 8.0.1-beta3 to your project dependencies. In addition, you must add the Newtonsoft.Json.ReferenceLoopHandling.Ignore parameter in the SerializerSettings.ReferenceLoopHandling settings. See the question for more details.

+4
source

You can return an anonymous object or use 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<JsonObject>(json); 

// ExpandoObject

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

Source: https://habr.com/ru/post/1238269/


All Articles