L'objet de communication, Système.ServiceModel.Canal.ServiceChannel, ne peut pas être utilisé pour la communication
L'objet de communication, le système.ServiceModel.Canal.ServiceChannel, ne peut pas être utilisé pour la communication car il est dans L'état défectueux.
Quelle est cette erreur, et comment vais-je la résoudre?
12 réponses
Vous obtenez cette erreur parce que vous avez laissé une exception. net se produire sur votre serveur, et vous ne l'avez pas attrapée et gérée, et ne l'avez pas convertie en une erreur SOAP non plus.
Maintenant que le côté serveur a "bombardé", le runtime WCF a" défectueux " 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 explosé, donc vous ne pouvez plus communiquer avec lui.
Donc, ce que vous devez faire est:
-
Toujours attraper et gérer vos erreurs Côté Serveur - ne pas laisser les exceptions. net voyager du serveur au client - toujours les envelopper dans des défauts soap interopérables. Consultez L'interface WCF IErrorHandler et implémentez-la Côté Serveur
-
Si vous êtes sur le point d'envoyer un second message sur votre canal à partir du client, assurez-vous que le canal n'est pas dans l'état défectueux:
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 elle l'est, tous les vous pouvez en disposer et recréer à nouveau le proxy côté client, puis réessayer
Pour empêcher le serveur de tomber dans L'État de défaut, vous devez vous assurer qu'aucune exception non gérée n'est déclenchée. Si WCF voit une Exception inattendue, plus d'appels sont acceptés-la sécurité d'abord.
Deux possibilités pour éviter ce comportement:
-
Utilisez une exception FaultException (celle-ci n'est pas inattendue pour WCF, donc la WCF sait que le serveur a toujours un état valide)
au lieu dethrow new Exception("Error xy in my function")
Utilisez toujours
throw new FaultException("Error xy in my function")
Peut-être que vous pouvez essayer..attrapez le bloc entier et lancer une exception FaultException dans tous les cas d'Exception
try { ... some code here } catch (Exception ex) { throw new FaultException(ex.Message) }
-
Dites à WCF de gérer toutes les Exceptions en utilisant un Errorhandler. Cela peut être fait de plusieurs façons, j'ai choisi un simple en utilisant un attribut:
Tout ce que nous avons à faire de plus, c'est d'utiliser l'attribut[SvcErrorHandlerBehaviour]
sur l'implémentation du Service vouluusing 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); } } }
Ceci est un exemple facile, vous pouvez plonger plus profondément dans IErrorhandler en n'utilisant pas le FaultException
nu, mais un FaultException<>
avec un type qui fournit des informations supplémentaires
voir IErrorHandler pour un exemple détaillé.
En fait, en cas d'échec après avoir suivi les suggestions de marc_s , Veuillez garder à l'esprit qu'un élément Message
et le client est configuré sur None
(ou, si le serveur ne fait pas partie d'un domaine Active Directory mais que l'hôte client distant l'est).
Astuce: dans de tels cas, l'application cliente sera très probablement appelez le service web fine lorsqu'il est exécuté directement sur la machine serveur sous compte d'administration dans la session RDP.
Joindre à le faulted
événement pour comprendre pourquoi et quand l'erreur s'est produite.
Edit: il serait également utile que vous publiiez plus d'informations sur ce que vous faites.
Pour diagnostiquer ce problème, exécutez le service sous le débogueur Visual Studio. Utilisez le menu: Debug / Exceptions et indiquez que vous voulez casser quand une Exception est levée.
L'exception d'origine levée aura un message d'erreur bien meilleur que "..il est dans l'état défectueux."
Par exemple, j'obtenais cette exception de ServiceHost.Open (), mais quand j'ai attrapé l'exception d'origine au moment où elle a été levée, le message d'erreur était:
Service 'MyServiceName' n'a aucune application (non-infrastructure) terminaison. Cela peut être dû au fait qu'aucun fichier de configuration n'a été trouvé pour votre application, ou parce qu'aucun élément de service nom du service peut être trouvé dans le fichier de configuration, ou parce les points de terminaison ont été définis dans l'élément service.
Correction de l'erreur d'orthographe dans L'application.config a résolu le problème.
J'ai un client web qui se connecte au service windows via WCF. mon application web lance la même erreur
L'objet de communication, Système.ServiceModel.Canal.ServiceChannel, ne peut pas être utilisé pour la communication car il est dans L'état défectueux J'ai activé le traçage WCF, ce qui n'était pas d'une grande aide. enfin le redémarrage du service windows l'a résolu et j'ai toujours aucune idée de la cause. donc, le dépannage devrait comme toujours commencer par simple. c'est un cas au point. si quelqu'un a un problème similaire, essayez de redémarrer service.
J'ai eu un autre problème, que je ne pense pas avoir été mentionné dans les autres réponses.
Je dois entretenir des points de terminaison sur la même adresse tcp et le même port. Dans l'application.config, j'avais oublié d'ajouter les deux points de terminaison, donc le service fonctionnait sur le port correct, mais avec la mauvaise interface de service.
Si vous voyez ce message dans Debug de Visual Studio et la solution contient le projet WCF. Ensuite, ouvrez ce projet WCF paramètres - > aller à" Options WCF "onglet - > off" Démarrer WCF Service Host lors du débogage..."option
Dans mon cas, la raison était un mauvais certificat qui n'a pas pu être chargé. J'ai découvert à ce sujet à partir de L'Observateur D'événements, sous System:
Une erreur fatale s'est produite lors de la tentative d'accès au serveur TLS clé privée d'identification. Le code d'erreur renvoyé par le chiffrement module est 0x8009030D. l'état d'erreur interne est 10001.
Cette erreur peut être déclenchée par votre propre ordinateur, et pas seulement une exception non gérée. Si votre serveur / ordinateur a son temps d'horloge de trop de minutes, de nombreux services web. net rejetteront votre demande avec une erreur non gérée. C'est géré de leur point de vue, mais non géré de votre point de vue. Vérifiez que l'heure d'horloge de votre serveur de réception est correcte. S'il doit être corrigé, vous devrez réinitialiser votre service ou redémarrer avant la réouverture du canal.
J'ai vécu ce problème sur un serveur où le pare-feu a bloqué la mise à jour de L'Heure Internet, et le serveur a quitté le temps pour une raison quelconque. Tous les services web. net tiers sont tombés en faute car ils ont rejeté toute demande de service web. Creuser dans L'Observateur D'événements a aidé à identifier le problème, mais ajuster l'horloge l'a résolu. L'erreur était de notre côté, même si nous avons reçu le message D'erreur D'état défectueux pour les futurs appels de service web.
Le serveur annule automatiquement les connexions sur lesquelles aucun message n'a été reçu pendant une durée égale au délai d'attente de réception (la valeur par défaut est de 10 minutes). Il s'agit D'une atténuation DoS pour empêcher les clients de forcer le serveur à ouvrir des connexions pendant une durée indéterminée.
Puisque le serveur interrompt la connexion car elle est restée inactive, le client obtient cette exception.
Vous pouvez contrôler combien de temps le serveur permet à une connexion de rester inactive avant l'abandonner en configurant le délai de réception sur la liaison du serveur. Crédit: T. R. Vishwanath-MSFT
Pas une solution à ce problème, mais si vous rencontrez L'erreur ci-dessus avec Ektron eSync, il se peut que votre base de données soit à court d'espace disque.
Edit: en fait, ce n'est pas entièrement un problème Ektron esync seulement. Cela pourrait se produire sur n'importe quel service qui interroge une base de données complète.
Edit: un manque d'espace disque ou le blocage de l'accès à un répertoire dont vous avez besoin provoquera ce problème.