ApiController可以返回带有其他对象集合的对象吗?

时间:2012-07-22 13:38:27

标签: c# asp.net-mvc-4 asp.net-web-api

如果我的Customer类只有简单的属性(例如Name等),那么我可以创建一个CustomersController来自ApiController,并查询我的客户对象使用网址/api/customers

同样,如果我的Order类具有简单属性(DescriptionAmount),那么我可以创建OrdersController并以相同的方式访问它。< / p>

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

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

...然后当我尝试使用/api/customers进行查询时,我收到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日志显示以下内容:http://i.imgur.com/iHxJl.png

[我很难相信Intellitrace窗口不允许我复制文本,因此我必须实际打印屏幕并上传图像。这是哪一年?]


相关:ASP.Net Web API showing correctly in VS but giving HTTP500

2 个答案:

答案 0 :(得分:7)

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

答案 1 :(得分:3)

好的,为回答我自己的问题道歉,特别是在我收到的所有帮助之后(感谢tugberk),但有一个简单的(r)解决方案。

正如tugberk指出的那样,问题在于我使用Entity Framework代码优先处理我的POCO对象。当框架尝试序列化我的对象时,它正在序列化EF代理类而不仅仅是POCO对象。

Tugberk建议使用DTO传递和接收数据(基本上是为此目的创建新类),但我真的不想这样做,因为我的POCO类看起来非常适合我,并且有重复的类不会看起来很干。

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

db.Configuration.ProxyCreationEnabled = false;

但这只是解决方案的50%,因为虽然这避免了错误,但它没有包含子对象的任何数据。 (那些在XML中以nil表示)。那是因为我的POCO类被设置为通过EF进行延迟加载。为了解决这个问题,我必须显式加载子对象:

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

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