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:
-
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 dethrow 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)
-
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 deseadousing 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, Collectionendpoints, 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 FaultException
pero 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 Message
nivel 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.