ASP.NET Web API 2 OData で $select, $expand, および $value を使用するUsing $select, $expand, and $value in ASP.NET Web API 2 OData

作成者Mike Wassonby Mike Wasson

$ の概要およびコード サンプルを展開し、$select と ASP.NET の場合、この $value は OData Web API 2 でオプション 4.x です。Overview and code samples for the $expand, $select, and $value options in OData Web API 2 for ASP.NET 4.x. これらのオプションは、サーバーから返された形式を制御することをクライアントに許可します。These options allow a client to control the representation that it gets back from the server.

  • $expand は、応答にインラインで含まれる関連するエンティティを発生させます。$expand causes related entities to be included inline in the response.
  • $selectは、応答に含めるプロパティのサブセットを選択します。$select selects a subset of properties to include in the response.
  • $valueは、プロパティの未加工の値を取得します。$value gets the raw value of a property.

スキーマの例Example Schema

この記事では、3 つのエンティティを定義する OData サービスを使用します。製品、仕入先、およびカテゴリ。For this article, I'll use an OData service that defines three entities: Product, Supplier, and Category. 各製品には、1 つのカテゴリと仕入先の 1 つがあります。Each product has one category and one supplier.

エンティティ モデルを定義する c# クラスを次に示します。Here are the C# classes that define the entity models:

public class Supplier
{
    [Key]
    public string Key {get; set; }
    public string Name { get; set; }
}
public class Category
{
    public int ID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Product> Products { get; set; }
}

public class Product
{
    public int ID { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }

    [ForeignKey("Category")]
    public int CategoryId { get; set; }
    public Category Category { get; set; }

    [ForeignKey("Supplier")]
    public string SupplierId { get; set; }
    public virtual Supplier Supplier { get; set; }
}

注意、Productクラスのナビゲーション プロパティを定義、SupplierCategoryします。Notice that the Product class defines navigation properties for the Supplier and Category. Categoryクラスは、各カテゴリの製品のナビゲーション プロパティを定義します。The Category class defines a navigation property for the products in each category.

このスキーマの OData エンドポイントを作成するには、Visual Studio 2013 のスキャフォールディングを」の説明に従って使用で ASP.NET Web API OData エンドポイントを作成するします。To create an OData endpoint for this schema, use the Visual Studio 2013 scaffolding, as described in Creating an OData Endpoint in ASP.NET Web API. 製品、カテゴリ、および仕入先の別のコント ローラーを追加します。Add separate controllers for Product, Category, and Supplier.

$ の有効化を展開し、$selectEnabling $expand and $select

Visual Studio 2013 では、Web API OData のスキャフォールディングは、その $ の展開を自動的にサポートおよび $select にコント ローラーを作成します。In Visual Studio 2013, the Web API OData scaffolding creates a controller that automatically supports $expand and $select. リファレンスについては、ここでは $ をサポートするための要件を展開し、コント ローラーの $select します。For reference, here are the requirements to support $expand and $select in a controller.

コレクションの場合、コント ローラーのGetメソッドが返す必要があります、 IQueryableします。For collections, the controller's Get method must return an IQueryable.

[Queryable]
public IQueryable<Category> GetCategories()
{
    return db.Categories;
}

単一のエンティティを返す、 SingleResult<T>、T は、 IQueryable 0 または 1 つのエンティティを格納しています。For single entities, return a SingleResult<T>, where T is an IQueryable that contains zero or one entities.

[Queryable]
public SingleResult<Category> GetCategory([FromODataUri] int key)
{
    return SingleResult.Create(db.Categories.Where(c => c.ID == key));
}

また、装飾、Getメソッド、 [Queryable] 属性は、前のコード スニペットで示すように。Also, decorate your Get methods with the [Queryable] attribute, as shown in the previous code snippets. 代わりに、呼び出すEnableQuerySupport上、 HttpConfigurationスタートアップ時のオブジェクト。Alternatively, call EnableQuerySupport on the HttpConfiguration object at startup. (詳細については、次を参照してくださいOData クエリ オプションを有効にする。)。(For more information, see Enabling OData Query Options.)

$ を使用して展開Using $expand

OData エンティティまたはコレクションを照会するときに、既定の応答に関連するエンティティは含まれません。When you query an OData entity or collection, the default response does not include related entities. たとえば、カテゴリ エンティティ セットの既定の応答を次に示します。For example, here is the default response for the Categories entity set:

{
  "odata.metadata":"http://localhost/odata/$metadata#Categories",
  "value":[
    {"ID":1,"Name":"Apparel"},
    {"ID":2,"Name":"Toys"}
  ]
}

