3

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

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

但是,如果我随后将一个属性添加到我的Customer类中,该属性列出了Order与该关联的 s 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 在 VS 中正确显示但给出 HTTP500

4

2 回答 2

7

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

于 2012-07-22T22:36:56.043 回答
3

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

正如 tugberk 指出的那样,问题在于我使用实体框架代码优先处理我的 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();

工作完成了,幸好没有多少代码要写。

于 2012-07-23T09:34:20.523 回答