Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 自引用导航属性和json序列化_C#_Json_Entity Framework_Asp.net Web Api_Navigation Properties - Fatal编程技术网

C# 自引用导航属性和json序列化

C# 自引用导航属性和json序列化,c#,json,entity-framework,asp.net-web-api,navigation-properties,C#,Json,Entity Framework,Asp.net Web Api,Navigation Properties,我有一个公开用户的Web API 每个用户都有一个经理,他也是一个用户 在我的EDMX中,我在“用户”实体上有一个self 1..*导航属性,它是“协作者”,用于从管理者到用户的导航,也是从用户到其管理者的导航的“管理者” 我的JSON API使用NewtonJSON序列化实体 为了定制API调用的JSON结果,我在querystring中实现了关键字“fields”。使用“字段”可以获得用户的部分JSON表示 调用如下所示:/api/users?fields=id、name、departmen

我有一个公开用户的Web API

每个用户都有一个经理,他也是一个用户

在我的EDMX中,我在“用户”实体上有一个self 1..*导航属性,它是“协作者”,用于从管理者到用户的导航,也是从用户到其管理者的导航的“管理者”

我的JSON API使用NewtonJSON序列化实体

为了定制API调用的JSON结果,我在querystring中实现了关键字“fields”。使用“字段”可以获得用户的部分JSON表示

调用如下所示:/api/users?fields=id、name、department、picture

从一个完整的C#user对象中得到一个只包含id、名称、部门和图片属性的JSON

我使用IContractResolver的自定义实现实现了这一点

问题是NewtonJSON契约解析器是“按类型”而不是“按对象”工作的,这意味着您可以告诉序列化程序序列化声明类型的此类成员,而不是另一个成员,但您不能告诉它(据我所知,这就是我在这里询问的原因)序列化此类型对象的此成员,而不是同一类型另一对象上的同一成员

也就是说,我的问题是当我请求:/api/users?fields=id、name、manager时

我在每个用户对象上得到了一个对manager成员重新进行序列化的响应,如下所示:

[{
    id: 123,
    name: "Foo",
    manager:
    {
        id: 124,
        name: "Foo",
        manager:
        {
            id: 125,
            name: "Foo",
            manager:
            {
            ...
            }
        }
    }
},
{
    id: 124,
    name: "Foo",
    manager:
    {
        id: 125,
        name: "Foo",
        manager:
        {
        ...
        }
    }
},
{
    id: 125,
    name: "Foo",
    manager:
    {
    ...
    }
}]
我还实现了请求部分子实体响应的功能,如:

[{
    id: 123,
    name: "Foo",
    manager:
    {
        id: 124,
        name: "Foo",
        manager:
        {
            id: 125,
            name: "Foo",
            manager:
            {
            ...
            }
        }
    }
},
{
    id: 124,
    name: "Foo",
    manager:
    {
        id: 125,
        name: "Foo",
        manager:
        {
        ...
        }
    }
},
{
    id: 125,
    name: "Foo",
    manager:
    {
    ...
    }
}]
/api/用户?字段=id、名称、manager.id

但它不起作用,因为主对象(这里是用户)和子对象(管理器)都是同一类型的

有没有人已经使用NewtonJSON来实现部分响应Web API?如何处理嵌入的自类型实体


感谢您的建议。

您可以编写一个操作筛选器,以了解fields参数并转换响应。我有一个将响应对象转换为字典的示例实现。键是客户端请求的字段,值是响应中返回的对象的字段值。该实现是一个示例,没有接近完成的地方:)

公共类FieldFilterAttribute:ActionFilterAttribute
{
公共覆盖无效OnActionExecuted(HttpActionExecuteContext ActionExecuteContext)
{
var fieldsParameter=actionExecutedContext.Request.GetQueryNameValuePairs()。其中(kvp=>kvp.Key==“字段”);
if(fieldsParameter.Count()==1)
{
目标反应;
客体反应;
if(actionExecutedContext.Response.TryGetContentValue(out响应))
{
string[]fields=fieldsParameter.First().Value.Split(',');
IEnumerable collection=响应为IEnumerable;
if(集合!=null)
{
newResponse=collection.Select(o=>SelectFields(fields,o));
}
其他的
{
newResponse=选择字段(字段,响应);
}
ActionExecuteContext.Response=ActionExecuteContext.Request.CreateResponse(HttpStatusCode.OK,newResponse);
}
}
}
私有静态字典SelectFields(字符串[]字段,对象值)
{
字典结果=新字典();
foreach(字段中的字符串字段)
{
添加(字段,获取值(字段,值));
}
返回结果;
}
私有静态对象GetValue(字符串索引器,对象值)
{
字符串[]indexer=indexer.Split('.');
foreach(索引器中的字符串属性)
{
PropertyInfo PropertyInfo=value.GetType().GetProperty(属性);
如果(propertyInfo==null)
{
抛出新异常(String.Format(“在类型“{1}”上找不到属性“{0}”,属性,value.GetType());
}
value=propertyInfo.GetValue(值);
如果(值==null)
{
返回null;
}
}
返回值;
}
}

< /代码>您可能需要考虑解析字段。它具有更好的表达式处理能力,还可以处理更复杂的表达式。缺点是您必须更加小心,以避免远程代码执行。此外,您想要的功能已经存在于OData协议中,即和。您可能想考虑将您的服务实现为ODATA服务:“谢谢@拉格兰姆为您的例子,这是一个非常有趣的观点。然而,我的印象是,您根本不使用合同解析器,而且我无法避免使用它,因为它除了处理我当前的问题之外,还处理其他事情。我也会看看OData。在一些国家,暴露用户可能是非法的。