如果我的Customer
类只有简单的属性(例如Name
等),那么我可以创建一个CustomersController
来自ApiController
,并查询我的客户对象使用网址/api/customers
。
同样,如果我的Order
类具有简单属性(Description
,Amount
),那么我可以创建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
答案 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();
完成工作,谢天谢地,没有多少代码要写。