Introduction aux services web

Ce guide montre comment utiliser différentes technologies de service web. Les sujets abordés incluent la communication avec les services REST, les services SOAP et les services Windows Communication Foundation.

Pour fonctionner correctement, de nombreuses applications mobiles dépendent du cloud. Par conséquent, l’intégration de services web dans les applications mobiles est un scénario courant. La plateforme Xamarin prend en charge la consommation de différentes technologies de service web, et inclut une prise en charge intégrée et tierce pour la consommation des services RESTful, ASMX et Windows Communication Foundation (WCF).

Pour les clients utilisant Xamarin.Forms, il existe des exemples complets utilisant chacune de ces technologies dans la documentation des services web Xamarin.Forms .

Important

Dans iOS 9, App Transport Security (ATS) applique des connexions sécurisées entre les ressources Internet (telles que le serveur principal de l’application) et l’application, empêchant ainsi la divulgation accidentelle d’informations sensibles. Étant donné qu’ATS est activé par défaut dans les applications conçues pour iOS 9, toutes les connexions sont soumises aux exigences de sécurité ATS. Si les connexions ne répondent pas à ces exigences, elles échouent avec une exception.

Vous pouvez refuser atS s’il n’est pas possible d’utiliser le protocole et la HTTPS communication sécurisée pour les ressources Internet. Pour ce faire, vous pouvez mettre à jour le fichier Info.plist de l’application. Pour plus d’informations, consultez Sécurité du transport d’applications.

REST

REST (Representational State Transfer) est un style d’architecture pour la création de services web. Les requêtes REST sont effectuées via HTTP en utilisant les mêmes verbes HTTP que ceux utilisés par les navigateurs web pour récupérer des pages web et envoyer des données aux serveurs. Les verbes sont :

  • GET : cette opération est utilisée pour récupérer des données auprès du service web.
  • POST : cette opération est utilisée pour créer un nouvel élément de données sur le service web.
  • PUT : cette opération est utilisée pour mettre à jour un élément de données sur le service web.
  • PATCH : cette opération est utilisée pour mettre à jour un élément de données sur le service web en décrivant un ensemble d’instructions sur la façon dont l’élément doit être modifié. Ce verbe n’est pas utilisé dans l’exemple d’application.
  • DELETE : cette opération est utilisée pour supprimer un élément de données sur le service web.

Les API de service web qui adhèrent à REST sont appelées API RESTful et elles sont définies en utilisant les éléments suivants :

  • URI de base.
  • Des méthodes HTTP, comme GET, POST, PUT, PATCH ou DELETE.
  • Type de média pour les données, tel que JSON (JavaScript Object Notation).

La simplicité de REST a contribué à en faire la méthode principale pour accéder aux services web dans les applications mobiles.

Utilisation des services REST

Il existe un certain nombre de bibliothèques et de classes qui peuvent être utilisées pour utiliser des services REST, et les sous-sections suivantes les décrivent. Pour plus d’informations sur l’utilisation d’un service REST, consultez Utiliser un service web RESTful.

HttpClient

Les bibliothèques clientes HTTP Microsoft fournissent la HttpClient classe , qui est utilisée pour envoyer et recevoir des requêtes via HTTP. Il fournit des fonctionnalités permettant d’envoyer des requêtes HTTP et de recevoir des réponses HTTP à partir d’une ressource identifiée par l’URI. Chaque requête est envoyée en tant qu’opération asynchrone. Pour plus d’informations sur les opérations asynchrones, consultez Vue d’ensemble de la prise en charge asynchrone.

La HttpResponseMessage classe représente un message de réponse HTTP reçu du service web après l’envoi d’une requête HTTP. Il contient des informations sur la réponse, notamment le code status, les en-têtes et le corps. La HttpContent classe représente le corps HTTP et les en-têtes de contenu, tels que Content-Type et Content-Encoding. Le contenu peut être lu à l’aide de l’une ReadAs des méthodes, telles que ReadAsStringAsync et ReadAsByteArrayAsync, selon le format des données.

Pour plus d’informations sur la HttpClient classe, consultez Création de l’objet HTTPClient.

HTTPWebRequest

