想象一组实体框架实体:
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 ICollectionMarkets{ get; set; } }
想象一下DOTNET 5 api GET
// GET api/product [HttpGet] public async TaskGetProduct([FromRoute] int id) { return Ok(await _context.Products .Include(p => p.Markets) .SingleAsync(m => m.ProductID == id)); }
如果实体没有附加市场,数据会毫无问题地返回,但只要我附加了一些链接项,我就会收到错误:
HTTP错误502.3 - 错误的网关
指定的CGI应用程序遇到错误,服务器终止了该进程.
我模糊地回忆起以前的应用程序,其中每个复杂的EF对象都有一个"仅原始"类型的对象来发送和接收客户端的这个对象,但我想知道是否有一种方法可以在没有中间对象的情况下进行通信?
例如:
public class ProductViewModel { public int ProductID { get; set; } public string Name { get; set; } public ListMarkets{ get; set; } } public class MarketViewModel { public int ProductID { get; set; } public Country Country { get; set; } }
我担心的是从客户端来回翻译每个复杂对象的编码开销(我承认,我不确定这是不是一件坏事,也许它必须要完成).
由于脚手架API似乎直接接收和返回实体,我发现自己想知道是否有办法直接处理对象的复杂部分
编辑#1:
Per Noel的评论如下,如果我更改导致错误的代码
[HttpGet("{id}", Name = "GetProduct")] public async TaskGetProduct([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); }
正确抛出堆栈跟踪.如果我删除了异常,则会出现500网关错误.我同意它看起来可能是一个序列化错误,但很难说.
编辑2 - 根据奥列格的评论如下:
坏网关的解决方案是首先显式更新文件中NewtonSoft.Json
依赖项的更新版本project.json
:
"dependencies": { "Newtonsoft.Json": "8.0.1-beta3",
接下来你必须改变Startup.cs
文件
public void ConfigureServices(IServiceCollection services) { services.AddMvc() .AddJsonOptions(options => { options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; });
使用这两个设置后,不再出现坏网关,并且api调用成功返回复杂对象,如预期的那样.