ご覧のように、応答は含まれません任意の製品では、Category エンティティは製品のナビゲーション リンク。As you can see, the response does not include any products, even though the Category entity has a Products navigation link. ただし、クライアントは $ を使用できる展開すると、各カテゴリの製品の一覧を取得します。However, the client can use $expand to get the list of products for each category. $Expand オプションを展開し、要求のクエリ文字列には。The $expand option goes in the query string of the request:

GET http://localhost/odata/Categories?$expand=Products

これで、サーバー カテゴリごとに、インラインで、カテゴリの製品が含まれます。Now the server will include the products for each category, inline with the categories. 応答ペイロードを次に示します。Here is the response payload:

{
  "odata.metadata":"http://localhost/odata/$metadata#Categories",
  "value":[
    {
      "Products":[
        {"ID":1,"Name":"Hat","Price":"15.00","CategoryId":1,"SupplierId":"CTSO"},
        {"ID":2,"Name":"Scarf","Price":"12.00","CategoryId":1,"SupplierId":"CTSO"},
        {"ID":3,"Name":"Socks","Price":"5.00","CategoryId":1,"SupplierId":"FBRK"}
      ],
      "ID":1,
      "Name":"Apparel"
    },
    {
      "Products":[
        {"ID":4,"Name":"Yo-yo","Price":"4.95","CategoryId":2,"SupplierId":"WING"},
        {"ID":5,"Name":"Puzzle","Price":"8.00","CategoryId":2,"SupplierId":"WING"}
      ],
      "ID":2,
      "Name":"Toys"
    }
  ]
}

"Value"配列内の各エントリに製品一覧が含まれていることを確認します。Notice that each entry in the "value" array contains a Products list.

$ では、展開するナビゲーション プロパティのオプションはコンマ区切りの一覧を展開します。The $expand option takes a comma-separated list of navigation properties to expand. 次の要求は、カテゴリと製品の仕入先の両方を展開します。The following request expands both the category and the supplier for a product.

GET http://localhost/odata/Products(1)?$expand=Category,Supplier

応答本文を次に示します。Here is the response body:

{
  "odata.metadata":"http://localhost/odata/$metadata#Products/@Element",
  "Category": {"ID":1,"Name":"Apparel"},
  "Supplier":{"Key":"CTSO","Name":"Contoso, Ltd."},
  "ID":1,
  "Name":"Hat",
  "Price":"15.00",
  "CategoryId":1,
  "SupplierId":"CTSO"
}

ナビゲーション プロパティの 1 つ以上のレベルを展開することができます。You can expand more than one level of navigation property. 次の例には、カテゴリのすべての製品と各製品の仕入先が含まれます。The following example includes all the products for a category and also the supplier for each product.

GET http://localhost/odata/Categories(1)?$expand=Products/Supplier

応答本文を次に示します。Here is the response body:

{
  "odata.metadata":"http://localhost/odata/$metadata#Categories/@Element",
  "Products":[
    {
      "Supplier":{"Key":"CTSO","Name":"Contoso, Ltd."},
      "ID":1,"Name":"Hat","Price":"15.00","CategoryId":1,"SupplierId":"CTSO"
    },
    {
      "Supplier":{"Key":"CTSO","Name":"Contoso, Ltd."},
      "ID":2,"Name":"Scarf","Price":"12.00","CategoryId":1,"SupplierId":"CTSO"
    },{
      "Supplier":{
        "Key":"FBRK","Name":"Fabrikam, Inc."
      },"ID":3,"Name":"Socks","Price":"5.00","CategoryId":1,"SupplierId":"FBRK"
    }
  ],"ID":1,"Name":"Apparel"
}

既定では、Web API は、2、最大の深さを制限します。By default, Web API limits the maximum expansion depth to 2. ような複雑な要求を送信することから、クライアントを妨げる$expand=Orders/OrderDetails/Product/Supplier/Region、効率的にクエリを実行し、大規模な応答を作成するがあります。That prevents the client from sending complex requests like $expand=Orders/OrderDetails/Product/Supplier/Region, which might be inefficient to query and create large responses. 既定値を上書きするには、設定、 MaxExpansionDepthプロパティを [Queryable] 属性。To override the default, set the MaxExpansionDepth property on the [Queryable] attribute.

[Queryable(MaxExpansionDepth=4)]
public IQueryable<Category> GetCategories()
{
    return db.Categories;
}

$ の詳細については、オプションを展開するを参照してください。 Expand システム クエリ オプション ($ の展開) 、公式の OData ドキュメント。For more information about the $expand option, see Expand System Query Option ($expand) in the official OData documentation.

$Select を使用します。Using $select

$Select オプションでは、応答本文に含めるプロパティのサブセットを指定します。The $select option specifies a subset of properties to include in the response body. たとえば、名前と各製品の価格を取得するには、次のクエリを使用します。For example, to get only the name and price of each product, use the following query:

