ASP.NET Web API 2 OData içindeki yönlendirme kurallarıRouting Conventions in ASP.NET Web API 2 Odata

, Mike te sonby Mike Wasson

Bu makalede, ASP.NET 4. x içindeki Web API 2 ' nin OData uç noktaları için kullandığı yönlendirme kuralları açıklanır.This article describes the routing conventions that Web API 2 in ASP.NET 4.x uses for OData endpoints.

Web API 'SI bir OData isteği aldığında, isteği bir denetleyici adı ve eylem adı ile eşler.When Web API gets an OData request, it maps the request to a controller name and an action name. Eşleme, HTTP yöntemini ve URI 'yi temel alır.The mapping is based on the HTTP method and the URI. Örneğin, GET /odata/Products(1) ProductsController.GetProducteşlenir.For example, GET /odata/Products(1) maps to ProductsController.GetProduct.

Bu makalenin 1. bölümünde, yerleşik OData yönlendirme kurallarını açıklıyorum.In part 1 of this article, I describe the built-in OData routing conventions. Bu kurallar, özel olarak OData uç noktaları için tasarlanmıştır ve varsayılan Web API yönlendirme sisteminin yerini alır.These conventions are designed specifically for OData endpoints, and they replace the default Web API routing system. ( MapODataRoute' i çağırdığınızda değiştirme olur.)(The replacement happens when you call MapODataRoute.)

Bölüm 2 ' de, özel yönlendirme kuralları eklemeyi gösterir.In part 2, I show how to add custom routing conventions. Şu anda yerleşik kurallar, tüm OData URI aralığını kapsamaz, ancak bunları ek durumları işleyecek şekilde genişletebilirsiniz.Currently the built-in conventions do not cover the entire range of OData URIs, but you can extend them to handle additional cases.

Yerleşik yönlendirme kurallarıBuilt-in Routing Conventions

Web API 'de OData yönlendirme kurallarını anladığımda, OData URI 'Lerini anlamak faydalı olabilir.Before I describe the OData routing conventions in Web API, it's helpful to understand OData URIs. OData URI aşağıdakilerden oluşur:An OData URI consists of:

  • Hizmet köküThe service root
  • Kaynak yoluThe resource path
  • Sorgu seçenekleriQuery options

Yönlendirme için, önemli parça kaynak yoludur.For routing, the important part is the resource path. Kaynak yolu kesimlere bölünür.The resource path is divided into segments. Örneğin, /Products(1)/Supplier üç parçaya sahiptir:For example, /Products(1)/Supplier has three segments:

  • Products, "Ürünler" adlı bir varlık kümesini ifade eder.Products refers to an entity set named "Products".
  • 1, kümeden tek bir varlık seçen bir varlık anahtarıdır.1 is an entity key, selecting a single entity from the set.
  • Supplier, ilgili varlığı seçen bir gezinti özelliğidir.Supplier is a navigation property that selects a related entity.

Bu nedenle bu yol, 1. ürünün tedarikçisine sahiptir.So this path picks out the supplier of product 1.

Note

OData yol kesimleri, her zaman URI kesimlerine karşılık gelmez.OData path segments do not always correspond to URI segments. Örneğin, "1" bir yol kesimi olarak değerlendirilir.For example, "1" is considered a path segment.

Denetleyici adları.Controller Names. Denetleyici adı her zaman kaynak yolunun kökündeki varlık kümesinden türetilir.The controller name is always derived from the entity set at the root of the resource path. Örneğin, kaynak yolu /Products(1)/Supplierise, Web API 'SI ProductsControlleradlı bir denetleyici arar.For example, if the resource path is /Products(1)/Supplier, Web API looks for a controller named ProductsController.

Eylem adları.Action Names. Eylem adları, aşağıdaki tablolarda listelendiği gibi yol kesimlerinden ve varlık veri modelinden (EDM) türetilir.Action names are derived from the path segments plus the entity data model (EDM), as listed in the following tables. Bazı durumlarda, eylem adı için iki seçeneğiniz vardır.In some cases, you have two choices for the action name. Örneğin, "Get" veya "GetProducts".For example, "Get" or "GetProducts".

Varlıkları sorgulamaQuerying Entities

İstekRequest Örnek URIExample URI Eylem AdıAction Name Örnek eylemExample Action
/EntitySet alGET /entityset /Products/Products GetEntitySet veya GetGetEntitySet or Get GetProductsGetProducts
/EntitySet (anahtar) AlGET /entityset(key) /Products (1)/Products(1) GetEntityType veya GetGetEntityType or Get GetProductGetProduct
/EntitySet (anahtar)/Cast alGET /entityset(key)/cast /Products (1)/models.Book/Products(1)/Models.Book GetEntityType veya GetGetEntityType or Get GetBookGetBook

Daha fazla bilgi için bkz. salt bir OData uç noktası oluşturma.For more information, see Create a Read-Only OData Endpoint.

Varlıkları oluşturma, güncelleştirme ve silmeCreating, Updating, and Deleting Entities

İstekRequest Örnek URIExample URI Eylem AdıAction Name Örnek eylemExample Action
/EntitySet SONRASıPOST /entityset /Products/Products PostEntityType veya postPostEntityType or Post PostProductPostProduct
PUT/EntitySet (anahtar)PUT /entityset(key) /Products (1)/Products(1) PutEntityType veya putPutEntityType or Put PutProductPutProduct
/EntitySet (anahtar)/Cast koyPUT /entityset(key)/cast /Products (1)/models.Book/Products(1)/Models.Book PutEntityType veya putPutEntityType or Put PutBookPutBook
PATCH/EntitySet (anahtar)PATCH /entityset(key) /Products (1)/Products(1) PatchEntityType veya PatchPatchEntityType or Patch PatchProductPatchProduct
PATCH/EntitySet (anahtar)/CastPATCH /entityset(key)/cast /Products (1)/models.Book/Products(1)/Models.Book PatchEntityType veya PatchPatchEntityType or Patch PatchBookPatchBook
/EntitySet 'i SIL (anahtar)DELETE /entityset(key) /Products (1)/Products(1) DeleteEntityType veya deleteDeleteEntityType or Delete DeleteProductDeleteProduct
/EntitySet (anahtar)/Cast SILDELETE /entityset(key)/cast /Products (1)/models.Book/Products(1)/Models.Book DeleteEntityType veya deleteDeleteEntityType or Delete DeleteBookDeleteBook

Gezinti özelliği sorgulamaQuerying a Navigation Property

İstekRequest Örnek URIExample URI Eylem AdıAction Name Örnek eylemExample Action
/EntitySet (anahtar)/gezinti alGET /entityset(key)/navigation /Products (1)/Tedarikçi/Products(1)/Supplier GetNavigationFromEntityType veya GetNavigationGetNavigationFromEntityType or GetNavigation GetSupplierFromProductGetSupplierFromProduct
/EntitySet (anahtar)/ro/Navigation alGET /entityset(key)/cast/navigation /Products (1)/Models.Book/Author/Products(1)/Models.Book/Author GetNavigationFromEntityType veya GetNavigationGetNavigationFromEntityType or GetNavigation GetAuthorFromBookGetAuthorFromBook

Daha fazla bilgi için bkz. varlık ilişkileri Ile çalışma.For more information, see Working with Entity Relations.

Bağlantı oluşturma ve silmeCreating and Deleting Links

İstekRequest Örnek URIExample URI Eylem AdıAction Name
/EntitySet (anahtar)/$links/Navigation SONRASıPOST /entityset(key)/$links/navigation /Products (1)/$links/Tedarikçi/Products(1)/$links/Supplier CreateLinkCreateLink
/EntitySet (anahtar)/$links/Navigation koyPUT /entityset(key)/$links/navigation /Products (1)/$links/Tedarikçi/Products(1)/$links/Supplier CreateLinkCreateLink
/EntitySet (anahtar)/$links/gezintiyi SILDELETE /entityset(key)/$links/navigation /Products (1)/$links/Tedarikçi/Products(1)/$links/Supplier DeleteLinkDeleteLink
/EntitySet (anahtar)/$links/Navigation (relatedKey) SILDELETE /entityset(key)/$links/navigation(relatedKey) /Products/(1)/$links/Suppliers (1)/Products/(1)/$links/Suppliers(1) DeleteLinkDeleteLink

Daha fazla bilgi için bkz. varlık ilişkileri Ile çalışma.For more information, see Working with Entity Relations.

ÖzelliklerProperties

Web API 2 gerektirirRequires Web API 2

İstekRequest Örnek URIExample URI Eylem AdıAction Name Örnek eylemExample Action
/EntitySet (anahtar)/Property alGET /entityset(key)/property /Products (1)/Name/Products(1)/Name GetPropertyFromEntityType veya GetPropertyGetPropertyFromEntityType or GetProperty GetNameFromProductGetNameFromProduct
/EntitySet (anahtar)/ro/Property alGET /entityset(key)/cast/property /Products (1)/Models.Book/Author/Products(1)/Models.Book/Author GetPropertyFromEntityType veya GetPropertyGetPropertyFromEntityType or GetProperty GetTitleFromBookGetTitleFromBook

EylemlerActions

İstekRequest Örnek URIExample URI Eylem AdıAction Name Örnek eylemExample Action
POST/EntitySet (anahtar)/ActionPOST /entityset(key)/action /Products (1)/ücret/Products(1)/Rate ActionNameOnEntityType veya ActionNameActionNameOnEntityType or ActionName RateOnProductRateOnProduct
POST/EntitySet (anahtar)/ro/ActionPOST /entityset(key)/cast/action /Products (1)/Models.Book/CheckOut/Products(1)/Models.Book/CheckOut ActionNameOnEntityType veya ActionNameActionNameOnEntityType or ActionName CheckOutOnBookCheckOutOnBook

Daha fazla bilgi için bkz. OData eylemleri.For more information, see OData Actions.

Yöntem ImzalarıMethod Signatures

Yöntem imzaları için bazı kurallar aşağıda verilmiştir:Here are some rules for the method signatures:

  • Yol bir anahtar içeriyorsa, eylem anahtaradlı bir parametreye sahip olmalıdır.If the path contains a key, the action should have a parameter named key.
  • Yol, bir gezinti özelliğine bir anahtar içeriyorsa, eylem RelatedKeyadlı bir parametreye sahip olmalıdır.If the path contains a key into a navigation property, the action should have a parameter named relatedKey.
  • [Fromodatauri] parametresiyle anahtar ve RelatedKey parametreleri süsle.Decorate key and relatedKey parameters with the [FromODataUri] parameter.
  • POST ve PUT istekleri, varlık türünün bir parametresini alır.POST and PUT requests take a parameter of the entity type.
  • Düzeltme Eki istekleri, Delta<t> türünde bir parametre alır, burada t varlık türüdür.PATCH requests take a parameter of type Delta<T>, where T is the entity type.

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.For reference, here is an example that shows method signatures for every built-in OData routing convention.

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ıCustom Routing Conventions

Şu anda yerleşik kurallar olası tüm OData URI 'Lerini kapsamaz.Currently the built-in conventions do not cover all possible OData URIs. IODataRoutingConvention arabirimini uygulayarak yeni kurallar ekleyebilirsiniz.You can add new conventions by implementing the IODataRoutingConvention interface. Bu arabirimin iki yöntemi vardır:This interface has two methods:

string SelectController(ODataPath odataPath, HttpRequestMessage request);
string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, 
    ILookup<string, HttpActionDescriptor> actionMap);
  • SelectController denetleyicinin adını döndürür.SelectController returns the name of the controller.
  • SelectAction eylemin adını döndürür.SelectAction returns the name of the action.

