ASP.NET Web API 2 Odata'da Yönlendirme Kuralları
Bu makalede, ASP.NET 4.x'teki Web API 2'nin OData uç noktaları için kullandığı yönlendirme kuralları açıklanmaktadır.
Web API'si bir OData isteği aldığında, isteği bir denetleyici adı ve bir eylem adıyla eşler. Eşleme HTTP yöntemini ve URI'yi temel alır. Örneğin, GET /odata/Products(1)
ile ProductsController.GetProduct
eşler.
Bu makalenin 1. bölümünde, yerleşik OData yönlendirme kurallarını açıkliyorum. Bu kurallar OData uç noktaları için özel olarak tasarlanmıştır ve varsayılan Web API yönlendirme sisteminin yerini alır. ( MapODataRoute'u çağırdığınızda değiştirme gerçekleşir.)
2. bölümde özel yönlendirme kurallarının nasıl ekleneceğini gösteriyorum. Şu anda yerleşik kurallar tüm OData URI'lerini kapsamaz, ancak bunları ek durumları işleyecek şekilde genişletebilirsiniz.
Yerleşik Yönlendirme Kuralları
Web API'sinde OData yönlendirme kurallarını açıklamadan önce OData URI'lerini anlamak yararlı olacaktır. OData URI'leri şunlardan oluşur:
- Hizmet kökü
- Kaynak yolu
- Sorgu seçenekleri
Yönlendirme için önemli olan kaynak yoludur. Kaynak yolu segmentlere ayrılır. Örneğin, /Products(1)/Supplier
üç segmenti vardır:
Products
"Products" adlı bir varlık kümesini ifade eder.1
, kümeden tek bir varlık seçen bir varlık anahtarıdır.Supplier
ilgili varlığı seçen bir gezinti özelliğidir.
Bu yol, ürün 1'in tedarikçisini seçer.
Not
OData yol kesimleri her zaman URI segmentlerine karşılık gelir. Örneğin, "1" bir yol kesimi olarak kabul edilir.
Denetleyici Adları. Denetleyici adı her zaman kaynak yolunun kökündeki varlık kümesinden türetilir. Örneğin, kaynak yolu ise /Products(1)/Supplier
, Web API'si adlı ProductsController
bir denetleyici arar.
Eylem Adları. Eylem adları, aşağıdaki tablolarda listelendiği gibi yol segmentlerinden ve varlık veri modelinden (EDM) türetilir. Bazı durumlarda eylem adı için iki seçeneğiniz vardır. Örneğin, "Get" veya "GetProducts".
Varlıkları Sorgulama
İstek | Örnek URI | Eylem Adı | Örnek Eylem |
---|---|---|---|
GET /entityset | /Ürünler | GetEntitySet veya Get | GetProducts |
GET /entityset(anahtar) | /Products(1) | GetEntityType veya Get | GetProduct |
GET /entityset(key)/cast | /Products(1)/Models.Book | GetEntityType veya Get | GetBook |
Daha fazla bilgi için bkz. Read-Only OData Uç Noktası Oluşturma.
Varlıkları Oluşturma, Güncelleştirme ve Silme
İstek | Örnek URI | Eylem Adı | Örnek Eylem |
---|---|---|---|
POST /entityset | /Ürünler | PostEntityType veya Post | PostProduct |
PUT /entityset(anahtar) | /Products(1) | PutEntityType veya Put | PutProduct |
PUT /entityset(key)/cast | /Products(1)/Models.Book | PutEntityType veya Put | PutBook |
PATCH /entityset(anahtar) | /Products(1) | PatchEntityType veya Patch | PatchProduct |
PATCH /entityset(key)/cast | /Products(1)/Models.Book | PatchEntityType veya Patch | PatchBook |
DELETE /entityset(anahtar) | /Products(1) | DeleteEntityType veya Delete | DeleteProduct |
DELETE /entityset(key)/cast | /Products(1)/Models.Book | DeleteEntityType veya Delete | DeleteBook |
Gezinti Özelliğini Sorgulama
İstek | Örnek URI | Eylem Adı | Örnek Eylem |
---|---|---|---|
GET /entityset(key)/navigation | /Products(1)/Supplier | GetNavigationFromEntityType veya GetNavigation | GetSupplierFromProduct |
GET /entityset(key)/cast/navigation | /Products(1)/Models.Book/Author | GetNavigationFromEntityType veya GetNavigation | GetAuthorFromBook |
Daha fazla bilgi için bkz . Varlık İlişkileriyle Çalışma.
Bağlantıları Oluşturma ve Silme
İstek | Örnek URI | Eylem Adı |
---|---|---|
POST /entityset(key)/$links/navigation | /Products(1)/$links/Supplier | CreateLink |
PUT /entityset(key)/$links/navigation | /Products(1)/$links/Supplier | CreateLink |
DELETE /entityset(key)/$links/navigation | /Products(1)/$links/Supplier | DeleteLink |
DELETE /entityset(key)/$links/navigation(relatedKey) | /Products/(1)/$links/Suppliers(1) | DeleteLink |
Daha fazla bilgi için bkz . Varlık İlişkileriyle Çalışma.
Özellikler
Web API 2 gerektirir
İstek | Örnek URI | Eylem Adı | Örnek Eylem |
---|---|---|---|
GET /entityset(key)/property | /Products(1)/Name | GetPropertyFromEntityType veya GetProperty | GetNameFromProduct |
GET /entityset(key)/cast/property | /Products(1)/Models.Book/Author | GetPropertyFromEntityType veya GetProperty | GetTitleFromBook |
Eylemler
İstek | Örnek URI | Eylem Adı | Örnek Eylem |
---|---|---|---|
POST /entityset(key)/action | /Products(1)/Rate | ActionNameOnEntityType veya ActionName | RateOnProduct |
POST /entityset(key)/cast/action | /Products(1)/Models.Book/CheckOut | ActionNameOnEntityType veya ActionName | CheckOutOnBook |
Daha fazla bilgi için bkz. OData Eylemleri.
Yöntem İmzaları
Yöntem imzaları için bazı kurallar şunlardır:
- Yol bir anahtar içeriyorsa, eylemin key adlı bir parametresi olmalıdır.
- Yol bir gezinti özelliğine anahtar içeriyorsa, eylemin relatedKey adlı bir parametresi olmalıdır.
- Key ve relatedKey parametrelerini [FromODataUri] parametresiyle süsleyin.
- POST ve PUT istekleri, varlık türünün bir parametresini alır.
- PATCH istekleri Delta<T> türünde bir parametre alır ve burada T , varlık türüdür.
Başvuru için, her yerleşik OData yönlendirme kuralı için yöntem imzalarını gösteren bir örnek aşağıda verilmiştir.
public class ProductsController : ODataController
{
// GET /odata/Products
public IQueryable<Product> Get()
// GET /odata/Products(1)
public Product Get([FromODataUri] int key)
// GET /odata/Products(1)/ODataRouting.Models.Book
public Book GetBook([FromODataUri] int key)
// POST /odata/Products
public HttpResponseMessage Post(Product item)
// PUT /odata/Products(1)
public HttpResponseMessage Put([FromODataUri] int key, Product item)
// PATCH /odata/Products(1)
public HttpResponseMessage Patch([FromODataUri] int key, Delta<Product> item)
// DELETE /odata/Products(1)
public HttpResponseMessage Delete([FromODataUri] int key)
// PUT /odata/Products(1)/ODataRouting.Models.Book
public HttpResponseMessage PutBook([FromODataUri] int key, Book item)
// PATCH /odata/Products(1)/ODataRouting.Models.Book
public HttpResponseMessage PatchBook([FromODataUri] int key, Delta<Book> item)
// DELETE /odata/Products(1)/ODataRouting.Models.Book
public HttpResponseMessage DeleteBook([FromODataUri] int key)
// GET /odata/Products(1)/Supplier
public Supplier GetSupplierFromProduct([FromODataUri] int key)
// GET /odata/Products(1)/ODataRouting.Models.Book/Author
public Author GetAuthorFromBook([FromODataUri] int key)
// POST /odata/Products(1)/$links/Supplier
public HttpResponseMessage CreateLink([FromODataUri] int key,
string navigationProperty, [FromBody] Uri link)
// DELETE /odata/Products(1)/$links/Supplier
public HttpResponseMessage DeleteLink([FromODataUri] int key,
string navigationProperty, [FromBody] Uri link)
// DELETE /odata/Products(1)/$links/Parts(1)
public HttpResponseMessage DeleteLink([FromODataUri] int key, string relatedKey, string navigationProperty)
// GET odata/Products(1)/Name
// GET odata/Products(1)/Name/$value
public HttpResponseMessage GetNameFromProduct([FromODataUri] int key)
// GET /odata/Products(1)/ODataRouting.Models.Book/Title
// GET /odata/Products(1)/ODataRouting.Models.Book/Title/$value
public HttpResponseMessage GetTitleFromBook([FromODataUri] int key)
}
Özel Yönlendirme Kuralları
Şu anda yerleşik kurallar tüm olası OData URI'lerini kapsamaz. IODataRoutingConvention arabirimini uygulayarak yeni kurallar ekleyebilirsiniz. Bu arabirimin iki yöntemi vardır:
string SelectController(ODataPath odataPath, HttpRequestMessage request);
string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext,
ILookup<string, HttpActionDescriptor> actionMap);
- SelectController denetleyicinin adını döndürür.
- SelectAction eylemin adını döndürür.
Her iki yöntem için de kural bu istek için geçerli değilse yöntemin null döndürmesi gerekir.
ODataPath parametresi ayrıştırılmış OData kaynak yolunu temsil eder. Kaynak yolunun her kesimi için bir tane olmak üzere ODataPathSegment örneklerinin listesini içerir. ODataPathSegment soyut bir sınıftır; her segment türü, ODataPathSegment'ten türetilen bir sınıfla temsil edilir.
ODataPath.TemplatePath özelliği, yol kesimlerinin tümünü birleştirmeyi temsil eden bir dizedir. Örneğin, URI ise /Products(1)/Supplier
yol şablonu "~/entityset/key/navigation" şeklindedir. Segmentlerin doğrudan URI segmentlerine karşılık gelmez. Örneğin, varlık anahtarı (1) kendi ODataPathSegment'i olarak temsil edilir.
Genellikle, IODataRoutingConvention uygulaması aşağıdakileri yapar:
- Bu kuralın geçerli istek için geçerli olup olmadığını görmek için yol şablonunu karşılaştırın. Geçerli değilse null döndür.
- Kural geçerliyse, denetleyici ve eylem adlarını türetmek için ODataPathSegment örneklerinin özelliklerini kullanın.
- Eylemler için, yol sözlüğüne eylem parametrelerine (genellikle varlık anahtarları) bağlanması gereken tüm değerleri ekleyin.
Şimdi belirli bir örneğe bakalım. Yerleşik yönlendirme kuralları, bir gezinti koleksiyonunda dizin oluşturmayı desteklemez. Başka bir deyişle, URI'ler için aşağıdaki gibi bir kural yoktur:
/odata/Products(1)/Suppliers(1)
Burada, bu tür bir sorguyu işlemek için özel bir yönlendirme kuralı yer alır.
using Microsoft.Data.Edm;
using System.Linq;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.OData.Routing;
using System.Web.Http.OData.Routing.Conventions;
namespace ODataRouting
{
public class NavigationIndexRoutingConvention : EntitySetRoutingConvention
{
public override string SelectAction(ODataPath odataPath, HttpControllerContext context,
ILookup<string, HttpActionDescriptor> actionMap)
{
if (context.Request.Method == HttpMethod.Get &&
odataPath.PathTemplate == "~/entityset/key/navigation/key")
{
NavigationPathSegment navigationSegment = odataPath.Segments[2] as NavigationPathSegment;
IEdmNavigationProperty navigationProperty = navigationSegment.NavigationProperty.Partner;
IEdmEntityType declaringType = navigationProperty.DeclaringType as IEdmEntityType;
string actionName = "Get" + declaringType.Name;
if (actionMap.Contains(actionName))
{
// Add keys to route data, so they will bind to action parameters.
KeyValuePathSegment keyValueSegment = odataPath.Segments[1] as KeyValuePathSegment;
context.RouteData.Values[ODataRouteConstants.Key] = keyValueSegment.Value;
KeyValuePathSegment relatedKeySegment = odataPath.Segments[3] as KeyValuePathSegment;
context.RouteData.Values[ODataRouteConstants.RelatedKey] = relatedKeySegment.Value;
return actionName;
}
}
// Not a match.
return null;
}
}
}
Notlar:
- Bu sınıftaki SelectController yöntemi bu yeni yönlendirme kuralı için uygun olduğundan EntitySetRoutingConvention'dan türetiyorum. Bu, SelectController'ı yeniden uygulamam gerekmeyecek anlamına gelir.
- Kural yalnızca GET istekleri için ve yalnızca yol şablonu "~/entityset/key/navigation/key" olduğunda geçerlidir.
- Eylem adı "Get{EntityType}" şeklindedir; burada {EntityType} , gezinti koleksiyonunun türüdür. Örneğin, "GetSupplier". İstediğiniz adlandırma kuralını kullanabilirsiniz; denetleyici eylemlerinizin eşleştiğinden emin olmanız gerekir.
- Eylem , key ve relatedKey adlı iki parametre alır. (Önceden tanımlanmış bazı parametre adlarının listesi için bkz . ODataRouteConstants.)
Sonraki adım, yeni kuralı yönlendirme kuralları listesine eklemektir. Bu, aşağıdaki kodda gösterildiği gibi yapılandırma sırasında gerçekleşir:
using ODataRouting.Models;
using System.Web.Http;
using System.Web.Http.OData.Builder;
using System.Web.Http.OData.Routing;
using System.Web.Http.OData.Routing.Conventions;
namespace ODataRouting
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
ODataModelBuilder modelBuilder = new ODataConventionModelBuilder();
// Create EDM (not shown).
// Create the default collection of built-in conventions.
var conventions = ODataRoutingConventions.CreateDefault();
// Insert the custom convention at the start of the collection.
conventions.Insert(0, new NavigationIndexRoutingConvention());
config.Routes.MapODataRoute(routeName: "ODataRoute",
routePrefix: "odata",
model: modelBuilder.GetEdmModel(),
pathHandler: new DefaultODataPathHandler(),
routingConventions: conventions);
}
}
}
Aşağıda, incelenecek diğer örnek yönlendirme kuralları verilmiştir:
Web API'sinin kendisi de açık kaynak olduğundan, yerleşik yönlendirme kurallarının kaynak kodunu görebilirsiniz. Bunlar System.Web.Http.OData.Routing.Conventions ad alanında tanımlanır.