Comment travailler avec la négociation de contenu dans l'API Web

L'API Web ASP.Net est une infrastructure légère utilisée pour créer des services HTTP sans état et RESTful. Les services RESTful sont des services légers, sans état, basés sur le client-serveur et pouvant être mis en cache, basés sur le concept de ressources. REST est un style architectural - un ensemble de contraintes utilisées pour implémenter des services sans état. Il s'agit d'un paradigme architectural utilisé pour créer des services réutilisables et évolutifs.

La représentation d'une ressource dans le format demandé est un sujet intéressant car vous pouvez souvent vouloir consommer vos services à partir de différents types d'appareils. La négociation de contenu est l'un des concepts les plus importants de l'API Web. Bien qu'il s'agisse d'un concept relativement simple, il existe de nombreuses idées fausses et malentendus autour de ce sujet. Lors de la conception et de la mise en œuvre de services RESTful à l'aide de l'API Web, vous devrez souvent gérer la négociation de contenu.

Qu'est-ce que le contenu négocié et pourquoi est-il important?

La négociation de contenu peut être définie comme le processus d'inspection de la structure d'une requête HTTP entrante pour déterminer la meilleure représentation d'une ressource parmi plusieurs représentations disponibles de la même ressource. En substance, la négociation de contenu est un concept qui permet à la même URL de servir le même contenu dans différents formats. Vous pouvez profiter de la négociation de contenu pour sélectionner le type de média préféré.

Dans l'API Web, la négociation de contenu est effectuée par le moteur d'exécution (côté serveur) pour déterminer le formateur de type de média à utiliser pour renvoyer la réponse à une demande entrante du côté client.

La négociation de contenu est centrée sur le type de média et le formateur de type de média. Alors que le premier fait référence à la valeur de l'en-tête "content-type" dans la requête HTTP et la réponse HTTP, le second est utilisé pour convertir les types .NET en données HTTP correspondantes et vice-versa. Notez que le formateur de type de média dans l'API Web est représenté par une classe abstraite appelée MediaTypeFormatter.

L'infrastructure de l'API Web est fournie par défaut avec les formateurs suivants.

  • System.Net.Http.Formatting.JsonMediaTypeFormatter
  • System.Net.Http.Formatting.XmlMediaTypeFormatter
  • System.Net.Http.Formatting.FormUrlEncodedMediaTypeFormatter
  • System.Web.Http.ModelBinding.JQueryMvcFormUrlEncodedFormatter

Pour personnaliser la négociation de contenu dans l'API Web, le principal point d'extensibilité dont vous devez tirer parti est le mappage de type de média. Notez que l'API Web propose par défaut les mappages de types de médias suivants.

  • QueryStringMapping
  • UriPathExtensionMapping
  • RequestHeaderMapping
  • MediaRangeMapping

Pour créer votre mappage de type de média personnalisé, vous devez créer une classe qui étend le MediaTypeMapping comme indiqué dans l'extrait de code ci-dessous.

public class MediaTypeMapping : MediaTypeMapping

{

   protected override double OnTryMatchMediaType(HttpResponseMessage response)

     {

                //Write your custom code here

     }

}

L'extrait de code suivant illustre comment vous pouvez récupérer les noms de tous les formateurs pris en charge dans l'API Web en itérant la collection HttpConfiguration.Formatters.

   [HttpGet]

       public List GetAllFormatters()

       {

           List lstFormaters = new List();

           foreach (var formatter in this.Configuration.Formatters)

           {

               lstFormaters.Add(formatter.GetType().Name);

           }

           return lstFormaters;

       }

Explorons maintenant comment nous pouvons travailler avec la négociation de contenu pour sélectionner le formateur que nous voulons et récupérer le contenu dans le format dont nous avons besoin. Considérez la classe d'entité suivante.

public class CustomerDTO

   {

       public Int32 Id

       { get; set; }

       public string FirstName

       { get; set; }

       public string LastName

       { get; set; }

       public string Address

      { get; set; }

   }

Ensuite, supposons que vous disposez d'une méthode qui remplit les données dans une liste de type CustomerDTO et la renvoie.

private List GetCustomerData()

       {

           List lstCustomers = new List();

           CustomerDTO customer = new CustomerDTO();

           customer.Id = 1;

           customer.FirstName = "Joydip";

           customer.LastName = "Kanjilal";

           customer.Address = "Hyderabad, India";

           lstCustomers.Add(customer);

           return lstCustomers;

       }

La méthode d'API Web suivante montre comment vous pouvez renvoyer HttpResponseMessage en tant que réponse de votre méthode d'API Web en fonction du mécanisme de négociation de contenu par défaut disponible.

[HttpGet]

       public HttpResponseMessage GetCustomers()

       {

           List lstCustomers = GetCustomerData();

           IContentNegotiator negotiator = Configuration.Services.GetContentNegotiator();

           ContentNegotiationResult result = negotiator.Negotiate(typeof(CustomerDTO), Request, Configuration.Formatters);

           return new HttpResponseMessage()

           {

               Content = new ObjectContent (lstCustomers, result.Formatter, result.MediaType.MediaType)

         };

       }

Si vous deviez utiliser un formateur spécifique disponible dans la collection de formateurs, vous souhaiterez peut-être réécrire la même méthode que celle indiquée dans l'extrait de code ci-dessous.

[HttpGet]

       public HttpResponseMessage GetCustomers()

       {

           List lstCustomers = GetCustomerData();

           return new HttpResponseMessage()

           {

               Content = new ObjectContent (lstCustomers, Configuration.Formatters[1])

           };

      }

D'accord; mais comment construire votre propre formateur personnalisé alors? Eh bien, pour créer un formateur de type de média personnalisé, vous devez créer une classe qui étend la classe abstraite MediaTypeFormatter. Vous devez ensuite écrire votre code personnalisé dans la classe que vous avez créée pour remplacer les méthodes de la classe de base abstraite MediaTypeFormatter.

public class CustomMediaTypeFormatter : MediaTypeFormatter

   {

       public override bool CanReadType(Type type)

       {

           throw new NotImplementedException();

       }

       public override bool CanWriteType(Type type)

       {

           throw new NotImplementedException();

       }

   }

Une fois votre formateur personnalisé en place, vous pouvez l'ajouter facilement à la collection de formateurs:

config.Formatters.Add(new CustomMediaTypeFormatter ());