Her iki yöntem için de kural bu istek için uygulanmadığından, yöntemi null döndürmelidir.For both methods, if the convention does not apply to that request, the method should return null.

ODataPath parametresi, ayrıştırılmış OData kaynak yolunu temsil eder.The ODataPath parameter represents the parsed OData resource path. Kaynak yolunun her segmenti için bir tane olmak üzere ODataPathSegment örneklerinin bir listesini içerir.It contains a list of ODataPathSegment instances, one for each segment of the resource path. ODataPathSegment soyut bir sınıftır; her segment türü ODataPathSegmentöğesinden türetilen bir sınıf tarafından temsil edilir.ODataPathSegment is an abstract class; each segment type is represented by a class that derives from ODataPathSegment.

ODataPath. TemplatePath özelliği, tüm yol segmentlerinin bitiştirilmesi temsil eden bir dizedir.The ODataPath.TemplatePath property is a string that represents the concatenation all of the path segments. Örneğin, URI /Products(1)/Supplier, yol şablonu "~/EntitySet/Key/Navigation"olur.For example, if the URI is /Products(1)/Supplier, the path template is "~/entityset/key/navigation". Segmentlerin doğrudan URI kesimlerine karşılık gelmediğine dikkat edin.Notice that the segments don't correspond directly to URI segments. Örneğin, varlık anahtarı (1) kendi ODataPathSegmentolarak temsil edilir.For example, the entity key (1) is represented as its own ODataPathSegment.

Genellikle, IODataRoutingConvention uygulamasında aşağıdakiler vardır:Typically, an implementation of IODataRoutingConvention does the following:

  1. Bu kuralın geçerli istek için geçerli olup olmadığını görmek için yol şablonunu karşılaştırın.Compare the path template to see if this convention applies to the current request. Uygulama yoksa, null döndürün.If it does not apply, return null.
  2. Kural geçerliyse, denetleyiciyi ve eylem adlarını türetmek için ODataPathSegment örneklerinin özelliklerini kullanın.If the convention applies, use properties of the ODataPathSegment instances to derive controller and action names.
  3. Eylemler için, işlem parametrelerine bağlanması gereken yol sözlüğüne herhangi bir değer ekleyin (genellikle varlık anahtarları).For actions, add any values to the route dictionary that should bind to the action parameters (typically entity keys).

Belirli bir örneğe bakalım.Let's look at a specific example. Yerleşik yönlendirme kuralları bir gezinti koleksiyonuna dizin oluşturmayı desteklemez.The built-in routing conventions do not support indexing into a navigation collection. Diğer bir deyişle, aşağıdaki gibi URI 'Ler için bir kural yoktur:In other words, there is no convention for URIs like the following:

/odata/Products(1)/Suppliers(1)

Bu tür bir sorgu işlemek için özel bir yönlendirme kuralı aşağıda verilmiştir.Here is a custom routing convention to handle this type of query.

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:Notes:

  1. Bu sınıftaki SelectController yöntemi bu yeni yönlendirme kuralına uygun olduğundan EntitySetRoutingConventionöğesinden türedim.I derive from EntitySetRoutingConvention, because the SelectController method in that class is appropriate for this new routing convention. Bu, SelectController'ı yeniden uygulamam gerekmediği anlamına gelir.That means I don't need to re-implement SelectController.
  2. Kural yalnızca GET istekleri için geçerlidir ve yalnızca yol şablonu "~/EntitySet/Key/Navigation/Key"olduğunda geçerlidir.The convention applies only to GET requests, and only when the path template is "~/entityset/key/navigation/key".
  3. Eylem adı "Get {EntityType}"; burada {EntityType} , gezinti koleksiyonunun türüdür.The action name is "Get{EntityType}", where {EntityType} is the type of the navigation collection. Örneğin, Gettedarikçinin"".For example, "GetSupplier". — Yalnızca denetleyici eylemlerinizin eşleştiğinden emin olmak istediğiniz adlandırma kurallarını kullanabilirsiniz.You can use any naming convention that you like — just make sure your controller actions match.
  4. Eylem, anahtar ve RelatedKeyadlı iki parametre alır.The action takes two parameters named key and relatedKey. (Önceden tanımlanmış bazı parametre adlarının listesi için bkz. ODataRouteConstants.)(For a list of some predefined parameter names, see ODataRouteConstants.)

Sonraki adım, yönlendirme kuralları listesine yeni kuralı ekliyor.The next step is adding the new convention to the list of routing conventions. Bu, aşağıdaki kodda gösterildiği gibi yapılandırma sırasında gerçekleşir:This happens during configuration, as shown in the following code:

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, çalışmak için yararlı olan bazı diğer örnek yönlendirme kuralları verilmiştir:Here are some other sample routing conventions that be useful to study:

Ayrıca, Web API 'sinin kendisi açık kaynak olduğundan, yerleşik yönlendirme kuralları için kaynak kodu görebilirsiniz.And of course Web API itself is open-source, so you can see the source code for the built-in routing conventions. Bunlar System. Web. http. OData. Routing. kurallarına ilişkin ad alanında tanımlanmıştır.These are defined in the System.Web.Http.OData.Routing.Conventions namespace.