IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

ASP.NET MVC Discussion :

Web API versionning


Sujet :

ASP.NET MVC

  1. #1
    Membre confirmé
    Inscrit en
    Avril 2010
    Messages
    200
    Détails du profil
    Informations forums :
    Inscription : Avril 2010
    Messages : 200
    Par défaut Web API versionning
    Bonjour à tous,

    J'ai actuellement un projet qui utilise Web API pour fournir des services. J'aimerais la modifier pour gérer le versioning. J'ai donc épluché mon meilleur ami Google et je tombe sur plusieurs blogs qui traitent ce point mais j'ai du mal à faire un choix. De ce que j'ai pu voir, il y a 3 solutions, définir la version dans :
    - le header (champ custom ou non ?)
    - une partie de l'url (par exemple : /api/v1/Book/GetAll
    - query parameter (par exemple /api/Book/GetAll?v=1)

    Je trouve la dernière solution "dégueulasse" pour pas mâcher mes mots car visuellement c'est moche, de plus ça signifie qu'il faut que je rajoute l'élément "v" à chacune de mes méthodes déjà existante, donc modifier tout et renseigner ce champ à chaque fois.
    J'ai tendance à choisir dans le header car je trouve ça propre et ça ne casse pas les URLs (existantes ou futures).
    Mais je trouve que la solution dans l'url est pas mal pour tester les services rapidement dans le navigateur.

    Quelle solution choisir et pourquoi ?

    Merci par avance.

  2. #2
    Membre émérite Avatar de chamamo
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    588
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 588
    Par défaut
    Je me posais la question il y a un petit moment, je confirme que la dernière proposition est dégueulasse, le versionning dans l'URL semble être la meilleurs solution, mais je ne l'ai pas mis en place car tu as un service par version, dans le cas ou tu as par exemple 10 service avec 3 version, tu auras en réalité 30 classes à gérer, ça reste du code dupliqué.

    J'ai opté pour une versionning global de l'application serveur et de l'application cliente.

    - Le client envoie sa requête HTTP avec sa version dans le header.
    - Le serveur reçoit la requête et vérifie si la version du client est compatible (le serveur à une version minimale du client à supporter)
    - Si la version du client est inférieure à la version minimale supportée le serveur envoie une exception pour lui dire qu'il faut mettre à jour l'application cliente.

    Maintenant le test dans l'autre sens, le client à une version minimale supportée du serveur
    - dans la même requête le client envoie dans le header la version minimale supportée du serveur
    - le serveur vérifie la version reçue du client avec sa version courante, si ça ne correspond pas une exception est envoyée au client, cette fois-ci pour dire que la version du client est supérieure à la version du serveur, il faut mettre à jour le serveur.

    J'espère que cette approche pourrait correspondre à ce que tu cherches.

  3. #3
    Membre confirmé
    Inscrit en
    Avril 2010
    Messages
    200
    Détails du profil
    Informations forums :
    Inscription : Avril 2010
    Messages : 200
    Par défaut
    Bonjour chamamo,

    On se croise une fois de plus.

    J'ai continué à me renseigner (quand je pouvais) et j'ai trouvé d'autres infos ou arguments qui me font douter pour la version avec la version dans l'url.

    Effectivement j'avais déjà dans l'idée que j'aurai du code dupliqué. Je trouve ça normal dans le sens où si un service est bogué, tu es bien obligé d'avoir une nouvelle version donc un code différent (tout en gardant l'ancienne pour les clients l'utilisant encore). Au final, le code n'est pas forcément dupliqué, si différent, puis une version une fois finalisée tu ne la touches plus. donc toujours qu'une seule version à gérer.

    Actuellement, nous avons une "gestion" (si on peut appeler ça comme ça) où on déploie toute la partie serveur avec l'API et les Front Office mais ça signifie créer de nouveaux noms de domaines avec des ports différents etc. enfin c'est complètement moche comme solution, nous sommes mal parti.

    Pour le principe de tout relivrer à chaque fois, comment gères-tu les différentes version du serveur ? Tu as donc comme nous plusieurs instances à gérer. Nous n'en avons que 2 pour le moment et ça devient déjà ingérable...

    D'après ces liens :
    - http://barelyenough.org/blog/2008/05...-web-services/ et
    - http://www.mnot.net/blog/2011/10/25/...ning_smackdown

    la solution de la version dans l'url n'est peut-être pas la mieux. Qu'en penses-tu ?

  4. #4
    Membre émérite Avatar de chamamo
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    588
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 588
    Par défaut
    Oui encore une fois, le monde est petit, et ce forum l'est encore moins

    Tu veux dire quoi par plusieurs instances et plusieurs domaines? tu gardes l'ancienne version quand tu déploies la nouvelle?

    Moi j'ai une seule instance (enfin une seule version) que je met à jour si besoin, et comme j'ai expliqué précédemment si j'ai des changements qui nécessitent une version récente de l'application cliente je lance une exception au client pour lui demander de mettre à jour sa version, ça me semblait moins lourd que gérer plusieurs versions d'un même services, sachant que j'en ai environ 30 services pour l'instant.

  5. #5
    Membre confirmé
    Inscrit en
    Avril 2010
    Messages
    200
    Détails du profil
    Informations forums :
    Inscription : Avril 2010
    Messages : 200
    Par défaut
    Oui exactement, je garde l'ancienne version sur demande du client. Et sur le moment c'est la seule solution qui a été trouvée. C'est pourquoi, nous ne pouvons pas rester dans cette situation.

    Au début nous faisions comme toi à remplacer la version par la dernière, mais aujourd'hui il faut gérer la population cliente sur les différentes versions.

    Je suis d'accord avec l'idée de renvoyer une exception sur une version trop ancienne mais en l’occurrence pour nous, nous n'avons actuellement que deux versions... C'est dommage !

    Je pense partir sur une solution avec la version dans l'url, mais je suis pas encore décidé. J'ai pas eu le temps de me repencher sur la question depuis.

    J'aimerais avoir d'autres avis, des retours d'expérience mais ça semble vide par ici...
    C'est fini les vacances, revenez !

  6. #6
    Membre confirmé
    Inscrit en
    Avril 2010
    Messages
    200
    Détails du profil
    Informations forums :
    Inscription : Avril 2010
    Messages : 200
    Par défaut
    Je reviens sur le sujet.

    Alors aujourd'hui j'ai pu avancé. J'ai réalisé un POC où je fais appel à une version de ma web api suivant la version dans le header.
    J'aimerais savoir comment je peux gérer le cas de l'avertissement dans le retour d'une requête qu'il faut utiliser une version minimale de l'API (que la version que l'utilisateur utilise actuellement est obsolète et/ou plus supportée et sera supprimée) ?

    Normalement une vielle API versionnée n'est plus censée être modifiée, du coup comment renvoyer dans la requête qu'il faut faire un upgrade sans avoir à modifier le code ?

  7. #7
    Membre émérite Avatar de chamamo
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    588
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 588
    Par défaut
    J'iamgine que tu utilies un Handler pour gérer tout ça,

    Tu peux renvoyer une exception si la version qu'il essaie d'appeler est obsolète

    un HttpResponseMessage avec HttpStatusCode.HttpVersionNotSupported comme StatusCode et une description de l'erreur:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
     
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
            {
             ....
             //Si la version appelée est obsolète
             return Task<HttpResponseMessage>.Factory.StartNew(() => new HttpResponseMessage(HttpStatusCode.HttpVersionNotSupported)
                {
                    ReasonPhrase = "Votre Application n'est pas à jour...."
                }, cancellationToken);
     
    }
    Coté client il faut que tu récupère l'erreur et l'afficher au client.
    j'espère que j'ai bien compris ta question.

  8. #8
    Membre confirmé
    Inscrit en
    Avril 2010
    Messages
    200
    Détails du profil
    Informations forums :
    Inscription : Avril 2010
    Messages : 200
    Par défaut
    Salut Chamamo,

    Oui tu as bien compris ma question et j'avais implémenté cette solution avant de t'avoir lu mais au moins j'ai un "tampon" de ta part sur ce que j'ai fait.

    J'ai cependant un autre problème. Je commence à implémenter le versioning dans mon réel projet mais je me rends compte que beaucoup trop de choses sont versionnées... Vraiment beaucoup...
    J'ai toute mon api, toutes mes entités business et tout ce qui est lié à ces entités (Helpers qui se chargent de transformer ces entités en entités "sql", toutes mes classes de ma couche service qui font appel à la couche Repository (pas besoin d'être modifiée elle)) de modifiés. Ça fait beaucoup de duplica de code (que j'avais accepté) mais beaucoup de renommage de namespace etc.

    Je suis toujours surpris de voir que tu es le seul à me répondre Chamamo, personne d'autre n'a dû implémenter du versioning d'API ? C'est pas possible...

  9. #9
    Membre émérite Avatar de chamamo
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    588
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 588
    Par défaut
    C'est pour ça que j'ai évité le versionning de chaque ApiController, je vérifie seulement la compatibilité globale, je vérifie que le version du client est supérieure ou égale à la version minimale supportée, et je vérifie que la version du serveur est supérieure ou égale à la version compatible avec l'application cliente, donc deux versionning.

    TU peux donner plus de détails sur ton problème?

  10. #10
    Membre confirmé
    Inscrit en
    Avril 2010
    Messages
    200
    Détails du profil
    Informations forums :
    Inscription : Avril 2010
    Messages : 200
    Par défaut
    C'est pour ça que j'ai évité le versionning de chaque ApiController
    Tu entends quoi exactement par là ? Ce que j'ai commencé à mettre en place versionne toute la couche API. Tous mes api controllers sont dans un namespace spécifique que je sélectionne avec SelectController. Donc mon problème ne vient pas vraiment de là.

    je vérifie que le version du client est supérieure ou égale à la version minimale supportée
    Donc tu utilises bien du versioning, mais où ? Comment ? J'ai pas compris comment tu avais mis ça en place du coup.

    je vérifie que la version du serveur est supérieure ou égale à la version compatible avec l'application cliente, donc deux versionning.
    Pour ma part j'ai mis en place le versionning sur l'API justement parce que je ne veux q'une seule version du serveur. Je ne comprends pas l'intérêt de faire du versionning si tel client est associé à tel serveur.

    Pour expliquer un peu plus, admettons que j'ai une classe AccountApiController. Dans ce controller je fais appel à une couche Service (dans un autre projet) qui se charge via la classe AccountService, de transformer mon entité AccountBusiness en entité AccountSql, puis fait appel à la classe AccountRepository dans la couche Repository (un autre projet) qui se charge d'effectuer la requête en base.

    La seule couche qui n'est pas modifiée est ma couche Repository, étant donné qu'elle ne travaille qu'avec des objets SQL.
    Mais tout ce qui travail avec mon entité business doit être versionné puisque mon entité business est versionné. tu comprends mieux ?

  11. #11
    Membre émérite Avatar de chamamo
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    588
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 588
    Par défaut
    je n'aurai peu être pas du utiliser le mot versionning, je vérifie plutôt la compatibilité globale, et je ne fais pas d'association, chaque version du client est compatible avec plusieurs versions du serveur, coté serveur aussi

    Par exemple la version du client est la 1.0, elle est compatible avec la version 1.0,1.2...1.5 du serveur mais pas la 1.6, coté serveur, si la version du serveur est la 2.0, elle est compatible avec la version 1.6, 1.5, 1.4 mais pas la version 1.3 du client.

    Dans ton cas je pense que tu es obligé de versionner la couche services, tes entités aussi.

    Imaginons que entre deux version d'un controller tu as rajouté un champs obligatoire dans ton entité, si tu valides par exemple les données, tu dois faire une validation pour l'entité sans ce champs et une autre qui prend en compte celui la.

  12. #12
    Rédacteur
    Avatar de The_badger_man
    Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2005
    Messages
    2 745
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 745
    Par défaut
    Citation Envoyé par Air P-E Voir le message
    Mais tout ce qui travail avec mon entité business doit être versionné puisque mon entité business est versionné. tu comprends mieux ?
    Tu as un exemple de versionning ici: http://www.culbertsonexchange.com/wp/?p=318
    Les règles du forum
    Le trio magique : FAQ + Cours + fonction rechercher
    Mes articles
    Pas de questions par messages privés svp

    Software is never finished, only abandoned.

  13. #13
    Membre confirmé
    Inscrit en
    Avril 2010
    Messages
    200
    Détails du profil
    Informations forums :
    Inscription : Avril 2010
    Messages : 200
    Par défaut
    @Chamamo,
    J'ai bien peur que oui, c'est d'ailleurs ce que j'ai fait. En y réfléchissant, je me dis que c'est pas plus mal. Lors d'un changement de version, j'ai fait un cas concret pour voir ce que ça donne : Un copier/coller du dossier version, un petit coup de ReSharper pour modifier les namespaces et le tour est joué.
    De plus la version ne changera que très rarement logiquement. De toute façon, j'ai l'impression de ne pas avoir le choix et il n'y a pas de solutions miracles.

    @The_badger_man,
    Ton lien est intéressant et je suis étonné de ne pas avoir pensé à une chose aussi simple !
    Mais j'y vois un inconvénient, cela implique de n'utiliser qu'une seule version de mes entités si je puis dire.
    En effet si je rajoute des champs dans mon entité Account (pour prendre un exemple), avec cette mise en place cela signifie que les versions précédentes se verront dotées de ce champ en plus ce qui n'est pas normal, à mon sens. Je ne sais pas ce que tu en penses.

Discussions similaires

  1. Réponses: 13
    Dernier message: 18/07/2010, 18h10
  2. Architecture Web API pour accès en base de données
    Par ahmed_automation dans le forum Flex
    Réponses: 7
    Dernier message: 09/04/2010, 09h51
  3. Réponses: 7
    Dernier message: 22/06/2009, 17h40
  4. Une Web API pour le forum, c'est imaginable ?
    Par mchk0123 dans le forum Evolutions du club
    Réponses: 7
    Dernier message: 11/06/2007, 10h32
  5. [services Web] API generant des Formulaire
    Par subzero82 dans le forum Services Web
    Réponses: 2
    Dernier message: 29/05/2006, 18h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo