带有OData v4的Web Api 2 - 返回复杂对象的绑定函数

Gor*_*n F 1 json odata asp.net-web-api-odata asp.net-web-api2 odata-v4

在这个简单的例子中,我试图从Web Api 2 + OData v4服务获取一个序列化为JSON的对象.控制器具有绑定功能Test,它返回一个annon数组.对象.

public class ProductsController : ODataController
{
    [HttpGet]
    public IHttpActionResult Test(int key)
    {
        var res = new[]
        {
            new { Name = "a", Value = new[] { 1, 2, 3 } },
            new { Name = "b", Value = new[] { 2, 4, 5 } }

            // this also produces same result
            // new { Name = "a", Value = "c" },
            // new { Name = "b", Value = "c" }
        };

        return this.Ok(res);
    }
}
Run Code Online (Sandbox Code Playgroud)

Edm是用这段代码构建的:

ODataModelBuilder builder = new ODataConventionModelBuilder();

builder.EntitySet<Product>("Products");
var productType = builder.EntityType<Product>();

var f = productType.Function("Test").Returns<object>();
Run Code Online (Sandbox Code Playgroud)

当我向服务发出请求时(例如http:// localhost:9010/odata/Products(33)/Default.Test)我得到一个奇怪的响应 - 一个包含两个空对象的数组,如下所示:

{
  "@odata.context": "http://localhost:9010/odata/$metadata#Collection(System.Object)",
  "value": [
    {},
    {}
  ]
}
Run Code Online (Sandbox Code Playgroud)

在我的真实应用程序中,我将使用Newtonsoft的Json转换器将对象序列化为JSON字符串 - 工作正常,但这个问题仍然困扰着我.我怀疑它与OData的默认序列化程序有关,但我不清楚如何配置它.

那么,是否有可能以这种方式配置edm函数的返回参数,我将获得正确的序列化复杂对象?

谢谢!

gor*_*oth 5

正如lukkea所说,OData不适用于匿名类型.
旁注,在WebApiConfig中,如果要返回集合,则应将"返回"更改为"ReturnsCollection".

无论如何,我们假设你写了以下内容.

return this.Ok(Newtonsoft.Json.JsonConvert.SerializeObject(res));

var f = productType.Function("Test").Returns<string>();
Run Code Online (Sandbox Code Playgroud)

你会得到以下回复:

{
    "@odata.context": "http://localhost/Test/odata/$metadata#Edm.String",
    "value": 
        "[
            {\"Name\":\"a\",\"Value\":[1,2,3]},
            {\"Name\":\"b\",\"Value\":[2,4,5]}
        ]"
}
Run Code Online (Sandbox Code Playgroud)

请注意,数组中仍有2个项目,但这次它们不是空的.
由于OData在前一个示例中不知道返回类型,因此它返回没有值的2个对象.

你有2个选择.

  1. 将匿名类型作为序列化的json字符串返回,然后在客户端反序列化该json.
  2. 创建一个类并返回该类型.

选项1

// ON SERVER
return this.Ok(Newtonsoft.Json.JsonConvert.SerializeObject(res));

var f = productType.Function("Test").Returns<string>();

// ON CLIENT
string jsonString = odataContext.Products.ByKey(33).Test().GetValue();  
var objectList = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(jsonString);  

string firstObjectName = objectList[0].Name;
Run Code Online (Sandbox Code Playgroud)

选项2

// ON SERVER  
public class TestObject
{
    public string Name { get; set; }
    public List<int> Integers { get; set; }
}

var res = new List<TestObject>
{
     new TestObject { Name = "a", Integers = new List<int> { 1, 2, 3 } },
     new TestObject { Name = "b", Integers = new List<int> { 2, 4, 5 } }
};

return this.Ok(res);  

var f = productType.Function("Test").ReturnsCollection<TestObject>();
Run Code Online (Sandbox Code Playgroud)

如果要返回具有非强类型的额外属性的人,则需要ODataOpenType