2014-10-10 39 views
10

我試圖實現Attribute RoutingVersionedRouteRoutingConstaints Sample,但是當我在控制器上同時使用時,versioned屬性不再起作用。Web API 2不識別多個屬性的路由(版本控制)

我需要在屬性上修改哪些內容才能讓它與屬性路由很好地發揮作用?

對於代碼示例下載示例項目(或只是看一些文件,從上面的鏈接),然後修改路由這樣:

// When I use the RoutePrefix, VersionedRoute no longer works (Sending "Api-Version" through http header doesn't route correctly 
// If I remove the RoutePrefix I can use VersionedRoute again 
// What do I need to change in its code to be able to use both? 

[VersionedRoute("api/Customers", 1)] // This route would be used as http://url/api/customers with a header of "api-version: 1" 
[RoutePrefix("api/v1/Customers")] // This route would be used purely through url versioning of http://url/api/v1/Customers 
public class CustomersV1Controller : ApiController { 

    /* Other stuff removed */ 

    [VersionedRoute("api/Customer", 1)] // I'd rather not have to use this here at all and just use a single one on the class, but having both nor just one on either works right now. 
    [Route("")] 
    public IHttpActionResult Get() 
    { 
     return Json(_customers); 
    } 
} 

VersionedRoute Code

VersionConstraint Code

編輯:請讓我知道,如果你需要更多的信息,甚至張貼想法或東西來嘗試:)

編輯2:這是一個我想從Troy Hunt的博客中嘗試做的一個例子:http://www.troyhunt.com/2014/02/your-api-versioning-is-wrong-which-is.html

Edit3:這是我想編寫的儘可能接近的代碼,因爲它會減少很多開銷和魔法字符串。

[VersionedRoute("api/Customers", 1)] // This route would be used as http://url/api/customers with a header of "api-version: 1" 
[RoutePrefix("api/v1/Customers")] // This route would be used purely through url versioning of http://url/api/v1/Customers 
public class CustomersV1Controller : ApiController { 

    /* Other stuff removed */ 
    [Route("")] 
    public IHttpActionResult Get() 
    { 
     // Removed 
     return Ok(customers); 
    } 


    [Route("{id:int}")] 
    public IHttpActionResult GetById(int id) 
    { 
     // Removed 
     return Ok(customer); 
    } 
} 

[VersionedRoute("api/Customers", 2)] // This route would be used as http://url/api/customers with a header of "api-version: 2" 
[RoutePrefix("api/v2/Customers")] // This route would be used purely through url versioning of http://url/api/v2/Customers 
public class CustomersV2Controller : ApiController { 

    /* Other stuff removed */ 
    [Route("")] 
    public IHttpActionResult Get() 
    { 
     // Removed 
     return Ok(customersThatAreDifferentThanV1); 
    } 


    [Route("{id:int}")] 
    public IHttpActionResult GetById(int id) 
    { 
     // Removed 
     return Ok(customerThatIsDifferent); 
    } 
} 

編輯:最後一次碰撞,試圖只需要在控制器屬性級而不是每個行爲每個路由寫一次路由版本信息。

+0

什麼是你想要做什麼呢? – DavidG 2014-10-17 08:54:18

+0

@DavidG我正在嘗試使用'VersionedRoute(「Customer」,1)'這將允許我使用http頭來提供版本#,以及使用'RoutePrefix(「v1/Customer /」)通過url進行版本控制。基本上我想支持標題和網址版本。但是,當我應用'RoutePrefix'時'VersionedRoute'屬性停止工作。 – John 2014-10-17 16:21:33

+0

設置項目時,你的配置是什麼樣的? – entropic 2014-10-17 16:44:27

回答

13

RouteVersionedRoute屬性被罰款一起工作,但你的RoutePrefix屬性也適用於您的VersionedRoute(嘗試訪問/ API/V1 /客戶/ API /客戶 - 你會得到迴應時,API版本頭設置)

下面的代碼會產生與問候到兩個URL在您的示例返回正確的響應所需的行爲,但顯然這並不能解決您想要一個VersionedRoute和一個RoutePrefix在班上名列前茅的問題。這需要另一種方法。但是,您可以爲不同的api版本分開控制器。

[RoutePrefix("api")] 
public class CustomersV1Controller : ApiController 
{ 
    /* Other stuff removed */ 

    [VersionedRoute("Customers", 1)] 
    [Route("v1/Customers")] 
    public IHttpActionResult Get() 
    { 
     return Json(_customers); 
    } 
} 

的改善將代替Route創建自己的屬性,這樣你就不需要每次前綴版本:

public class CustomVersionedRoute : Attribute, IHttpRouteInfoProvider 
{ 
    private readonly string _template; 

    public CustomVersionedRoute(string route, int version) 
    { 
     _template = string.Format("v{0}/{1}", version, route); 
    } 

    public string Name { get { return _template; } } 
    public string Template { get { return _template ; } } 
    public int Order { get; set; } 
} 

[RoutePrefix("api")] 
public class CustomersV2Controller : ApiController 
{ 
    /* Other stuff removed */ 

    [VersionedRoute("Customers", 2)] 
    [CustomVersionedRoute("Customers", 2)] 
    public IHttpActionResult Get() 
    { 
     return Json(_customers); 
    } 
} 
+0

正確,這導致了很多重複的代碼:(我寧願只設置一個' VersionedRoute'和一個'RoutePrefix'在類的頂部,然後不必擔心下面的其他路由。我有一個使用常量來保存routeprefix的東西,但你可以想象它不是近儘可能清潔它應該(可能) – John 2014-10-21 17:29:47

+0

我的問題是我如何得到一個'VersionedRoute'和一個'RoutePrefix',這樣我就不用擔心把版本信息放在每個方法的上面了。我可以在每一個上面手動指定它,但我想保持它乾淨和乾燥。 – John 2014-10-21 18:09:20

+0

我不確定如果它有幫助,一個改進就是通過製作你自己的(Route屬性)見編輯),你可以通過你的const nts和一個版本,但您仍然需要每種方法的兩個屬性,每個方法一個。 – embee 2014-10-21 18:50:14