2014-10-10 13 views
10

Sto cercando di implementare sia Attribute Routing e VersionedRoute da RoutingConstaints Sample ma quando uso entrambi su un controller, l'attributo versioned non funziona più.API Web Api 2 che non riconosce più attributi per il routing (Versioning)

Che cosa avrei bisogno di modificare sull'attributo per farlo funzionare bene con Attribute Routing?

Ad esempio di codice scaricare il progetto di esempio (o semplicemente guardare i pochi file dal link qui sotto) e quindi modificare i percorsi in quanto tale:

// 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

Edit : Per favore fatemi sapere se avete bisogno di ulteriori informazioni o anche postare idee o cose da provare :)

Edit2: Ecco un n esempio di quello che sto cercando di fare dal blog di Troy Hunt: http://www.troyhunt.com/2014/02/your-api-versioning-is-wrong-which-is.html

Edit3: Ecco cosa vorrei codice per essere il più vicino in quanto ridurrebbe un sacco di overhead e stringhe magiche.

[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); 
    } 
} 

Edit: Ultimo urto, cercando di solo devono scrivere le informazioni sulla versione percorso una volta per tratta, a livello di attributo di controllo e non per-action.

+0

Che cosa stai cercando di fare esattamente? – DavidG

+0

@DavidG Sto provando ad usare sia 'VersionedRoute (" Customer ", 1)' che mi permetterebbe di usare le intestazioni http per fornire la versione #, sia l'uso di un 'RoutePrefix (" v1/Customer/")' per il controllo delle versioni tramite l'URL. Fondamentalmente voglio supportare sia la versione di intestazione che quella di url. Tuttavia quando applico 'RoutePrefix' l'attributo' VersionedRoute' smette di funzionare. – John

+0

Come appare la tua configurazione durante l'impostazione del progetto? – entropic

risposta

13

I Route e VersionedRoute attributi stanno lavorando bene insieme, ma l'attributo RoutePrefix si applica anche al tuo VersionedRoute (provare ad accedere/api/v1/clienti/api/Cliente - si otterrà una risposta quando l'intestazione API-versione è impostato)

Il seguente codice produrrebbe il comportamento desiderato in relazione ai due URL dell'esempio restituendo le risposte corrette, ma ovviamente questo non risolve il problema di volere uno VersionedRoute e uno RoutePrefix all'inizio della classe . Un altro approccio sarebbe necessario per questo. Tuttavia, è possibile avere controller separati per diverse versioni di API.

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

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

Un miglioramento sarebbe quello di creare il proprio attributo invece di Route in modo che non avrebbe bisogno di anteporre la versione ogni volta:

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

Corretto, questo si traduce in un sacco di codice duplicato :(. Preferirei piuttosto impostarne uno ' VersionedRoute' e uno 'RoutePrefix' nella parte superiore della classe e quindi non devono preoccuparsi del resto delle rotte sottostanti.Io ho un problema con le costanti per tenere il routeprefix, ma come potete immaginare non è quasi pulito come dovrebbe (potrebbe) essere. – John

+0

La mia domanda è come ottengo quella 'VersionedRoute' e una' RoutePrefix' per ciascuna quindi non devo preoccuparmi di inserire le informazioni sulla versione sopra ciascun metodo. Posso specificarlo manualmente sopra ciascuno di essi, ma vorrei mantenerlo pulito e ASCIUTTO. – John

+0

Non ne sono sicuro. Nel caso in cui aiuti, un miglioramento sarebbe quello di riordinare l'attributo 'Route' creando il tuo (vedi modifica), che potresti semplicemente passare per consta nts e una versione, ma avresti ancora bisogno di due attributi su ciascun metodo, uno per ogni percorso. – embee

Problemi correlati