Démarrage rapide de la résolution des problèmes WCF

Cette rubrique prend la forme de questions et de réponses afin de décrire une partie des problèmes rencontrés les plus courants, les mesures à prendre pour les corriger et les endroits auxquels vous pouvez trouver davantage d'informations sur les problèmes.

Questions

Question : Je reçois parfois une MessageSecurityException sur la deuxième demande si mon client est inactif pendant un instant après la première demande. Que se passe-t-il ?

La deuxième demande peut échouer pour deux raisons principales : (1) la session a expiré ou (2) le serveur Web qui héberge le service est recyclé. Dans le premier cas, la session est valide jusqu'à ce que le service expire. Lorsque le service ne reçoit pas de demande du client pendant la période spécifiée dans la liaison du service (ReceiveTimeout), le service met fin à la session de sécurité. Les messages clients suivants engendrent une MessageSecurityException. Le client doit de nouveau établir une session sécurisée avec le service pour envoyer de futurs messages ou utiliser un jeton de contexte de sécurité avec état. Les jetons de contexte de sécurité avec état permettent également à une session sécurisée de survivre à un serveur Web en cours de recyclage. Pour plus d'informations sur l'utilisation de jetons de contexte de sécurité avec état dans une session sécurisée, consultez Comment : créer un jeton de contexte de sécurité avec état pour une session sécurisée. Vous pouvez également désactiver des sessions sécurisées. Lorsque vous utilisez la liaison WsHttpBinding, vous pouvez affecter à la propriété establishSecurityContext la valeur false pour désactiver des sessions sécurisées. Pour désactiver des sessions sécurisées pour d'autres liaisons, vous devez créer une liaison personnalisée. Pour plus d'informations sur la création d'une liaison personnalisée, consultez Comment : créer une liaison personnalisée à l'aide de SecurityBindingElement. Avant d'appliquer chacune de ces options, vous devez comprendre les conditions de sécurité de votre application.

Question : Mon service commence à rejeter les nouveaux clients une fois qu'environ 10 clients interagissent avec lui. Que se passe-t-il ?

Par défaut, les services peuvent avoir uniquement 10 sessions simultanées. Par conséquent, si les liaisons de service utilisent des sessions, le service accepte les nouvelles connexions clientes jusqu'à ce qu'il atteigne ce nombre, après quoi il refuse les nouvelles connexions clientes jusqu'à ce que l'une des sessions en cours se termine. Vous pouvez prendre en charge davantage de clients de plusieurs manières. Si votre service ne requiert pas de sessions, n'utilisez pas de liaison avec session. (Pour plus d'informations, consultez Utilisation de sessions.) Une autre option consiste à augmenter la limite de session en changeant la valeur de la propriété MaxConcurrentSessions par le nombre approprié à votre situation.

Question : Est-ce que je peux charger la configuration de mon service autrement qu'à partir du fichier de configuration de l'application WCF ?

Oui. Toutefois vous devez créer une classe ServiceHost personnalisée qui remplace la méthode ApplyConfiguration. À l'intérieur de cette méthode, vous pouvez appeler la base pour charger la configuration en premier (si vous souhaitez charger également les informations de configuration standard), mais vous pouvez également remplacer entièrement le système de chargement de la configuration. Notez que si vous souhaitez charger la configuration à partir d'un fichier de configuration différent du fichier de configuration de l'application, vous devez analyser le fichier de configuration vous-même et charger la configuration.

L'exemple de code suivant indique la manière de substituer la méthode ApplyConfiguration et de configurer directement un point de terminaison.

public class MyServiceHost : ServiceHost
{
  public MyServiceHost(Type serviceType, params Uri[] baseAddresses)  
    : base(serviceType, baseAddresses)
  { Console.WriteLine("MyServiceHost Constructor"); }

  protected override void ApplyConfiguration()
  {
    string straddress = GetAddress();
    Uri address = new Uri(straddress);
    Binding binding = GetBinding();
    base.AddServiceEndpoint(typeof(IData), binding, address);
  }

  string GetAddress()
  { return "http://MyMachine:7777/MyEndpointAddress/"; }

  Binding GetBinding()
  {
    WSHttpBinding binding = new WSHttpBinding();
    binding.Security.Mode = SecurityMode.None;
    return binding;
  }
}

Question : Mon service et mon client fonctionnent convenablement, mais je ne parviens pas à les faire fonctionner lorsque le client est sur un autre ordinateur ? Que se passe-t-il ?

En fonction de l'exception, plusieurs problèmes peuvent exister :

  • Vous devrez peut-être remplacer les adresses de point de terminaison du client par le nom d'hôte, au lieu de « localhost ».
  • Vous devrez peut-être ouvrir le port vers l'application. Pour plus d'informations, consultez Firewall Instructions dans les exemples du Kit de développement logiciel.
  • Pour d'autres problèmes possibles, consultez la rubrique des exemples, Running the Samples in a Workgroup and Across Machines.
  • Si votre client utilise des informations d'identification Windows et que l'exception est une SecurityNegotiationException, configurez Kerberos comme suit.
    1. Ajoutez les informations d'identification à l'élément de point de terminaison dans le fichier App.config du client :

      <endpoint 
        address="http://MyServer:8000/MyService/" 
        binding="wsHttpBinding" 
        bindingConfiguration="WSHttpBinding_IServiceExample" 
        contract="IServiceExample" 
        behaviorConfiguration="ClientCredBehavior" 
        name="WSHttpBinding_IServiceExample">
        <identity>
          <userPrincipalName value="name@corp.contoso.com"/>
        </identity>
      </endpoint>
      
    2. Exécutez le service auto-hébergé sous le compte System ou NetworkService. Vous pouvez exécuter cette commande pour créer une fenêtre de commande sous le compte System :

      at 12:36  /interactive "cmd.exe"
      
    3. Hébergez le service sous IIS (Internet Information Services), qui, par défaut, utilise le compte de nom principal de service (SPN).

    4. Enregistrez un nouveau SPN avec le domaine à l'aide de SetSPN. Notez que vous devez être administrateur de domaine pour effectuer cette opération.

Pour plus d'informations sur le protocole Kerberos, consultez Concepts de sécurité utilisés dans WCF et :

Question : Lorsque je lève une FaultException<Exception> où le type est une exception, je reçois toujours un type FaultException général sur le client et non le type générique. Que se passe-t-il ?

Il est fortement recommandé de créer votre propre type de données d'erreur personnalisé et de le déclarer comme le type de détail dans votre contrat d'erreur. La raison est que l'utilisation des types d'exceptions fournis par le système :

  • crée une dépendance des types qui supprime l'une des plus grandes forces des applications orientées service ;
  • ne peut pas dépendre d'exceptions sérialisant de manière standard (certaines, comme SecurityException risquent de pas être du tout sérialisables) ;
  • expose des informations d'implémentation interne aux clients. Pour plus d'informations, consultez Spécification et gestion des erreurs dans les contrats et les services.

Si vous déboguez une application, toutefois, vous pouvez sérialiser des informations sur les exceptions et les renvoyer au client à l'aide de la classe ServiceDebugBehavior.

Question : Il semble que les opérations monodirectionnelles et demande-réponse reviennent quasiment à la même vitesse lorsque la réponse ne contient pas de données. Que se passe-t-il ?

Spécifier qu'une opération est monodirectionnelle signifie uniquement que le contrat de l'opération accepte un message d'entrée et ne renvoie pas de message de sortie. Dans WCF, tous les appels clients sont renvoyés lorsque les données sortantes ont été écrites sur le fil ou qu'une exception est levée. Les opérations monodirectionnelles fonctionnent de la même façon et elles peuvent lever si le service ne peut pas être localisé ou bloquer si le service n'est pas préparé à accepter les données du réseau. En général, dans WCF, cela provoque des appels monodirectionnels renvoyés au client plus rapidement qu'une demande-réponse ; mais toute condition qui ralentit l'envoi des données sortantes sur le réseau ralentit les opérations monodirectionnelles ainsi que les opérations demande-réponse. Pour plus d'informations, consultez Services monodirectionnels et Accès aux services à l'aide d'un client.

Question : J'utilise un certificat X.509 avec mon service et j'obtiens une System.Security.Cryptography.CryptographicException. J'utilise un certificat X.509 avec mon service et j'obtiens une System.Security.Cryptography.CryptographicException. Que se passe-t-il ?

Cela se produit couramment après avoir modifié le compte d'utilisateur sous lequel le processus de travail IIS s'exécute. Par exemple, dans Windows XP, si vous modifiez le compte d'utilisateur par défaut sous lequel Aspnet_wp.exe s'exécute en remplaçant ASPNET par un compte d'utilisateur personnalisé, vous pouvez obtenir cette erreur. Lors de l'utilisation d'une clé privée, le processus qui l'utilise aura besoin des autorisations d'accès au fichier qui stocke cette clé.

Le cas échéant, vous devez octroyer des privilèges d'accès en lecture au compte du processus pour le fichier contenant la clé privée. Par exemple, si le processus de travail IIS s'exécute sous le compte Jacques, vous devrez octroyer à Jacques un accès en lecture au fichier contenant la clé privée.

Pour plus d'informations sur la manière d'octroyer au compte d'utilisateur l'accès correct au fichier contenant la clé privée pour un certificat X.509 spécifique, consultez Comment : rendre des certificats X.509 accessibles à WCF.

Question : J'ai remplacé les majuscules du premier paramètre d'une opération par des minuscules ; à présent, mon client lève une exception. Que se passe-t-il ?

La valeur des noms de paramètre dans la signature de l'opération fait partie du contrat et respecte la casse. Utilisez l'attribut System.ServiceModel.MessageParameterAttribute lorsque vous devez distinguer le nom du paramètre local et les métadonnées qui décrivent l'opération pour les applications clientes.

Question : J'utilise l'un de mes outils de suivi et j'obtiens une EndpointNotFoundException. Que se passe-t-il ?

Si vous utilisez un outil de suivi qui n'est pas le mécanisme de suivi WCF fourni par le système et que vous recevez une EndpointNotFoundException qui indique une incompatibilité du filtre d'adresse, vous devez utiliser la classe ClientViaBehavior pour diriger les messages vers l'utilitaire de suivi et faire rediriger ces messages par l'utilitaire vers l'adresse du service. La classe ClientViaBehavior altère l'en-tête d'adressage Via pour spécifier l'adresse réseau suivante séparément du dernier destinataire, indiqué par l'en-tête d'adressage To. Ce faisant, en revanche, ne modifiez pas l'adresse du point de terminaison, utilisée pour établir la valeur To.

L'exemple de code suivant présente un exemple de fichier de configuration d'un client.

<endpoint 
  address=https://localhost:8000/MyServer/
  binding="wsHttpBinding"
  bindingConfiguration="WSHttpBinding_IMyContract"
  behaviorConfiguration="MyClient" 
  contract="IMyContract" 
  name="WSHttpBinding_IMyContract">
</endpoint>
<behaviors>
  <endpointBehaviors>
    <behavior name="MyClient">
      <clientVia viaUri="https://localhost:8001/MyServer/"/>
    </behavior>
  </endpointBehaviors>
</behaviors>

Question : Qu'est-ce que l'adresse de base ? Comment est-elle liée à une adresse de point de terminaison ?

Une adresse de base est l'adresse racine d'une classe ServiceHost. Par défaut, si vous ajoutez une classe ServiceMetadataBehavior dans votre configuration de service, tous les points de terminaison WSDL (Web Services Description Language) que l'hôte publie sont récupérés à partir de l'adresse de base HTTP, plus toute adresse relative fournie au comportement de métadonnées, plus « ?wsdl ». Si vous connaissez bien ASP.NET et IIS, l'adresse de base équivaut au répertoire virtuel.

Question : Comment puis-je exposer plusieurs points de terminaison pour un seul service ?

Pour ce faire, ajoutez des éléments <endpoint> à l'élément <service> dans un fichier de configuration de l'application ou exécutez les étapes équivalentes par programme. Pour plus d'informations, consultez Spécification d'une adresse de point de terminaison, Comment : créer un point de terminaison de service dans la configuration. et Comment : créer un point de terminaison de service dans le code.

Question : Comment puis-je savoir quelles liaisons prennent en charge des comportements différents ?

Pour plus d'informations sur les liaisons fournies par le système et les fonctionnalités qu'elles prennent en charge, consultez Liaisons fournies par le système.

Question : Comment puis-je configurer une liaison standard avec différentes valeurs pour chacun des attributs ?

Pour plus d'informations, consultez Configuration de liaisons pour les services Windows Communication Foundation.