L’appel de services web avec HTTPWebRequest implique :

  • Création de la demande instance pour un URI particulier.
  • Définition de différentes propriétés HTTP sur la requête instance.
  • Récupération d’un HttpWebResponse à partir de la requête.
  • Lecture des données hors de la réponse.

Par exemple, le code suivant récupère des données du service web de la Bibliothèque nationale de médecine des États-Unis :

var rxcui = "198440";
var request = HttpWebRequest.Create(string.Format(@"https://rxnav.nlm.nih.gov/REST/RxTerms/rxcui/{0}/allinfo", rxcui));
request.ContentType = "application/json";
request.Method = "GET";

using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
  if (response.StatusCode != HttpStatusCode.OK)
     Console.Out.WriteLine("Error fetching data. Server returned status code: {0}", response.StatusCode);
  using (StreamReader reader = new StreamReader(response.GetResponseStream()))
  {
               var content = reader.ReadToEnd();
               if(string.IsNullOrWhiteSpace(content)) {
                       Console.Out.WriteLine("Response contained empty body...");
               }
               else {
                       Console.Out.WriteLine("Response Body: \r\n {0}", content);
               }

               Assert.NotNull(content);
  }
}

L’exemple ci-dessus crée un qui retourne des HttpWebRequest données au format JSON. Les données sont retournées dans un HttpWebResponse, à partir duquel un StreamReader peut être obtenu pour lire les données.

RestSharp

Une autre approche de la consommation des services REST consiste à utiliser la bibliothèque RestSharp . RestSharp encapsule les requêtes HTTP, y compris la prise en charge de la récupération des résultats sous forme de contenu de chaîne brute ou en tant qu’objet C# désérialisé. Par exemple, le code suivant effectue une demande au service web de la Bibliothèque nationale de médecine des États-Unis et récupère les résultats sous forme de chaîne au format JSON :

var request = new RestRequest(string.Format("{0}/allinfo", rxcui));
request.RequestFormat = DataFormat.Json;
var response = Client.Execute(request);
if(string.IsNullOrWhiteSpace(response.Content) || response.StatusCode != System.Net.HttpStatusCode.OK) {
       return null;
}
rxTerm = DeserializeRxTerm(response.Content);

DeserializeRxTerm est une méthode qui prend la chaîne JSON brute de la propriété et la RestSharp.RestResponse.Content convertit en objet C#. La désérialisation des données retournées par les services web est abordée plus loin dans cet article.

Nsurlconnection

Outre les classes disponibles dans la bibliothèque de classes de base (BCL) Mono, telles que HttpWebRequest, et les bibliothèques C# tierces, telles que RestSharp, les classes spécifiques à la plateforme sont également disponibles pour l’utilisation des services web. Par exemple, dans iOS, les NSUrlConnection classes et NSMutableUrlRequest peuvent être utilisées.

L’exemple de code suivant montre comment appeler le service web de la Bibliothèque nationale de médecine des États-Unis à l’aide de classes iOS :

var rxcui = "198440";
var request = new NSMutableUrlRequest(new NSUrl(string.Format("https://rxnav.nlm.nih.gov/REST/RxTerms/rxcui/{0}/allinfo", rxcui)),
       NSUrlRequestCachePolicy.ReloadRevalidatingCacheData, 20);
request["Accept"] = "application/json";

var connectionDelegate = new RxTermNSURLConnectionDelegate();
var connection = new NSUrlConnection(request, connectionDelegate);
connection.Start();

public class RxTermNSURLConnectionDelegate : NSUrlConnectionDelegate
{
       StringBuilder _ResponseBuilder;
       public bool IsFinishedLoading { get; set; }
       public string ResponseContent { get; set; }

       public RxTermNSURLConnectionDelegate()
               : base()
       {
               _ResponseBuilder = new StringBuilder();
       }

       public override void ReceivedData(NSUrlConnection connection, NSData data)
       {
               if(data != null) {
                       _ResponseBuilder.Append(data.ToString());
               }
       }
       public override void FinishedLoading(NSUrlConnection connection)
       {
               IsFinishedLoading = true;
               ResponseContent = _ResponseBuilder.ToString();
       }
}

En règle générale, les classes spécifiques à la plateforme pour l’utilisation des services web doivent être limitées aux scénarios où du code natif est porté vers C#. Dans la mesure du possible, le code d’accès au service web doit être portable afin qu’il puisse être partagé multiplateforme.

