2013-03-25 11 views
9

Prima di considerare questo un duplicato, si prega di prendere un secondo. Quando cerco Web Api sulla questione del controllo delle versioni, tutto riguarda i controller e le best practice con versioni attorno alla specifica della versione in url vs. intestazioni.Soluzione di controllo delle versioni di Web Api?

Quello che sto cercando di capire è ciò che è il modo migliore per la versione risposta di uscita in modo da non rompere la versione 1 clienti quando esco con la versione 2.

Diciamo che ho un modifica continua del DAL per una suite di siti Web che alimenta un sito Web e altri servizi. Sto lavorando a un nuovo progetto Web Api che dovrebbe contenere risposte conformi agli schemi delle versioni.

La mia domanda è: quali sono le soluzioni/best practice collaudate per implementare il controllo delle versioni in Web Api, i precedenti controller con versioni precedenti e i DAL non versione?

Mi è venuta in mente una soluzione che implica un ulteriore livello di repository con versioni e un ulteriore livello di modelli con versioni, quindi i controller con versione utilizzano repository con versione che utilizzano modelli con versione. E ho impostato Automapper per mappare tra i modelli di dominio non versione (dal DAL) ai modelli con versione. Ma il difetto ereditario di questa configurazione è che devo aggiornare tutte le mappe per ogni nuova versione; un problema in crescita esponenziale.

Ci deve essere un modo migliore. Grazie!

+0

https://github.com/Sebazzz/SDammann.WebApi.Versioning – adt

+0

È un'ottima soluzione per i controller di versioni, ma come ho detto, non sto cercando quello – Levitikon

+0

L'unica cosa che potrei pensare; sarebbe quello di creare un modello autonomo che detiene tali dati. Quindi utilizzare un controller per estrarre tali informazioni. Oppure, per disporre di una tabella database separata in cui utilizzare tali riferimenti. Non sono sicuro che questo aiuti, buona domanda, ci rifletterò anche su questo. – Greg

risposta

1

Nella mia esperienza, il più pulito (ma non più semplice) soluzione che abbiamo trovato è disponibile in 5 parti:

  1. Avere un modello di dati autorevole e un back-end che è sempre aggiornata : DAL/Database/Servizi.
  2. Avere dati specifici della versione tutti comprensibili per il sistema: Modello di dati multipli.
  3. Assicurarsi che le modifiche tra versione siano identificate e tracciate correttamente e che le modifiche siano reversibili. Le regole devono essere definite in modo esplicito per gestire quello (che potrebbe essere più difficile): Convertitori.
  4. Fare in modo che il client indichi in modo esplicito quale versione utilizzano: stringhe di query/intestazioni.
  5. Avere una logica aziendale autorevole che è sempre aggiornata ma sa come spostarsi tra le diverse versioni dei dati - compatibile con le versioni precedenti: Controller.

Il modello di dati che abbiamo è fornitore per esempio.

(1) Il back end (ovvero DAL/database) è in V5. La Business Logic (ovvero i servizi) è anche in V5.

(2) Tuttavia, dobbiamo servire il fornitore del cliente su V1, V2, V3, V4 e client aggiornato su V5 tutti allo stesso tempo. Facciamo V1 a V5 del nostro modello di dati: SupplierV1, SupplierV2 ... (si potrebbe usare namespace, o altri modi per differenziarli)

(3) è necessario definire convertitori e gestirli. Devono gestire sia la compatibilità in avanti che a ritroso tra le versioni del modello di dati. Questo potrebbe essere fatto con un modello di strategia, lambdas, un manager con convertitori DI, ecc.Dovresti gestire V1-> V2-> V3-> V4-> V5 ma anche V5-> V4-> V3-> V2-> V1.

Le regole nei convertitori sono la parte più difficile. A volte è facile: valori predefiniti per i nuovi campi. Altre volte è necessario eseguire alcune logiche di business. A volte è necessario convertire/unire i dati esistenti; devi assicurarti che sia reversibile! Ad esempio, se i valori sono in lettere maiuscole in V1 e lo converti in maiuscolo in V2 ... non potrai tornare a V1, dato che non hai idea di quali caratteri siano maiuscoli e minuscoli. È possibile gestire in due modi:

  • Mantenerlo in maiuscolo per V1. Dopotutto, è solo V2 che lo richiede, probabilmente V1 può funzionare con tutti i casi superiori (ovviamente non funzionerebbe con le chiavi).
  • Mantieni il vecchio valore in un campo in V2. Ad esempio, se si decide di digitare maiuscole nel campo Stato, è possibile mantenere uno stato originale misto a caso e copiarlo in stato quando si torna a V1.

Come potete vedere, è necessario pensare a quelli difficili ed è spesso non banale.

(4) Quindi, nei controller, è necessario conoscere la versione con cui il client lavora per eseguire la conversione dentro e fuori il controller quando necessario. Per questo è possibile utilizzare stringhe di query, intestazioni (X-API-Version o Accept per esempio, ma attenzione alcune strisce host/proxy alcune di esse), parametro post, ecc.

(5) Infine, quando il il controller riceve un modello di dati, è necessario verificare quale versione il client ha inviato (diciamo V2) e aggiornarlo alla versione più recente per il back-end (V5). Quindi usarlo correttamente, e in seguito, se è necessario inviare i dati, è necessario eseguirne il downgrade alla versione client (V2). Per fare questo, si potrebbe fare su misura vincolante, per richiedere azioni personalizzate, risultati d'azione personalizzati, ecc, ad esempio (si prega di automatizzare questo):

public IHttpActionResult DoSomethingWithSupplier(JToken supplier) // Receiving Json Supplier 
{ 
    // TODO: Get the client version type, for example in the X-API-Version header/query strings 
    // (beware, some proxy/hosts strips some headers) 
    // Type clientType = ... 

    var clientSupplier = JsonConvert.DeserializeObject(supplier.ToString(), clientType); 

    // You should probably detect latest version automatically (instead of typeof) 
    var latestSupplier = VersionManager.Upgrade(clientSupplier, clientType, typeof(SupplierV5)); 

    outputSupplier = DoSomething(latestSupplier); 

    // You should probably detect latest version automatically (instead of typeof) 
    var clientOutputSupplier = VersionManager.Downgrade(outputSupplier, typeof(SupplierV5), clientType); 

    return Ok(clientOutputSupplier); 
} 

Questo è un modo molto grezzo visualizzare l'idea. Questo è qualcosa che abbiamo fatto in uno dei nostri sistemi. Potresti avere Manager che rilevano tipi e versioni e gestire direttamente la conversione, puoi caricare dinamicamente assembly/converters con l'iniezione delle dipendenze, puoi automatizzare la maggior parte della conversione in associazioni personalizzate/azioni di richiesta e così via.

Nota: C'è anche una parte (6) potrebbe essere necessario prendere in considerazione. Per aggiornare effettivamente i dati del client nel database su V5, è possibile farlo durante la migrazione a V5 (migrazione batch di dati), OPPURE, farlo in fase di runtime. Quando si riceve SupplierV1, lo si carica dal database (ancora dati V1), si esegue l'aggiornamento a V5 e si salvano i dati aggiornati, il tutto nel convertitore. Ciò significa che ora hai la migrazione immediata del tuo back-end. Ovviamente, non è così facile come sembra, in quanto è necessario supportare entrambe le versioni nello stesso database, ma potrebbe funzionare bene a seconda del tipo di modifiche o dati che si hanno.

Problemi correlati