带有OData和实体框架的Web API - 序列化问题

时间:2014-08-14 17:56:46

标签: c# json entity-framework asp.net-web-api odata

在我的Web API应用中,如果我在Get方法中使用OData来过滤结果,我会得到不一致的结果。没有OData过滤器,结果很好。 使用OData时序列化的处理方式不同吗? 我这样做是否正确?

使用OData:

enter image description here

我不明白$ ref条目是什么,为什么它们是随机的,为什么我不在使用OData时得到它们?

以下是Web API方法:

public HttpResponseMessage Get(System.Web.Http.OData.Query.ODataQueryOptions<Employee> options)
        {
            HttpResponseMessage response;

            var employees = options.ApplyTo(_unitOfWork.EmployeeRepository.Get());

            if (employees == null)
            {
                response = new HttpResponseMessage(HttpStatusCode.NotFound);
            }
            else
            {
                response = Request.CreateResponse(HttpStatusCode.OK, employees);
                response.Content.Headers.Expires = new DateTimeOffset(DateTime.Now.AddSeconds(300));
            }
            return response;
        }

这是要序列化的类:

 public class Employee
    {
        [Key]
        public string WinId { get; set; }
        public string XML { get; set; }
        public int EffectiveYear { get; set; }
        public int FileKeeperGroupId { get; set; }
    }

编辑8/15

这是我的WebApiConfig

 var json = config.Formatters.JsonFormatter;
            config.Formatters.Clear();
            config.Formatters.Add(json);
            config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = 
                Newtonsoft.Json.PreserveReferencesHandling.None;

2 个答案:

答案 0 :(得分:1)

弃用答案:
如本主题Entity relations in odata-v4中所述,请查看以下部分:

创建实体之间的关系

  

OData支持创建或删除两个现有关系   实体。在OData v4术语中,该关系是“参考”。   (在OData v3中,这种关系被称为链接。协议   差异与本教程无关。)

     

引用有自己的URI和表单   /实体/ NavigationProperty / $ REF。例如,这是URI的   解决产品与供应商之间的参考:

     

HTTP:/主机/产品(1)/供应商/ $ REF

因此,基本上它是odata知道哪个实体具有另一个实体的导航属性的方式。 WebApi不知道知道什么是什么,它所做的只是服务数据。但是,使用OData,您可以在 URL本身中创建客户端查询,而不是在c#的后端使用linq(就像您对Web api一样)。为了让odata正确查询后端,需要了解db上下文中的所有实体和关系;这是通过首先检查从ODataController服务的$元数据来完成的。您可以通过查看

来验证这一点
http://localhost/api/User/$metadata

注意:假设您的控制器名为UserController

请阅读有关odata的更多信息,并习惯odata需要这些额外信息围绕您的数据,以便正确理解您的数据库。如果你不完全满意,你总是可以在c#中编写你的linq查询,并坚持使用webapi(虽然你确实失去了odata的一些优点,你可以自己研究)。

新答案(8/15)
编辑:根据下面的评论,它肯定是导致问题而不是OData序列化的json序列化。找到设置的好工作,因为这个站点:PreserveReferenceHandling,讨论了在JSON响应中保留引用的配置。

我们意识到$ ref用于OData中的导航属性,我们还发现$ ref用于在序列化和反序列化json时跟踪对象引用。

就个人而言,我宁愿将$ ref留在那里,因为JSON.NET非常聪明,可以发现循环引用。如果你不相信我,请查看这篇文章:Serializing Circular References。但这都是个人偏好。

答案 1 :(得分:-1)

从描述中可以看出,你不熟悉OData概念(如果我做了错误的观察,请纠正我)。 OData是用于编写RESTful服务和客户端的开放标准(an OASIS standard),并且在OData中定义了某些约定和规则,它们与其他类型的RESTful服务不同。 ASP.NET Web API支持OData版本1-3和OData版本4.0。如果您希望在Web API服务中启用此类支持,您应该知道您正在编写OData服务,并且只有OData特定客户端才能与您的服务进行通信。

在OData中处理序列化与处理常见Web API服务的方式有很大不同。原因是OData具有非常特殊的有效负载类型,需要特殊处理。我们以OData V4 JSON有效载荷为例。它有很多OData特定的JSON元素和属性,而常见的JSON有效负载处理程序并不具备特殊的知识。

您附加的有效负载不是OData有效负载,也不是您附加OData控制器操作的控制器操作。对于编写OData服务,可以参考ASP.NET learning site以获取详细信息。