ServiceStack

Une autre option pour appeler des services web est la bibliothèque Service Stack . Par exemple, le code suivant montre comment utiliser la méthode de Service Stack pour émettre une demande de IServiceClient.GetAsync service :

client.GetAsync<CustomersResponse>("",
          (response) => {
               foreach(var c in response.Customers) {
                       Console.WriteLine(c.CompanyName);
               }
       },
       (response, ex) => {
               Console.WriteLine(ex.Message);
       });

Important

Bien que des outils tels que ServiceStack et RestSharp facilitent l’appel et l’utilisation de services REST, il est parfois non trivial de consommer du code XML ou JSON qui n’est pas conforme aux conventions de sérialisation DataContract standard. Si nécessaire, appelez la demande et gérez explicitement la sérialisation appropriée à l’aide de la bibliothèque ServiceStack.Text décrite ci-dessous.

Consommation de données RESTful

Les services web RESTful utilisent généralement des messages JSON pour retourner des données au client. JSON est un format textuel d’échange de données qui produit des charges utiles compactes, ce qui réduit les besoins en bande passante lors de l’envoi de données. Dans cette section, les mécanismes de consommation des réponses RESTful en JSON et en plain-old-XML (POX) seront examinés.

System.JSON

La plateforme Xamarin est fournie avec la prise en charge de JSON prête à l’emploi. À l’aide d’un JsonObject, les résultats peuvent être récupérés comme indiqué dans l’exemple de code suivant :

var obj = JsonObject.Parse(json);
var properties = obj["rxtermsProperties"];
term.BrandName = properties["brandName"];
term.DisplayName = properties["displayName"];
term.Synonym = properties["synonym"];
term.FullName = properties["fullName"];
term.FullGenericName = properties["fullGenericName"];
term.Strength = properties["strength"];

Toutefois, il est important de savoir que les System.Json outils chargent l’intégralité des données en mémoire.

JSON.NET

La bibliothèque JSON.NET NewtonSoft est une bibliothèque largement utilisée pour sérialiser et désérialiser des messages JSON. L’exemple de code suivant montre comment utiliser JSON.NET pour désérialiser un message JSON dans un objet C# :

var term = new RxTerm();
var properties = JObject.Parse(json)["rxtermsProperties"];
term.BrandName = properties["brandName"].Value<string>();
term.DisplayName = properties["displayName"].Value<string>();
term.Synonym = properties["synonym"].Value<string>();;
term.FullName = properties["fullName"].Value<string>();;
term.FullGenericName = properties["fullGenericName"].Value<string>();;
term.Strength = properties["strength"].Value<string>();
term.RxCUI = properties["rxcui"].Value<string>();

ServiceStack.Text

ServiceStack.Text est une bibliothèque de sérialisation JSON conçue pour fonctionner avec la bibliothèque ServiceStack. L’exemple de code suivant montre comment analyser JSON à l’aide d’un ServiceStack.Text.JsonObject:

var result = JsonObject.Parse(json).Object("rxtermsProperties")
       .ConvertTo(x => new RxTerm {
               BrandName = x.Get("brandName"),
               DisplayName = x.Get("displayName"),
               Synonym = x.Get("synonym"),
               FullName = x.Get("fullName"),
               FullGenericName = x.Get("fullGenericName"),
               Strength = x.Get("strength"),
               RxTermDoseForm = x.Get("rxtermsDoseForm"),
               Route = x.Get("route"),
               RxCUI = x.Get("rxcui"),
               RxNormDoseForm = x.Get("rxnormDoseForm"),
       });

System.Xml.Linq

En cas de consommation d’un service web REST xml, LINQ to XML pouvez être utilisé pour analyser le code XML et remplir un objet C# inline, comme illustré dans l’exemple de code suivant :

var doc = XDocument.Parse(xml);
var result = doc.Root.Descendants("rxtermsProperties")
.Select(x=> new RxTerm()
       {
               BrandName = x.Element("brandName").Value,
               DisplayName = x.Element("displayName").Value,
               Synonym = x.Element("synonym").Value,
               FullName = x.Element("fullName").Value,
               FullGenericName = x.Element("fullGenericName").Value,
               //bind more here...
               RxCUI = x.Element("rxcui").Value,
       });

service web ASP.NET (ASMX)

ASMX offre la possibilité de créer des services web qui envoient des messages à l’aide du protocole SOAP (Simple Object Access Protocol). SOAP est un protocole indépendant de la plateforme et du langage pour la création et l’accès à des services web. Les consommateurs d’un service ASMX n’ont pas besoin de connaître la plateforme, le modèle objet ou le langage de programmation utilisé pour implémenter le service. Il leur suffit de comprendre comment envoyer et recevoir des messages SOAP.

Un message SOAP est un document XML contenant les éléments suivants :

  • Élément racine nommé Envelope qui identifie le document XML en tant que message SOAP.
  • Élément Header facultatif qui contient des informations spécifiques à l’application, telles que des données d’authentification. Si l’élément Header est présent, il doit être le premier élément enfant de l’élément Envelope .
  • Élément Body obligatoire qui contient le message SOAP destiné au destinataire.
  • Élément Fault facultatif utilisé pour indiquer les messages d’erreur. Si l’élément Fault est présent, il doit s’agir d’un élément enfant de l’élément Body .

SOAP peut fonctionner sur de nombreux protocoles de transport, notamment HTTP, SMTP, TCP et UDP. Toutefois, un service ASMX ne peut fonctionner que via HTTP. La plateforme Xamarin prend en charge les implémentations SOAP 1.1 standard sur HTTP, et cela inclut la prise en charge de nombreuses configurations de service ASMX standard.

Génération d’un proxy

Un proxy doit être généré pour utiliser un service ASMX, ce qui permet à l’application de se connecter au service. Le proxy est construit en consommant des métadonnées de service qui définissent les méthodes et la configuration de service associée. Ces métadonnées sont exposées en tant que document WSDL (Web Services Description Language) généré par le service web. Le proxy est créé en utilisant Visual Studio pour Mac ou Visual Studio pour ajouter une référence web pour le service web aux projets spécifiques à la plateforme.

L’URL du service web peut être une source distante hébergée ou une ressource de système de fichiers local accessible via le préfixe de file:/// chemin d’accès, par exemple :

file:///Users/myUserName/projects/MyProjectName/service.wsdl

L’URL du service web peut être une source distante hébergée ou une ressource de système de fichiers local accessible via le préfixe de chemin de fichier

Cela génère le proxy dans le dossier Web ou Références de service du projet. Étant donné qu’un proxy est généré du code, il ne doit pas être modifié.

Ajout manuel d’un proxy à un projet

Si vous avez un proxy existant qui a été généré à l’aide d’outils compatibles, cette sortie peut être consommée lorsqu’elle est incluse dans votre projet. Dans Visual Studio pour Mac, utilisez l’option de menu Ajouter des fichiers... pour ajouter le proxy. En outre, cela nécessite queSystem.Web.Services.dll soient référencés explicitement à l’aide de la boîte de dialogue Ajouter des références... .

Utilisation du proxy

Les classes proxy générées fournissent des méthodes pour consommer le service web qui utilisent le modèle de conception APM (Asynchrone Programming Model). Dans ce modèle, une opération asynchrone est implémentée en tant que deux méthodes nommées BeginOperationName et EndOperationName, qui commencent et mettent fin à l’opération asynchrone.

La méthode BeginOperationName commence l’opération asynchrone et retourne un objet qui implémente l’interface IAsyncResult . Après avoir appelé BeginOperationName, une application peut continuer à exécuter des instructions sur le thread appelant, tandis que l’opération asynchrone a lieu sur un thread de pool de threads.

Pour chaque appel à BeginOperationName, l’application doit également appeler EndOperationName pour obtenir les résultats de l’opération. La valeur de retour de EndOperationName est le même type renvoyé par la méthode de service web synchrone. L’exemple de code ci-dessous en est un exemple :

public async Task<List<TodoItem>> RefreshDataAsync ()
{
  ...
  var todoItems = await Task.Factory.FromAsync<ASMXService.TodoItem[]> (
    todoService.BeginGetTodoItems,
    todoService.EndGetTodoItems,
    null,
    TaskCreationOptions.None);
  ...
}

