Saltar al contenido

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

Te recomendamos que revises esta solución en un entorno controlado antes de enviarlo a producción, un saludo.

Solución:

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

Ahora, dado que el lado del servidor “fue bombardeado”, el tiempo de ejecución de WCF ha “fallado” en el canal, por ejemplo, el enlace de comunicación entre el cliente y el servidor no se puede usar, después de todo, parece que su servidor simplemente explotó, por lo que no puede comunicarse con más.

Así que lo que tienes que hacer es:

  • siempre capturar y manejar sus errores del lado del servidor – no dejar que las excepciones de .NET viajen desde el servidor al cliente – siempre envuélvalos 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 un estado defectuoso:

    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 y luego intentarlo de nuevo.

Para evitar que el servidor caiga en estado de error, 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: la seguridad es lo primero.
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")  
    

    tal vez pueda 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 attribute [SvcErrorHandlerBehaviour] sobre la implementación del servicio deseado

    using System;
    using System.Collections.ObjectModel;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Description;
    using System.ServiceModel.Dispatcher;
    
    namespace MainService.Services
    
        /// 
        /// Provides FaultExceptions for all Methods Calls of a Service that fails with an Exception
        /// 
        public class SvcErrorHandlerBehaviourAttribute : Attribute, IServiceBehavior
        
            public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
              //implementation not needed
    
            public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection 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 fácil, puede profundizar en IErrorhandler al no usar el desnudo FaultExceptionpero un FaultException<> con un tipo que proporciona información adicional, consulte IErrorHandler para obtener un ejemplo detallado.

De hecho, si no tiene éxito después de seguir las sugerencias de marc_stenga en cuenta que un elemento en la configuración de enlace del servidor (o la falta de ella) en web.config en el servidor puede causar esta excepción. Por ejemplo, el servidor está esperando Messagenivel de seguridad 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 es).

Sugerencia: En tales casos, lo más probable es que la aplicación del cliente invoque el servicio web correctamente cuando se ejecute directamente en la máquina del servidor bajo la cuenta administrativa en la sesión RDP.

Agradecemos que quieras añadir valor a nuestra información colaborando tu veteranía en las críticas.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : / /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *