El objeto de comunicación, System.ServiceModel.Channels.ServiceChannel, no se puede usar para la comunicación

156

El objeto de comunicación, System.ServiceModel.Channels.ServiceChannel, no se puede usar para la comunicación porque está en estado Faulted.

¿De qué se trata este error y cómo haría para resolverlo?

Innova
fuente

Respuestas:

151

Obtiene este error porque dejó que ocurriera una excepción .NET en el lado del servidor, y no la detectó y manejó, y tampoco la convirtió en una falla SOAP.

Ahora, dado que el lado del servidor "bombardeó", el tiempo de ejecución de WCF ha "fallado" el canal, por ejemplo, el enlace de comunicación entre el cliente y el servidor no se puede utilizar, después de todo, parece que su servidor explotó, por lo que no puede comunicarse con Ya no más.

Entonces, lo que debe hacer es:

  • siempre detecte y maneje sus errores del lado del servidor , no permita que las excepciones .NET viajen del servidor al cliente, siempre envuélvalas en fallas SOAP interoperables. Consulte la interfaz WCF IErrorHandler e impleméntela en el lado del servidor

  • si está a punto de enviar un segundo mensaje a su canal desde el cliente, asegúrese de que el canal no esté en estado de error:

    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 es así, todo lo que puede hacer es deshacerse de él y volver a crear el proxy del lado del cliente nuevamente y luego intentarlo nuevamente

marc_s
fuente
11
Parece que el mismo error puede ocurrir cuando el problema también está en el lado del cliente: por ejemplo, cuando se ha excedido la cuota de tamaño de mensaje para los mensajes entrantes.
svick
66
¿Cómo puedo volver a crear el cliente?
Masoud
32

Para evitar que el servidor caiga en estado de falla, debe asegurarse de que no se genere ninguna excepción no controlada. Si WCF ve una excepción inesperada, no se aceptan más llamadas, primero la seguridad.
Dos posibilidades para evitar este comportamiento:

  1. Use una FaultException (esta no es inesperada para WCF, por lo que WCF sabe que el servidor aún tiene un estado válido) en
    lugar de

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

    usar siempre

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

    quizás puedas intentar ... capturar todo el bloque y lanzar una FaultException en todos los casos de una Excepción

    try   
    {  
        ... some code here   
    }
    catch (Exception ex)
    {  
        throw new FaultException(ex.Message)   
    }
  2. Dígale a WCF que maneje todas las excepciones usando un controlador de errores. Esto se puede hacer de varias maneras, elegí una simple usando un atributo:
    todo lo que tenemos que hacer más es usar el atributo [SvcErrorHandlerBehaviour]en la implementación de servicio deseada

    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);
            }
        }
    }

Este es un ejemplo sencillo, puede sumergirse más profundamente en IErrorhandler al no usar el desnudo FaultException , pero FaultException<>con un tipo que proporciona información adicional, consulte IErrorHandler para obtener un ejemplo detallado.

BerndK
fuente
10

De hecho, si no tiene éxito después de seguir las sugerencias de marc_s , tenga en cuenta que un elemento <security> en la configuración de enlace del servidor (o la falta de este) en web.config en el servidor puede causar esta excepción. Por ejemplo, el servidor espera Messageseguridad de nivel y el cliente está configurado para None(o, si el servidor no es parte de un dominio de Active Directory pero el host del cliente remoto sí lo está).

Consejo: en tales casos, la aplicación cliente probablemente invocará el servicio web cuando se ejecute directamente en la máquina del servidor con una cuenta administrativa en la sesión RDP.

timmi4sa
fuente
2

Para diagnosticar este problema, ejecute el servicio en el depurador de Visual Studio. Use el menú: Depurar | Excepciones e indique que desea interrumpir cuando se produce una Excepción.

La excepción original lanzada tendrá un mensaje de error mucho mejor que "..está en estado Faulted".

Por ejemplo, recibí esta excepción de ServiceHost.Open (), pero cuando capté la excepción original en el momento en que se lanzó, el mensaje de error fue:

El servicio 'MyServiceName' tiene cero puntos finales de aplicación (no infraestructura). Esto puede deberse a que no se encontró ningún archivo de configuración para su aplicación, o porque no se pudo encontrar ningún elemento de servicio que coincida con el nombre del servicio en el archivo de configuración, o porque no se definieron puntos finales en el elemento de servicio.

La solución del error de ortografía en App.config resolvió el problema.

Dale Wilson
fuente
En VS2015, elija Depurar → Configuración de excepciones y marque Excepciones de Common Language Runtime.
SharpC
1
Entonces, ¿por qué no se dio la excepción original hasta que utilizó el depurador de Visual Studio?
Jez
2

Tuve el mismo problema al intentar consumir el punto final del servicio net.tcp wcf en un servicio http asmx.

Como vi, nadie escribió una respuesta específica POR QUÉ está ocurriendo este problema, sino solo cómo manejarlo adecuadamente.

He estado luchando con esto varios días seguidos y finalmente descubrí de dónde viene el problema en mi caso.

Inicialmente, pensé que cuando se hace referencia a un servicio, el archivo de configuración se configurará con respecto a la etiqueta de seguridad de la misma manera que en la fuente, pero ese no era el caso y debería ocuparme de él manualmente. En mi caso solo tenía

<netTcpBinding>
    <binding name="NetTcpBinding_IAuthenticationLoggerService"
    </binding>