La bibliothèque parallèle de tâches (TPL) peut simplifier le processus d’utilisation d’une paire de méthodes début/fin APM en encapsulant les opérations asynchrones dans le même Task objet. Cette encapsulation est fournie par plusieurs surcharges de la Task.Factory.FromAsync méthode. Cette méthode crée un Task qui exécute la méthode une fois la TodoService.BeginGetTodoItemsTodoService.EndGetTodoItems méthode terminée, avec le null paramètre indiquant qu’aucune donnée n’est passée dans le BeginGetTodoItems délégué. Enfin, la valeur de l’énumération TaskCreationOptions spécifie que le comportement par défaut pour la création et l’exécution de tâches doit être utilisé.

Pour plus d’informations sur APM, consultez Modèle de programmation asynchrone et TPL et Programmation asynchrone .NET Framework traditionnelle sur MSDN.

Pour plus d’informations sur la consommation d’un service ASMX, consultez Consommer un service web ASP.NET (ASMX).

Windows Communication Foundation (WCF)

WCF est l’infrastructure unifiée de Microsoft pour la création d’applications orientées service. Il permet aux développeurs de créer des applications distribuées sécurisées, fiables, traitées et interopérables.

WCF décrit un service avec une variété de contrats différents, notamment :

  • Contrats de données : définissez les structures de données qui constituent la base du contenu d’un message.
  • Contrats de message : composez des messages à partir de contrats de données existants.
  • Contrats d’erreur : autorisent la spécification d’erreurs SOAP personnalisées.
  • Contrats de service : spécifiez les opérations prises en charge par les services et les messages nécessaires pour interagir avec chaque opération. Ils spécifient également tout comportement d’erreur personnalisé qui peut être associé aux opérations sur chaque service.

Il existe des différences entre les services web ASP.NET (ASMX) et WCF, mais il est important de comprendre que WCF prend en charge les mêmes fonctionnalités qu’ASMX : les messages SOAP sur HTTP.

Important

La prise en charge de la plateforme Xamarin pour WCF est limitée aux messages SOAP encodés texte sur HTTP/HTTPS à l’aide de la BasicHttpBinding classe . En outre, la prise en charge de WCF nécessite l’utilisation d’outils disponibles uniquement dans un environnement Windows pour générer le proxy.

Génération d’un proxy

Un proxy doit être généré pour utiliser un service WCF, ce qui permet à l’application de se connecter au service. Le proxy est construit en consommant des métadonnées de service qui définissent les méthodes et la configuration de service associée. Ces métadonnées sont exposées sous la forme d’un document WSDL (Web Services Description Language) généré par le service web. Le proxy peut être créé à l’aide du fournisseur Microsoft WCF Web Service Reference dans Visual Studio 2017 pour ajouter une référence de service pour le service web à une bibliothèque .NET Standard.

Une alternative à la création du proxy à l’aide du fournisseur Microsoft WCF Web Service Reference dans Visual Studio 2017 consiste à utiliser l’outil Utilitaire de métadonnées ServiceModel (svcutil.exe). Pour plus d’informations, consultez ServiceModel Metadata Utility Tool (Svcutil.exe).

Configuration du proxy

La configuration du proxy généré prend généralement deux arguments de configuration (en fonction de SOAP 1.1/ASMX ou WCF) lors de l’initialisation : les EndpointAddress informations de liaison associées et/ou, comme illustré dans l’exemple ci-dessous :

var binding = new BasicHttpBinding () {
       Name= "basicHttpBinding",
       MaxReceivedMessageSize = 67108864,
};

binding.ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas() {
       MaxArrayLength = 2147483646,
       MaxStringContentLength = 5242880,
};

var timeout = new TimeSpan(0,1,0);
binding.SendTimeout= timeout;
binding.OpenTimeout = timeout;
binding.ReceiveTimeout = timeout;

client = new Service1Client (binding, new EndpointAddress ("http://192.168.1.100/Service1.svc"));

Une liaison est utilisée pour spécifier les détails du transport, de l’encodage et du protocole requis pour que les applications et les services communiquent entre eux. Spécifie BasicHttpBinding que les messages SOAP encodés texte seront envoyés via le protocole de transport HTTP. La spécification d’une adresse de point de terminaison permet à l’application de se connecter à différentes instances du service WCF, à condition qu’il existe plusieurs instances publiées.