GET http://localhost/odata/Products?$select=Price,Name

応答本文を次に示します。Here is the response body:

{
  "odata.metadata":"http://localhost/odata/$metadata#Products&$select=Price,Name",
  "value":[
    {"Price":"15.00","Name":"Hat"},
    {"Price":"12.00","Name":"Scarf"},
    {"Price":"5.00","Name":"Socks"},
    {"Price":"4.95","Name":"Yo-yo"},
    {"Price":"8.00","Name":"Puzzle"}
  ]
}

$Select を組み合わせることができ、$ が同じクエリ内で展開します。You can combine $select and $expand in the same query. $Select オプションに展開されたプロパティを含めるに確認します。Make sure to include the expanded property in the $select option. たとえば、次の要求は、業者と製品の名前を取得します。For example, the following request gets the product name and supplier.

GET http://localhost/odata/Products?$select=Name,Supplier&$expand=Supplier

応答本文を次に示します。Here is the response body:

{
  "odata.metadata":"http://localhost/odata/$metadata#Products&$select=Name,Supplier",
  "value":[
    {
      "Supplier":{"Key":"CTSO","Name":"Contoso, Ltd."},
      "Name":"Hat"
    },
    {
      "Supplier":{"Key":"CTSO","Name":"Contoso, Ltd."},
      "Name":"Scarf"
    },
    {
      "Supplier":{"Key":"FBRK","Name":"Fabrikam, Inc."},
      "Name":"Socks"
    },
    {
      "Supplier":{"Key":"WING","Name":"Wingtip Toys"},
      "Name":"Yo-yo"
    },
    {
      "Supplier":{"Key":"WING","Name":"Wingtip Toys"},
      "Name":"Puzzle"
   }
  ]
}

展開のプロパティ内のプロパティを選択することもできます。You can also select the properties within an expanded property. 次の要求では、製品を展開し、カテゴリ名と製品名を選択します。The following request expands Products and selects category name plus product name.

GET http://localhost/odata/Categories?$expand=Products&$select=Name,Products/Name

応答本文を次に示します。Here is the response body:

{
  "odata.metadata":"http://localhost/odata/$metadata#Categories&$select=Name,Products/Name",
  "value":[ 
    {
      "Products":[ {"Name":"Hat"},{"Name":"Scarf"},{"Name":"Socks"} ],
      "Name":"Apparel"
    },
    {
      "Products":[ {"Name":"Yo-yo"},{"Name":"Puzzle"} ],
      "Name":"Toys"
    }
  ]
}

$Select オプションの詳細については、次を参照してください。 Select システム クエリ オプション ($select) 、公式の OData ドキュメント。For more information about the $select option, see Select System Query Option ($select) in the official OData documentation.

エンティティ ($value) の個々 のプロパティを取得します。Getting Individual Properties of an Entity ($value)

エンティティから個々 のプロパティを取得する OData クライアントの 2 つの方法はあります。There are two ways for an OData client to get an individual property from an entity. クライアントでは、OData の形式で値を取得することまたは、プロパティの生の値を取得できます。The client can either get the value in OData format, or get the raw value of the property.

次の要求は、OData 形式でプロパティを取得します。The following request gets a property in OData format.

GET http://localhost/odata/Products(1)/Name

JSON 形式で応答の例を示します。Here is an example response in JSON format:

HTTP/1.1 200 OK
Content-Type: application/json; odata=minimalmetadata; streaming=true; charset=utf-8
DataServiceVersion: 3.0
Content-Length: 90

{
  "odata.metadata":"http://localhost:14239/odata/$metadata#Edm.String",
  "value":"Hat"
}

プロパティの生の値を取得するには、URI に $value を追加します。To get the raw value of the property, append $value to the URI:

GET http://localhost/odata/Products(1)/Name/$value

応答を次に示します。Here is the response. コンテンツの種類が"text/plain"、JSON に注意してください。Notice that the content type is "text/plain", not JSON.

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
DataServiceVersion: 3.0
Content-Length: 3

Hat

という名前のメソッドを追加すると、OData コント ローラーでこれらのクエリをサポートするためにGetPropertyここで、Propertyプロパティの名前を指定します。To support these queries in your OData controller, add a method named GetProperty, where Property is the name of the property. たとえば、Name プロパティを取得するメソッドを名前はGetNameします。For example, the method to get the Name property would be named GetName. メソッドは、そのプロパティの値を返す必要があります。The method should return the value of that property:

public async Task<IHttpActionResult> GetName(int key)
{
    Product product = await db.Products.FindAsync(key);
    if (product == null)
    {
        return NotFound();
    }
    return Ok(product.Name);
}