Question : Est-ce que je dois déployer mon service sur un serveur HTTP si je souhaite utiliser HTTP comme transport ?

Non. Les liaisons fournies par le système en incluent plusieurs qui prennent en charge les transports HTTP lorsqu'elles sont utilisées à partir de tout type d'application hôte. Pour plus d'informations sur les liaisons fournies par le système et les fonctionnalités qu'elles prennent en charge, consultez Liaisons fournies par le système.

Question : Quel est le comportement par défaut d'un service qui utilise des liaisons standard ?

Le comportement dépend de la liaison standard choisie. En général, le comportement par défaut pour les liaisons qui utilisent des sessions est pour créer une instance de service pour chaque nouveau client, et les appels suivants d'un client particulier sont routés à l'instance de service associée. Pour plus d'informations sur liaisons fournies par le système et les fonctionnalités qu'ils prennent en charge, consultez Liaisons fournies par le système.

Question : Existe-t-il un moyen simple de connaître les correspondances entre les fonctionnalités et les liaisons ? Par exemple, comment puis-je déterminer quelles liaisons prennent en charge des transactions, la sécurité, etc. ?

Oui. Consultez Liaisons fournies par le système.

Question : Comment puis-je transmettre des types de données personnalisés d'un service à un client ?

Les types de données passés entre deux points de terminaison doivent être sérialisables et le mécanisme de sérialisation le plus simple et le plus interopérable pour les services consiste à utiliser les classes DataContractAttribute et DataMemberAttribute. Pour plus d'informations sur ce mécanisme et d'autres mécanismes de sérialisation pris en charge, consultez Spécification du transfert de données dans des contrats de service.

Question : Quand dois-je effectuer une configuration à l'aide d'un fichier de configuration et quand dois-je l'effectuer dans le code ?

Étant donné que le fichier de configuration d'une application permet au développeur de placer des décisions sur la configuration à l'exécution dans les mains du responsable de déploiement, les décisions que les responsables de déploiement ne doivent jamais prendre sont de bons arguments en faveur d'une configuration dans le code du produit. Les responsables de déploiement peuvent être les personnes qui installent des programmes sur leurs propres ordinateurs ou des administrateurs d'entreprise qui utilisent des stratégies de groupe d'entreprise pour modifier les fichiers de configuration des ordinateurs et qui les verrouillent afin d'empêcher toute modification locale. Pour obtenir un exemple d'un tel verrouillage, consultez Comment : verrouiller des points de terminaison dans l'entreprise.

Question : Qu'est-ce que je dois savoir sur la conception d'un service valide ?

Consultez Conception et implémentation de services.

Question : Que signifie tout le code client généré ?

Pour vous y retrouver dans le code client généré, consultez Fonctionnement du code client généré. Pour plus d'informations sur l'architecture cliente, consultez Architecture du client.

Question : Pourquoi dois-je appeler la méthode Close sur l'objet client WCF ?

L'appel de Close sur l'objet client WCF permet au client et au service de conclure correctement la conversation et de recycler les ressources qui y sont associées. En outre, si vous utilisez des sessions, l'appel de Close peut être la manière la plus rapide de déterminer si la session a provoqué une erreur depuis le dernier appel, ce qui constitue un scénario potentiellement éloquent pour votre application cliente. Pour plus d'informations, consultez Accès aux services à l'aide d'un client WCF et l'exemple Expected Exceptions

Question : Pourquoi mon service ne s'exécute-t-il pas comme prévu même lorsque le code semble correct ?

Si votre application de service est configurée à l'aide d'un fichier de configuration de l'application, vous devez examiner ce fichier afin de déterminer si un élément ou attribut de configuration altère le comportement d'exécution de manière inattendue. Plus particulièrement, le comportement à l'exécution dépend souvent de la liaison qui implémente le contrat dans un point de terminaison. Vérifiez que la liaison dans le fichier de configuration prend en charge les fonctionnalités que vous souhaitiez, et ce de la manière attendue.

Si le fichier de configuration semble correct, vous pouvez continuer à examiner le comportement à l'exécution de votre application en utilisant les fonctionnalités de diagnostic telles que la journalisation et le suivi. Pour plus d'informations, consultez Administration et diagnostics.

Question : Quel est le meilleur moyen de dire à un client qu'un problème s'est produit sur le service ?

