14

GET'leri ve POST'ları ayrı bir API Denetleyicisi türüne ayırmak ve aynı Rota Önekini kullanarak bunlara erişmek mümkün mü? Her zaman Kumandanızda bir RoutePrefix belirtmek gerekmezAynı Rota önekine sahip Çoklu Denetleyici Türleri ASP.NET Web Api

[RoutePrefix("api/Books")] 
public class BooksWriteController : EventStoreApiController 
{ 
    [Route("")] 
    public void Post([FromBody] CommandWrapper commandWrapper){...} 
} 

[RoutePrefix("api/Books")] 
public class BooksReadController : MongoDbApiController 
{ 
    [Route("")] 
    public Book[] Get() {...} 


    [Route("{id:int}")] 
    public Book Get(int id) {...} 
} 

cevap

29

Web API'sı (1.x-2.x), farklı denetleyicilerin aynı yoldaki birden çok öznitelik yolunu desteklemez. Sonuç bir 404'tür, çünkü tüm rota birden fazla denetleyiciyle eşleşir ve bu noktada Web API, sonucu belirsiz olarak değerlendirir. MVC Çekirdek hem MVC & Web API işlevi görür: MVC Core bu senaryo notu desteklemek yaptığı

Not.

Web API 2.11 (veya daha yeni bir sürümünü) kullanmayı seçerseniz, denetleyici başına http yöntemi için bir yol kısıtlaması oluşturabilir ve Route Attribute öğesinde yerleşik olarak kullanmak yerine kullanabilirsiniz. Aşağıdaki örnek, RoutePrefix'i veya doğrudan Rotaları (kmacdonald'ın cevabı gibi) kullanabileceğinizi göstermektedir.

using System.Collections.Generic; 
using System.Net.Http; 
using System.Web.Http; 
using System.Web.Http.Routing; 

public class BooksWriteController : ApiController 
{ 
    [PostRoute("api/Books")] 
    public void Post() { } 
} 

[RoutePrefix("api/books")] 
public class BooksReadController : ApiController 
{ 
    [GetRoute] 
    public void Get() { } 

    [GetRoute("{id:int}")] 
    public void Get(int id) { } 
} 

Bu iki sınıf

rotaya sınırlamalar ekleyerek bu sadece standart bir rota kısıtlaması, sirke

class MethodConstraintedRouteAttribute : RouteFactoryAttribute 
{ 
    public MethodConstraintedRouteAttribute(string template, HttpMethod method) 
     : base(template) 
    { 
     Method = method; 
    } 

    public HttpMethod Method 
    { 
     get; 
     private set; 
    } 

    public override IDictionary<string, object> Constraints 
    { 
     get 
     { 
      var constraints = new HttpRouteValueDictionary(); 
      constraints.Add("method", new MethodConstraint(Method)); 
      return constraints; 
     } 
    } 
} 

oluşturulan sağlar

class GetRouteAttribute : MethodConstraintedRouteAttribute 
{ 
    public GetRouteAttribute(string template) : base(template ?? "", HttpMethod.Get) { } 
} 

class PostRouteAttribute : MethodConstraintedRouteAttribute 
{ 
    public PostRouteAttribute(string template) : base(template ?? "", HttpMethod.Post) { } 
} 

Bu sınıf kısıtlaması rota özelliğinin kullanımını kolaylaştırmak : kısıtlamaları azaltmak için kısıtlama nesnesini önbelleğe almak isteyebilirsiniz.

class MethodConstraint : IHttpRouteConstraint 
{ 
    public HttpMethod Method { get; private set; } 

    public MethodConstraint(HttpMethod method) 
    { 
     Method = method; 
    } 

    public bool Match(HttpRequestMessage request, 
         IHttpRoute route, 
         string parameterName, 
         IDictionary<string, object> values, 
         HttpRouteDirection routeDirection) 
    { 
     return request.Method == Method; 
    } 
} 
+0

tabanlı doğru denetleyici türünü seçmektir. Bu mükemmel çalışır. – user1145404

+1

@YishaiGalatzer: [System.Web.Http.Routing.HttpMethodConstraint] (https://msdn.microsoft.com/en-us/library/system.web) 'yi yeniden kullanmak yerine özel 'MethodConstraint' özel gereksinimine ihtiyacınız var. http.routing.httpmethodconstraint (v = vs.118) .aspx)? – Serguei

+1

Nokta, rotanın kendisini sınırlıyor. Yerleşik özellik sadece çok geç çalışan eylem seçiminde rol oynar. –

3

: Burada

benim kontrolörlerdir. sadece web yöntemlerine doğrudan rotayı bırakabilir:

public class BooksWriteController : EventStoreApiController 
{ 
    [Route("api/Books")] 
    public void Post([FromBody] CommandWrapper commandWrapper){...} 
} 

public class BooksReadController : MongoDbApiController 
{ 
    [Route("api/Books")] 
    public TaskTypeInfo[] Get() {...} 


    [Route("api/Books/{id:int}")] 
    public TaskTypeInfo Get(int id) {...} 
} 

Ancak, ben senin RoutePrefix hem denetleyicileri üzerinde iyi çalışır hayal ediyorum. RoutePrefix özniteliğinin, aslında rotayı tanımlayan Route özniteliğiyle birlikte kullanıldığını düşünüyorum. Bu, çelişen bir yolunuz olmadığı sürece (bu bir biggie) iyi olmanız gerektiği anlamına gelir.

+2

Teşekkürler, sorun değil. Sorun, GET veya POST – user1145404