1

この単純な例では、Web Api 2 + OData v4 サービスから JSON としてシリアル化されたオブジェクトを取得しようとしています。コントローラーには、annon の配列を返す関数 Test がバインドされています。オブジェクト。

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);
    }
}

Edm は次のコードで構築されています。

ODataModelBuilder builder = new ODataConventionModelBuilder();

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

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

サービスにリクエストを送信すると (例: http://localhost:9010/odata/Products(33)/Default.Test )、次のような 2 つの空のオブジェクトの配列という奇妙な応答が返されます。

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

私の実際のアプリでは、Newtonsoft の Json コンバーターを使用して、JSON 文字列にシリアル化されたオブジェクトを返しています。これは正常に動作しますが、この問題は依然として私を悩ませています。OData の既定のシリアライザーに関連するものだと思われますが、構成方法がわかりません。

それで、正しくシリアル化された複雑なオブジェクトを取得するような方法で edm 関数の戻りパラメータを構成することは可能ですか?

ありがとう!

4

2 に答える 2

5

lukkea が言ったように、OData は匿名型で動作するようには設計されていません。
コレクションを返す場合は、WebApiConfig で "Returns" を "ReturnsCollection" に変更する必要があります。

とにかく、あなたが次のように書いたとしましょう。

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

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

次のように返されます。

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

配列にはまだ 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;

オプション 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>();

厳密に型指定されていない追加のプロパティを持つ人を返したい場合は、ODataOpenTypeが必要です

于 2016-10-27T11:27:36.493 に答える