ASP.NET Web API 2 OData'da $select, $expand ve $value kullanma
tarafından Mike Wasson
ASP.NET 4.x için OData Web API 2'deki $expand, $select ve $value seçeneklerine genel bakış ve kod örnekleri. Bu seçenekler, istemcinin sunucudan geri aldığı gösterimi denetlemesine olanak sağlar.
- $expand ilgili varlıkların yanıta satır içinde eklenmesine neden olur.
- $select yanıta eklenecek özelliklerin bir alt kümesini seçer.
- $value bir özelliğin ham değerini alır.
Örnek Şema
Bu makale için üç varlığı tanımlayan bir OData hizmeti kullanacağım: Product, Supplier ve Category. Her ürünün bir kategorisi ve bir tedarikçisi vardır.
Varlık modellerini tanımlayan C# sınıfları şunlardır:
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; }
}
sınıfının ve Category
için Supplier
gezinti özelliklerini tanımladığını Product
fark edin. Category
sınıfı, her kategorideki ürünler için bir gezinti özelliği tanımlar.
Bu şema için bir OData uç noktası oluşturmak için, ASP.NET Web API'sinde OData Uç Noktası Oluşturma bölümünde açıklandığı gibi Visual Studio 2013 yapı iskelesini kullanın. Ürün, Kategori ve Tedarikçi için ayrı denetleyiciler ekleyin.
$expand ve $select etkinleştirme
Visual Studio 2013'de, Web API OData iskelesi $expand ve $select otomatik olarak destekleyen bir denetleyici oluşturur. Başvuru için, bir denetleyicide $expand ve $select destekleme gereksinimleri aşağıdadır.
Koleksiyonlar için denetleyicinin Get
yöntemi bir IQueryable döndürmelidir.
[Queryable]
public IQueryable<Category> GetCategories()
{
return db.Categories;
}
Tek varlıklar için, bir SingleResult<T> döndürür; burada T sıfır veya bir varlık içeren bir IQueryable'dır .
[Queryable]
public SingleResult<Category> GetCategory([FromODataUri] int key)
{
return SingleResult.Create(db.Categories.Where(c => c.ID == key));
}
Ayrıca, önceki kod parçacıklarında gösterildiği gibi yöntemlerinizi Get
[Queryable] özniteliğiyle süsleyin. Alternatif olarak, başlangıçta HttpConfiguration nesnesinde EnableQuerySupport'u çağırın. (Daha fazla bilgi için bkz . OData Sorgu Seçeneklerini Etkinleştirme.)
$expand kullanma
Bir OData varlığını veya koleksiyonunu sorguladığınızda, varsayılan yanıt ilgili varlıkları içermez. Örneğin, Kategoriler varlık kümesi için varsayılan yanıt aşağıda verilmiştir:
{
"odata.metadata":"http://localhost/odata/$metadata#Categories",
"value":[
{"ID":1,"Name":"Apparel"},
{"ID":2,"Name":"Toys"}
]
}
Gördüğünüz gibi, Kategori varlığında Ürünler gezinti bağlantısı olsa bile yanıt hiçbir ürün içermez. Ancak istemci, her kategoriye ait ürünlerin listesini almak için $expand kullanabilir. $expand seçeneği isteğin sorgu dizesine gider:
GET http://localhost/odata/Categories?$expand=Products
Artık sunucu her kategoriye ait ürünleri kategorilerle satır içi olarak içerecektir. Yanıt yükü şu şekildedir:
{
"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" dizisindeki her girişin bir Ürünler listesi içerdiğine dikkat edin.
$expand seçeneği, genişletmek için gezinti özelliklerinin virgülle ayrılmış bir listesini alır. Aşağıdaki istek, bir ürünün hem kategorisini hem de tedarikçisini genişletir.
GET http://localhost/odata/Products(1)?$expand=Category,Supplier
Yanıt gövdesi aşağıdadır:
{
"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"
}
Birden fazla gezinti özelliği düzeyini genişletebilirsiniz. Aşağıdaki örnek, bir kategoriye ilişkin tüm ürünleri ve her ürünün tedarikçisini içerir.
GET http://localhost/odata/Categories(1)?$expand=Products/Supplier
Yanıt gövdesi aşağıdadır:
{
"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"
}
Varsayılan olarak, Web API'si maksimum genişletme derinliğini 2 ile sınırlar. Bu, istemcinin gibi $expand=Orders/OrderDetails/Product/Supplier/Region
büyük yanıtları sorgulamak ve oluşturmak için verimsiz olabilecek karmaşık istekler göndermesini engeller. Varsayılanı geçersiz kılmak için [Queryable] özniteliğinde MaxExpansionDepth özelliğini ayarlayın.
[Queryable(MaxExpansionDepth=4)]
public IQueryable<Category> GetCategories()
{
return db.Categories;
}
$expand seçeneği hakkında daha fazla bilgi için resmi OData belgelerindeki Sistem Sorgu Seçeneğini ($expand) Genişletme bölümüne bakın.
$select kullanma
$select seçeneği, yanıt gövdesine eklenecek özelliklerin bir alt kümesini belirtir. Örneğin, her ürünün yalnızca adını ve fiyatını almak için aşağıdaki sorguyu kullanın:
GET http://localhost/odata/Products?$select=Price,Name
Yanıt gövdesi aşağıdadır:
{
"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 ve $expand aynı sorguda birleştirebilirsiniz. genişletilmiş özelliğini $select seçeneğine eklediğinizden emin olun. Örneğin, aşağıdaki istek ürün adını ve sağlayıcıyı alır.
GET http://localhost/odata/Products?$select=Name,Supplier&$expand=Supplier
Yanıt gövdesi aşağıdadır:
{
"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"
}
]
}
Genişletilmiş bir özellik içindeki özellikleri de seçebilirsiniz. Aşağıdaki istek Ürünler'i genişletir ve kategori adı ile ürün adını seçer.
GET http://localhost/odata/Categories?$expand=Products&$select=Name,Products/Name
Yanıt gövdesi aşağıdadır:
{
"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 seçeneği hakkında daha fazla bilgi için resmi OData belgelerindeki Sistem Sorgusu Seçeneğini ($select) Seçme bölümüne bakın.
Varlığın Tek Tek Özelliklerini Alma ($value)
OData istemcisinin bir varlıktan tek bir özelliği alması için iki yol vardır. İstemci değeri OData biçiminde alabilir veya özelliğin ham değerini alabilir.
Aşağıdaki istek OData biçiminde bir özellik alır.
GET http://localhost/odata/Products(1)/Name
JSON biçiminde bir örnek yanıt aşağıda verilmiştir:
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"
}
Özelliğin ham değerini almak için URI'ye $value ekleme:
GET http://localhost/odata/Products(1)/Name/$value
Yanıtı burada bulabilirsiniz. İçerik türünün JSON değil "text/plain" olduğuna dikkat edin.
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
DataServiceVersion: 3.0
Content-Length: 3
Hat
OData denetleyicinizde bu sorguları desteklemek için, özelliğinin adı olan Property
adlı GetProperty
bir yöntem ekleyin. Örneğin, Name özelliğini alma yöntemi olarak adlandırılır GetName
. yöntemi bu özelliğin değerini döndürmelidir:
public async Task<IHttpActionResult> GetName(int key)
{
Product product = await db.Products.FindAsync(key);
if (product == null)
{
return NotFound();
}
return Ok(product.Name);
}