Le meilleur moyen consiste à ajouter une classe FaultContractAttribute avec un type de données d'erreur sérialisable et personnalisé à votre opération. Ainsi, lorsque votre opération rencontre une condition d'erreur qu'elle peut détecter, elle lève une nouvelle FaultException où le paramètre de type correspond au type d'erreur sérialisable. Pour plus d'informations, consultez Spécification et gestion des erreurs dans les contrats et les services.

Question : Quelles sont les informations que je peux repasser au client ?

Renvoyez uniquement les informations que les clients de votre service ont besoin de connaître. En tant que concepteur du service, vous devez fournir uniquement cette quantité d'informations et pas une de plus afin de minimiser l'exposition d'informations d'implémentation interne à des clients non autorisés. C'est pourquoi il est fortement recommandé de ne pas renvoyer des objets Exception dans vos erreurs SOAP. Pour plus d'informations, consultez Spécification et gestion des erreurs dans les contrats et les services.

Question : Comment mon application cliente détecte-t-elle la fermeture d'une connexion à un service ?

Vous pouvez gérer les événements de modification d'état CommunicationObject du canal client. Toutefois, le moment auquel vous êtes notifié de la fermeture ou de l'erreur d'un canal dépend de l'implémentation du canal. Par exemple, une classe NetTcpBinding vous avertit assez rapidement que le canal est fermé ou qu'il provoque une erreur parce que la durée de vie de sa session est associée à la durée de vie du socket sous-jacent.

Toutefois, une liaison avec session conçue pour protéger l'application contre de petites perturbations du réseau, comme la session fournie par la classe ReliableSessionBindingElement, ne peut pas vous avertir pendant un instant lorsqu'elle tente de rétablir la session. Parce que c'est le cas, il est recommandé de ne pas essayer de détecter la déconnexion directement.

Traitez plutôt la session comme une conversation. Si vous ouvrez le canal, faites plusieurs appels d'opération et fermez le canal avec succès, puis vous pouvez supposer que le canal n'a pas fermé de façon inattendue. Pour plus d'informations sur les clients et les sessions, consultez Utilisation de sessions. Pour plus d'informations sur la gestion des exceptions liées aux canaux sur le client, consultez Accès aux services à l'aide d'un client. Pour plus d'informations sur la gestion des exceptions en général, consultez Spécification et gestion des erreurs dans les contrats et les services.

Question : Comment configurer un certificat SSL (Secure Sockets Layer) pour la sécurité de service WCF ?

Consultez Comment : configurer un port avec un certificat SSL.

Question : Comment utiliser des inspecteurs de message pour journaliser ou modifier le message ?

Consultez les rubriques suivantes :

Question : Comment puis-je ajouter une adresse de point de terminaison contenant des informations supplémentaires ?

Lorsque vous souhaitez joindre des adresses de point de terminaison complexes par programme (par exemple, si vous devez spécifier par programme une classe EndpointAddress qui contient un en-tête ou une identité spécifique), vous devez effectuer les opérations suivantes, où relativeOrAbsoluteAddress correspond à un URI (Uniform Resource Identifier) relatif ou absolu :

// Do this:
ServiceEndpoint e = myServiceHost.AddServiceEndpoint(c,b,"relativeOrAbsoluteAddress");
e.Address = new EndpointAddress(e.Address.Uri, /*other info like headers */);

Question : je cherche à générer un exemple hébergé sur le Web et la génération échoue en raison de l'échec d'une commande supprimer, copier ou créer répertoire. Pourquoi ?

Au cours de la génération, certains exemples hébergés sur le Web tentent de copier les fichiers binaires compilés de service WCF dans le dossier %SystemDrive%\inetpub\wwwroot\ServiceModelSamples. Cette procédure permet de déployer le service dans IIS. Si le compte sous lequel l'invite de commandes du Kit de développement SDK ou Visual Studio s'exécute n'a pas l'autorisation de modifier le dossier, la génération échoue. Pour remédier à ce problème, vous pouvez effectuer l'une des opérations suivantes

  • Accordez des droits de modification pour %SystemDrive%\inetpub\wwwroot au compte sous lequel vous générez l'exemple.
    ou
  • Exécutez l'invite de commandes du Kit de développement SDK ou Visual Studio en tant qu'administrateur.

Voir aussi

Concepts

Débogage d'erreurs d'authentification Windows