ApiController是否可以返回一个带有其他对象集合的对象



如果我有一个Customer类,它只有简单的属性(例如Name等),那么我可以创建一个从ApiController派生的CustomersController,并使用URL /api/customers查询我的Customer对象。

类似地,如果我有一个具有简单属性的Order类(DescriptionAmount),那么我可以创建一个OrdersController并以相同的方式访问它。

但是,如果我随后向Customer类添加一个属性,该属性列出了与该Customer:关联的Order

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    // ...
    public virtual ICollection<Order> Orders { get; set; }
}

那么当我尝试使用CCD_ 13进行查询时,我会得到一个500服务器错误。我可以在CustomersController中放置一个断点,可以看到它确实调用了正确的方法,并尝试返回一个值。然而,在框架的某个核心部分,它未能将其转化为HTTP响应。

看起来它无法序列化Orders信息和/或将其打包以用于HTTP响应,但我不确定需要做什么才能实现这一点。或者仅仅是WebApi的东西不是为了返回复杂的对象而设计的?


更新:我的代码在这里:https://gist.github.com/43ed2f29f8adfb44cef6


更新2:关于我得到的错误的更多信息:

Server error
The website encountered an error while retrieving http://localhost:1031/api/customers/6.

它可能停机进行维护或配置不正确。以下是一些建议:稍后重新加载此网页。HTTP错误500(内部服务器错误):服务器尝试实现时遇到意外情况要求

Intellitrace日志显示以下内容:https://i.stack.imgur.com/8R1XL.png

[我简直不敢相信Intellitrace窗口不允许我复制文本,所以我不得不实际打印屏幕并上传图像。今年是什么年份?]


相关:ASP.Net Web API在VS中正确显示,但给出HTTP500

您正在传递一个实体框架实体,这将导致问题。您需要数据传输对象来传递和接收数据。因为将实体绑定在一起,所以不允许序列化数据。

好的,很抱歉回答了我自己的问题,尤其是在我得到了所有帮助之后(感谢tugberk),但有一个简单的(r)解决方案。

正如tugberk所指出的,问题是我首先使用实体框架代码来处理我的POCO对象。当框架试图序列化我的对象时,它正在序列化EF代理类,而不仅仅是POCO对象。

Tugberk建议使用DTO来传递和接收数据(本质上是为此目的创建新的类),但我真的不想这么做,因为我的POCO类对我来说非常合适,而且有重复的类似乎并不太枯燥。

然后我发现(通过https://stackoverflow.com/a/11386206/98422)我可以在我的控制器中关闭DbContext上的代理生成(如下所示),这将导致POCO对象被序列化,而不是代理类,从而避免500错误:

db.Configuration.ProxyCreationEnabled = false;

不过,这只是解决方案的50%,因为尽管这避免了错误,但它不包括子对象的任何数据。(这些在XML中显示为零)。这是因为我的POCO类是通过EF为延迟加载设置的。为了解决这个问题,我必须显式地加载子对象:

return db.Customers.Include("Orders").AsEnumerable();

工作完成了,谢天谢地没有太多代码要写。

最新更新