194 votes

L'objet de communication, System.ServiceModel.Channels.ServiceChannel, ne peut pas être utilisé pour la communication.

L'objet de communication, System.ServiceModel.Channels.ServiceChannel, ne peut pas être utilisé pour la communication car il est dans l'état Faulted.

À quoi correspond cette erreur et comment puis-je la résoudre ?

170voto

marc_s Points 321990

Vous obtenez cette erreur parce que vous avez laissé une exception .NET se produire du côté du serveur, et que vous ne l'avez pas attrapée et traitée, et que vous ne l'avez pas non plus convertie en erreur SOAP.

Maintenant, puisque le côté serveur a "explosé", le runtime WCF a "failli" le canal - par exemple, le lien de communication entre le client et le serveur est inutilisable - après tout, il semble que votre serveur a juste explosé, donc vous ne pouvez plus communiquer avec lui.

Donc ce que tu dois faire c'est :

  • toujours attrape et gère les erreurs côté serveur - ne pas laisser les exceptions .NET voyager du serveur au client - toujours les emballer dans des fautes SOAP interopérables. Vérifiez le WCF IErrorHandler et l'implémenter du côté serveur

  • si vous êtes sur le point d'envoyer un second message sur votre canal depuis le client, assurez-vous que le canal n'est pas en état de défaut :

    if(client.InnerChannel.State != System.ServiceModel.CommunicationState.Faulted)
    {
       // call service - everything's fine
    }
    else
    {
       // channel faulted - re-create your client and then try again
    }

    Si c'est le cas, tout ce que vous pouvez faire est de le détruire et de recréer le proxy côté client, puis de réessayer.

13 votes

Il semble que la même erreur puisse se produire lorsque le problème se situe également du côté du client : par exemple, lorsque le quota de taille des messages entrants a été dépassé.

9 votes

Comment puis-je recréer le client ?

0 votes

Recycler le pool d'applications a fonctionné pour moi - l'exception n'a probablement pas été levée lors du prochain appel du service Web.

37voto

BerndK Points 131

Pour éviter que le serveur ne tombe en état d'erreur, vous devez vous assurer qu'aucune exception non gérée n'est levée. Si WCF voit une exception inattendue, pas plus d'appels sont acceptés - la sécurité d'abord.
Deux possibilités pour éviter ce comportement :

  1. Utilisez un FaultException (celui-ci n'est pas inattendu pour WCF, ainsi le WCF sait que le serveur a toujours un état valide)
    au lieu de

    throw new Exception("Error xy in my function")  

    utiliser toujours

    throw new FaultException("Error xy in my function")  

    Vous pouvez peut-être essayer d'attraper tout le bloc et de lancer une FaultException dans tous les cas d'exception.

    try   
    {  
        ... some code here   
    }
    catch (Exception ex)
    {  
        throw new FaultException(ex.Message)   
    }
  2. Dites à WCF de traiter toutes les Exceptions en utilisant un Errorhandler. Ceci peut être fait de plusieurs manières, j'ai choisi une simple en utilisant un Attribut :
    Tout ce que nous avons à faire de plus, c'est d'utiliser l'attribut [SvcErrorHandlerBehaviour] sur la mise en œuvre du service recherché

    using System;
    using System.Collections.ObjectModel;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Description;
    using System.ServiceModel.Dispatcher;
    
    namespace MainService.Services
    {
        /// <summary>
        /// Provides FaultExceptions for all Methods Calls of a Service that fails with an Exception
        /// </summary>
        public class SvcErrorHandlerBehaviourAttribute : Attribute, IServiceBehavior
        {
            public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
            { } //implementation not needed
    
            public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints,
                                             BindingParameterCollection bindingParameters)
            { } //implementation not needed
    
            public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
            {
                foreach (ChannelDispatcherBase chanDispBase in serviceHostBase.ChannelDispatchers)
                {
                    ChannelDispatcher channelDispatcher = chanDispBase as ChannelDispatcher;
                    if (channelDispatcher == null)
                        continue;
                    channelDispatcher.ErrorHandlers.Add(new SvcErrorHandler());
                }
            }
        }
    
        public class SvcErrorHandler: IErrorHandler
        {
            public bool HandleError(Exception error)
            {
                //You can log th message if you want.
                return true;
            }
    
            public void ProvideFault(Exception error, MessageVersion version, ref Message msg)
            {
                if (error is FaultException)
                    return;
    
                FaultException faultException = new FaultException(error.Message);
                MessageFault messageFault = faultException.CreateMessageFault();
                msg = Message.CreateMessage(version, messageFault, faultException.Action);
            }
        }
    }

Il s'agit d'un exemple simple, vous pouvez plonger plus profondément dans IErrorhandler en n'utilisant pas le naked FaultException mais un FaultException<> avec un type qui fournit des informations supplémentaires voir IErrorHandler pour un exemple détaillé.

12voto

timmi4sa Points 121

En fait, si vous ne réussissez pas à suivre les suggestions de marc_s Si vous avez un problème de sécurité, n'oubliez pas qu'un élément <security> dans la configuration de la liaison du serveur (ou l'absence de celle-ci) dans le fichier web.config sur le serveur peut provoquer cette exception. Par exemple, le serveur attend Message -et le client est configuré pour None (ou, si le serveur ne fait pas partie d'un domaine Active Directory mais que l'hôte client distant en fait partie).

Conseil : Dans ce cas, l'application cliente invoquera très probablement le service web correctement lorsqu'elle sera exécutée directement sur la machine serveur sous un compte administratif dans une session RDP.

7voto

Florian Gerhardt Points 2966

Attacher à le site faulted événement pour comprendre pourquoi et quand l'erreur s'est produite.

Edit : Il serait également utile que vous postiez quelques informations supplémentaires sur ce que vous faites.

2voto

yantaq Points 142

J'ai un client web qui se connecte à un service Windows via WCF. Mon application Web génère la même erreur

L'objet de communication, System.ServiceModel.Channels.ServiceChannel, ne peut pas être utilisé pour la communication car il est dans l'état Faulted. J'ai activé le traçage WCF, ce qui n'a pas été d'une grande aide. Finalement, le redémarrage du service Windows l'a résolu et je n'ai toujours toujours aucune idée de la cause. Le dépannage doit donc, comme toujours, commencer par le plus simple. Ceci est un cas d'espèce. Si quelqu'un a un problème similaire, essayez de redémarrer le service. le service.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X