Comment versionner votre API Web

Vous devez toujours effectuer une version de votre API Web tout en conservant autant que possible le même URI. Imaginez une situation où vous disposez d'une API Web qui est opérationnelle en production et qui est utilisée par les utilisateurs. Supposons maintenant que vous ayez besoin de plus de fonctionnalités dans l'API Web tout en conservant la fonctionnalité existante intacte. Vous pouvez avoir quelques utilisateurs qui ont encore besoin de l'ancienne API, tandis que d'autres auront besoin d'une version avec des fonctionnalités nouvelles ou étendues. C'est exactement là que la gestion des versions de l'API Web vient à la rescousse.

Vous pouvez versionner votre API Web de l'une des manières suivantes:

  1. Utiliser des URL: les informations de version sont spécifiées dans l'URL sous forme de chaîne de requête.
  2. Utiliser des en-têtes de demande personnalisés: les informations de version de votre contrôleur sont spécifiées dans l'en-tête de la demande sans aucune modification de l'URL.
  3. Utiliser les en-têtes Accept: les en-têtes Accept définissent généralement le type de média et les encodages de caractères. Vous pouvez transmettre les informations de version de votre API Web via les en-têtes d'acceptation sans avoir à modifier l'URL.

API Web de contrôle de version à l'aide d'URL

Considérez les contrôleurs API Web suivants, qui ont été nommés  AuthorsV1Controlleret AuthorsV2Controllerrespectivement.

public class AuthorsV1Controller: ApiController

    {

        [HttpGet]

        public IEnumerable GetAuthors ()

        {

          retourne une nouvelle chaîne [] {"Joydip Kanjilal", "Gerben Wierda"};

        }

    }

public class AuthorsV2Controller: ApiController

    {

        [HttpGet]

        public IEnumerable GetAuthors ()

        {

            renvoie une nouvelle chaîne [] {"Joydip Kanjilal, INDE", "Gerben Wierda, Pays-Bas"};

        }

    }

Pour simplifier cette illustration, j'ai incorporé une méthode nommée GetAuthors()dans chaque contrôleur. Alors que GetAuthors()in AuthorsV1Controllerrenvoie uniquement les noms des auteurs, GetAuthors()in AuthorsV2Controller(la nouvelle version) renvoie les noms des auteurs ainsi que les noms des pays dans lesquels résident les auteurs.

L'extrait de code suivant montre comment les deux contrôleurs utilisent la méthode Register de la WebApiConfigclasse.

config.Routes.MapHttpRoute (

                nom: "WebAPIV1",

                routeTemplate: "api / v1 / {controller} / {id}",

                par défaut: nouveau {controller = "AuthorsV1Controller", action = "GetAuthors", id = RouteParameter.Optional}

            );

config.Routes.MapHttpRoute (

                nom: "WebAPIV2",

                routeTemplate: "api / v2 / {controller} / {id}",

                par défaut: new {controller = "AuthorsV2Controller", action = "GetAuthors", id = RouteParameter.Optional}

            );

Vous pouvez maintenant appeler la méthode API Web GetAuthorsà l'aide de l'URL suivante.

// localhost / WebAPI / api / v1 / Authors / GetAuthors

Versioning de l'API Web à l'aide de l'en-tête de requête

Vous pouvez également implémenter la gestion des versions de l'API Web à l'aide de l'en-tête de la requête. Pour ce faire, vous devez implémenter une classe personnalisée qui étend la DefaultHttpControllerSelectorclasse, puis la remplacer SelectControllerdans votre classe personnalisée. Notez que la DefaultHttpControllerSelectorclasse implémente l' IHttpControllerSelectorinterface. SelectControllerappelle en GetControllerNameinterne et accepte une instance de HttpRequestMessagecomme paramètre.

L'extrait de code suivant illustre comment vous pouvez récupérer les informations de version à partir de l'en-tête de la demande.

chaîne privée GetControllerVersionFromRequestHeader (requête HttpRequestMessage)

        {

            var acceptHeader = request.Headers.Accept;

            const string headerName = "Version";

            string controllerVersion = string.Empty;

            if (request.Headers.Contains (headerName))

            {

                controllerVersion = "V" + request.Headers.GetValues ​​(headerName) .First ();               

            }

            return controllerVersion;

        }

Versioning de l'API Web à l'aide de l'en-tête d'acceptation

La méthode suivante montre comment vous pouvez récupérer les informations de version de votre API Web à partir de l'en-tête d'acceptation. La méthode vérifie le type MIME et renvoie les informations de version de manière appropriée. Si le type de support n'est pas application/json, la version par défaut est renvoyée sous la forme V1.

private string GetControllerVersionFromAcceptHeader(HttpRequestMessage request)

        {

            var acceptHeader = request.Headers.Accept;

            string controllerVersion = string.Empty;

            foreach (var mime in acceptHeader)

            {

                if (mime.MediaType.Equals("application/json"))

                {

                    NameValueHeaderValue version = mime.Parameters.FirstOrDefault(v => v.Name.Equals("Version", StringComparison.OrdinalIgnoreCase));

                    controllerVersion = "V" + version.Value.ToString();

                    return controllerVersion;

                }

            }

            return "V1";

        }

You can invoke your Web API from Fiddler by passing the accept header as shown below.

Accept: application/json; charset=utf-8;version=2

The following code listing illustrates how you can override SelectController to select a controller dynamically. Note how GetControllerVersionFromRequestHeader has been used. If you would like to retrieve the controller version from the accept header, you should leverage GetControllerVersionFromAcceptHeader instead.

public override HttpControllerDescriptor SelectController(HttpRequestMessage request)

        {

            try

            {

                string controllerName = base.GetControllerName(request);

                var controllers = GetControllerMapping();

                var routeData = request.GetRouteData();

                string controllerVersion = GetControllerVersionFromRequestHeader(request);             

                controllerName = String.Format("{0}{1}", controllerName, controllerVersion);

                HttpControllerDescriptor controllerDescriptor;

                if (!controllers.TryGetValue(controllerName, out controllerDescriptor))

                {

                    string message = "No HTTP resource was found that matches the specified request URI {0}";

                    throw new HttpResponseException(request.CreateErrorResponse(System.Net.HttpStatusCode.NotFound, String.Format(message, request.RequestUri)));

                }

                return controllerDescriptor;

            }

            catch (Exception ex)

            {

                throw new HttpResponseException(request.CreateErrorResponse(System.Net.HttpStatusCode.NotFound, String.Format(ex.Message, request.RequestUri)));

            }

        }

You should add the following line in the Register method of the WebApiConfig class to provide support for controller selection at runtime.

config.Services.Replace (typeof (IHttpControllerSelector), nouveau ControllerSelector ((config)));

Vous pouvez maintenant utiliser Fiddler pour tester votre API Web - utilisez l'onglet de composition de Fiddler et fournissez l'URL et les informations de version, le cas échéant. Si vous souhaitez que la version 2 de votre contrôleur d'API Web soit appelée, vous devez spécifier Version: 2lors de la composition des informations d'en-tête de demande dans l'onglet Compositeur de Fiddler.