Utilisation du proxy

Les classes proxy générées fournissent des méthodes pour consommer les services web qui utilisent le modèle de conception APM (Asynchrone Programming Model). Dans ce modèle, une opération asynchrone est implémentée sous la forme de deux méthodes nommées BeginOperationName et EndOperationName, qui commencent et terminent l’opération asynchrone.

La méthode BeginOperationName commence l’opération asynchrone et retourne un objet qui implémente l’interface IAsyncResult . Après avoir appelé BeginOperationName, une application peut continuer à exécuter des instructions sur le thread appelant, tandis que l’opération asynchrone a lieu sur un thread de pool de threads.

Pour chaque appel à BeginOperationName, l’application doit également appeler EndOperationName pour obtenir les résultats de l’opération. La valeur de retour de EndOperationName est le même type renvoyé par la méthode de service web synchrone. L’exemple de code ci-dessous en est un exemple :

public async Task<List<TodoItem>> RefreshDataAsync ()
{
  ...
  var todoItems = await Task.Factory.FromAsync <ObservableCollection<TodoWCFService.TodoItem>> (
    todoService.BeginGetTodoItems,
    todoService.EndGetTodoItems,
    null,
    TaskCreationOptions.None);
  ...
}

La bibliothèque parallèle de tâches (TPL) peut simplifier le processus d’utilisation d’une paire de méthodes début/fin APM en encapsulant les opérations asynchrones dans le même Task objet. Cette encapsulation est fournie par plusieurs surcharges de la Task.Factory.FromAsync méthode. Cette méthode crée un Task qui exécute la méthode une fois la TodoServiceClient.BeginGetTodoItemsTodoServiceClient.EndGetTodoItems méthode terminée, avec le null paramètre indiquant qu’aucune donnée n’est passée dans le BeginGetTodoItems délégué. Enfin, la valeur de l’énumération TaskCreationOptions spécifie que le comportement par défaut pour la création et l’exécution de tâches doit être utilisé.

Pour plus d’informations sur APM, consultez Modèle de programmation asynchrone et TPL et Programmation asynchrone .NET Framework traditionnelle sur MSDN.

Pour plus d’informations sur la consommation d’un service WCF, consultez Utiliser un service web Windows Communication Foundation (WCF).

Utilisation de la sécurité du transport

Les services WCF peuvent utiliser la sécurité au niveau du transport pour se protéger contre l’interception des messages. La plateforme Xamarin prend en charge les liaisons qui utilisent la sécurité au niveau du transport à l’aide de SSL. Toutefois, il peut arriver que la pile ait besoin de valider le certificat, ce qui entraîne un comportement imprévu. La validation peut être remplacée en inscrivant un ServerCertificateValidationCallback délégué avant d’appeler le service, comme illustré dans l’exemple de code suivant :

System.Net.ServicePointManager.ServerCertificateValidationCallback +=
(se, cert, chain, sslerror) => { return true; };

Cela maintient le chiffrement du transport tout en ignorant la validation du certificat côté serveur. Toutefois, cette approche ne tient pas compte des préoccupations d’approbation associées au certificat et peut ne pas être appropriée. Pour plus d’informations, consultez Utilisation de racines approuvées respectueusement sur mono-project.com.

Utilisation de la sécurité des informations d’identification du client

Les services WCF peuvent également exiger que les clients de service s’authentifient à l’aide d’informations d’identification. La plateforme Xamarin ne prend pas en charge le protocole WS-Security, qui permet aux clients d’envoyer des informations d’identification à l’intérieur de l’enveloppe de message SOAP. Toutefois, la plateforme Xamarin prend en charge la possibilité d’envoyer des informations d’identification d’authentification DE base HTTP au serveur en spécifiant le approprié ClientCredentialType:

basicHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;

Ensuite, les informations d’identification d’authentification de base peuvent être spécifiées :

client.ClientCredentials.UserName.UserName = @"foo";
client.ClientCredentials.UserName.Password = @"mrsnuggles";

Pour plus d’informations sur l’authentification de base HTTP, bien que dans le contexte d’un service web REST, consultez Authentification d’un service web RESTful.