Propiedad IncludeExceptionDetailInFaults en WCF

La propiedad IncludeExceptionDetailInFaults es utilizada para habilitar a los servicios de WCF el envio de informacion detallada cuando una excepcion ocurre en objetos SOAP fault hacia el cliente.  El propósito de esta acción, es brindarle al cliente más información en pruebas de la aplicación. 

Por defecto, el valor de esta propiedad es false por motivos de seguridad.  Sin embargo existen varias formas de cambiar este valor las cuales se ejemplarizan a continuación:  

Utilizando .config

Esta es la forma más utilizada por su comodidad ya que basta con editar el archivo de configuración del servicio WCF y especificar al atributo includeExceptionDetailInFaults el valor true

Al hacer esta operación, todos los endpoints relacionados al servicio enviarán información detallada de errores en cualquier momento.

 <system.serviceModel>
  <services>
    <service name="BizTalkLATAM.WCF.DebugService"
             behaviorConfiguration="DebugServiceConfiguration">
    </service>
  </services>
  <behaviors>
    <serviceBehaviors>
      <behavior name="DebugServiceConfiguration">
        <serviceDebug includeExceptionDetailInFaults="true"/>
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>

Utilizando código

También es posible habilitar esta propiedad utilizando código, para esto existen dos formas.  La primera es especificando la propiedad IncludeExceptionDetailInFaults con el valor de true en el atributo ServiceBehaviorAttribute aplicado a la clase que representa el servicio. 

 [ServiceContract(Namespace="https://wcf.biztalklatam.com/debug/")]
[ServiceBehavior(IncludeExceptionDetailInFaults=true)]
public class DebugService
{ }

La segunda forma es estableciendo el valor de la propiedad IncludeExceptionDetailInFaults en true antes de invocar el metodo Open() del servicio, esto sin necesidad de especificar el atributo ServiceBehaviorAttribute a la clase que representa el servicio. 

 [ServiceContract(Namespace="https://wcf.biztalklatam.com/debug/")] 
public class DebugService 
{ } 
 using (ServiceHost host = new ServiceHost(typeof(DebugService)))
{
    ServiceDescription svcDesc = host.Description.Behaviors;
    ServiceDebugBehavior svcDebug = svcDesc.Behaviors.Find<ServiceDebugBehavior>();
    svcDebug.IncludeExceptionDetailInFaults = true;
    host.Open();
}

Habilitando parcialmente la propiedad

Las técnicas anteriormente vistas habilitan la propiedad  IncludeExceptionDetailInFaults para todos los endpoints de un servicio, pero cómo hacer si solo un endpoint se desea habilitar para ello?

En el siguiente ejemplo se utilizan dos endpoints: debug1 y debug2, de acuerdo al atributo bindingName.  Y se requiere que el endpoint debug1 envie información detallada en el momento de una excepción pero debug2 no.

<system.serviceModel>
  <services>
    <service name="BizTalkLATAM.WCF.DebugService"
             behaviorConfiguration="DebugServiceConfiguration">
      <endpoint address="net.tcp://localhost:8009/wcf/debugep1"
                binding="netTcpBinding"
                bindingName="debug1"
                bindingNamespace="https://wcf.biztalklatam.com/binding/"
                contract="BizTalkLATAM.WCF.DebugService" />
      <endpoint address="net.tcp://localhost:8009/wcf/debugep2"
                binding="netTcpBinding"
                bindingName="debug2"
                bindingNamespace="https://wcf.biztalklatam.com/binding/"
                contract="BizTalkLATAM.WCF.DebugService" />
    </service>
    <behaviors>
    <serviceBehaviors>
     <behavior name="DebugServiceConfiguration">
      <serviceDebug includeExceptionDetailInFaults="false"/>
     </behavior>
    </serviceBehaviors>
  </behaviors>
  </services>
</system.serviceModel>

Luego de definir el archivo de configuración, se debe cambiar el valor de la propiedad IncludeExceptionDetailInFaults a true al endpoint debug1.  Para esto es necesario buscar en la colección ChannelDispatchers del servicio WCF el ChannelDispatcher que representa el endpoint debug1, esto se logra fácilmente usando la propiedad ChannelDispatcher.BindingName.  Una vez localizado el endpoint, se cambia la propiedad IncludeExceptionDetailInFaults a true.

Ya que modificar la propiedad IncludeExceptionDetailInFaults en un objeto tipo ChannelDispatcher solo se puede hacer cuando el objeto se encuenta en un estado Created, es necesario implementar una nueva clase que derive de la interfaz IServiceBehavior e implementar el código correspondiente a la modificación de la propiedad en el método ApplyDispatchBehavior.

Posteriormente se establece el nuevo atributo a la clase que representa el servicio WCF.

 [ServiceContract(Namespace = "https://wcf.biztalklatam.com/debug/")]
[CustomDebugBehavior]
public class DebugService
{ }

public class CustomDebugBehaviorAttribute : Attribute, IServiceBehavior
{
    #region IServiceBehavior Members
    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, 
        System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, 
        System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {
        // sin implementar
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers)
            if (cd.BindingName.Equals("https://wcf.biztalklatam.com/binding/:debug1"))
                cd.IncludeExceptionDetailInFaults = true;
    }

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        // sin implementar
    }
    #endregion
}

Por último se inicia el servicio WCF en forma normal: 

 using (ServiceHost host = new ServiceHost(typeof(DebugService))) {
 host.Open();
 ...
}

 

La propiedad IncludeExceptionDetailInFaults nos ayuda en pruebas a encontrar mas información acerca de errores, pero se aconseja deshabilitarla para producción.  Sin embargo, es posible utilizar algun tipo de habilitación parcial de un endpoint para dejar habilitado en producción y en caso de error poder obtener mas información.

 

Autor: Carlos Medina
Este mensaje se proporciona "como está" sin garantías de ninguna clase, y no otorga ningun derecho