</netTcpBinding>`

Más tarde vi que falta la parte de seguridad y debería verse así

<netTcpBinding>
    <binding name="NetTcpBinding_IAuthenticationLoggerService" transferMode="Buffered">
      <security mode="None">
        <transport clientCredentialType="None"/>
      </security>
    </binding>
  </netTcpBinding>

El segundo problema en mi caso fue que estaba usando transferMode="Streamed"mi servicio WCF de origen y en el cliente no tenía nada específico al respecto, lo cual era malo, porque el valor predeterminado transferModees Bufferedy es importante en ambos lugares que el origen y el cliente estén configurados en el mismo camino.

ppenchev
fuente
1

Tuve otro problema, que no creo que se haya mencionado en las otras respuestas.

Tengo que dar servicio a los puntos finales en la misma dirección y puerto TCP. En app.config, me había olvidado de agregar ambos puntos finales, por lo que el servicio se estaba ejecutando en el puerto correcto, pero con la interfaz de servicio incorrecta.

Karsten
fuente
1

Si ve este mensaje en Debug from Visual Studio y la solución contiene el proyecto WCF. Luego abra esta configuración del proyecto WCF -> vaya a la pestaña "Opciones WCF" -> fuera de la opción "Iniciar host de servicio WCF al depurar ..."

Ivan Horev
fuente
Tuve el mismo problema y me quedé atrapado en este problema durante bastante tiempo. Probablemente no sea una buena práctica tener tanto el cliente como el servidor en la misma solución. ¡Gracias!
yoosha
1

Para mí, el problema fue causado por el archivo de configuración generado automáticamente al importar el WSDL. Actualicé el enlace de basicHttpBinding a customBinding. Agregar manejo adicional de excepciones no ayudó a señalar esto.

antes de

<basicHttpBinding>
            <binding name="ServiceName">
                <security mode="Transport" />
            </binding>
        </basicHttpBinding>`

Después

<customBinding>
        <binding name="ServiceName">
          <textMessageEncoding messageVersion="Soap12" />
          <httpsTransport />
        </binding>
      </customBinding>`
BGotIt
fuente
0

En mi caso, el motivo fue un certificado incorrecto que no se pudo cargar. Lo descubrí desde el Visor de eventos, en Sistema:

Se produjo un error grave al intentar acceder a la clave privada de credencial del servidor TLS. El código de error devuelto por el módulo criptográfico es 0x8009030D. El estado de error interno es 10001.

altumano
fuente
0

Este error también puede ser activado por su propia computadora, y no solo por una excepción no controlada. Si su servidor / computadora tiene su reloj apagado por demasiados minutos, muchos servicios web .NET rechazarán su solicitud con un error no manejado. Se maneja desde su punto de vista, pero no se maneja desde su punto de vista. Verifique para asegurarse de que la hora del reloj del servidor receptor sea correcta. Si necesita ser reparado, tendrá que restablecer su servicio o reiniciar antes de que el canal se vuelva a abrir.

Experimenté este problema en un servidor donde el cortafuegos bloqueó la actualización de la hora de Internet, y el servidor se desconectó por alguna razón. Todos los servicios web .NET de terceros entraron en falta porque rechazaron cualquier solicitud de servicio web. Excavar en el Visor de eventos ayudó a identificar el problema, pero ajustar el reloj lo resolvió. El error fue de nuestra parte, a pesar de que recibimos el mensaje de error Estado fallido para futuras llamadas al servicio web.

HBlackorby
fuente
0

El servidor cancelará automáticamente las conexiones en las que no se haya recibido ningún mensaje durante el tiempo igual al tiempo de espera de recepción (el valor predeterminado es 10 minutos ). Esta es una mitigación de DoS para evitar que los clientes obliguen al servidor a tener conexiones abiertas por un período de tiempo indefinido.

Como el servidor cancela la conexión porque se ha quedado inactivo, el cliente obtiene esta excepción.

Puede controlar cuánto tiempo el servidor permite que una conexión permanezca inactiva antes de cancelarla configurando el tiempo de espera de recepción en el enlace del servidor. Crédito: TRVishwanath - MSFT

Vijay Rana
fuente
0

Sé que esta es una publicación anterior, pero una cosa a tener en cuenta cuando no puede cambiar la seguridad es asegurarse de que su nombre de usuario y contraseña estén configurados.

Tenía un servicio con modo de autenticación como UserNameOverTransport, cuando el nombre de usuario y la contraseña no estaban configurados para el cliente del servicio, obtenía este error.

Joshua G
fuente
0

Para mí fue un problema de equilibrador de carga / url. Un servicio web detrás de un equilibrador de carga llamó a otro servicio detrás de la misma equilibrador de carga utilizando la URL completa, como: loadbalancer.mycompany.com. Lo cambié para omitir el equilibrador de carga al llamar al segundo servicio usando en su localhost.mycompany.comlugar.

Creo que hubo algún tipo de problema de referencia circular con el equilibrador de carga.

goku_da_master
fuente
-2

No es una solución a este problema, pero si experimenta el error anterior con Ektron eSync, podría ser que su base de datos se haya quedado sin espacio en disco.

Editar: de hecho, este no es un problema exclusivo de Ektron eSync. Esto podría suceder en cualquier servicio que consulte una base de datos completa.

Editar: sin espacio en disco o bloquear el acceso a un directorio que necesita causará este problema.

Jonathan Bick
fuente
Esto no proporciona una respuesta a la pregunta. Para criticar o solicitar una aclaración de un autor, deje un comentario debajo de su publicación: siempre puede comentar sus propias publicaciones, y una vez que tenga suficiente reputación podrá comentar cualquier publicación .
Dariusz
2
Respondí a su pregunta "¿cómo haría para resolverlo?", No es mi culpa que nunca nos haya dado detalles sobre si estaba usando Ektron o no. También necesito 50 representantes para comentar su publicación.
Jonathan Bick