2008-09-15 11 views
9

Estoy experimentando con el uso de FaultException y FaultException <T> para determinar el mejor patrón de uso en nuestras aplicaciones. Necesitamos apoyar a WCF así como a consumidores/clientes que no pertenecen a WCF, incluidos los clientes SOAP 1.1 y SOAP 1.2..NET Fallos WCF que generan valores de código de error SOAP 1.1 incorrectos

FYI: el uso de FaultExceptions con wsHttpBinding da como resultado la semántica de SOAP 1.2 mientras que el uso de FaultExceptions con basicHttpBinding da como resultado la semántica de SOAP 1.1.

estoy usando el siguiente código para lanzar una FaultException <FaultDetails>:

throw new FaultException<FaultDetails>(
     new FaultDetails("Throwing FaultException<FaultDetails>."), 
     new FaultReason("Testing fault exceptions."), 
     FaultCode.CreateSenderFaultCode(new FaultCode("MySubFaultCode")) 
    ); 

La clase FaultDetails es sólo una clase de prueba simple que contiene una cadena de propiedad "mensaje" como se puede ver a continuación.

Al utilizar wsHttpBinding la respuesta es:

<?xml version="1.0" encoding="utf-16"?> 
<Fault xmlns="http://www.w3.org/2003/05/soap-envelope"> 
<Code> 
    <Value>Sender</Value> 
    <Subcode> 
    <Value>MySubFaultCode</Value> 
    </Subcode> 
</Code> 
<Reason> 
    <Text xml:lang="en-US">Testing fault exceptions.</Text> 
</Reason> 
<Detail> 
    <FaultDetails xmlns="http://schemas.datacontract.org/2004/07/ClassLibrary" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 
    <Message>Throwing FaultException&lt;FaultDetails&gt;.</Message> 
    </FaultDetails> 
</Detail> 

Esto se ve bien de acuerdo con el SOAP 1.2 especificaciones. El "Código" principal/raíz es "Remitente", que tiene un "Subcódigo" de "MySubFaultCode". Si el consumidor/cliente del servicio utiliza WCF, FaultException en el lado del cliente también imita la misma estructura, con faultException.Code.Name como "Sender" y faultException.Code.SubCode.Name como "MySubFaultCode".

Al utilizar basicHttpBinding la respuesta es:

<?xml version="1.0" encoding="utf-16"?> 
<s:Fault xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> 
    <faultcode>s:MySubFaultCode</faultcode> 
    <faultstring xml:lang="en-US">Testing fault exceptions.</faultstring> 
    <detail> 
    <FaultDetails xmlns="http://schemas.datacontract.org/2004/07/ClassLibrary" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 
     <Message>Throwing FaultException&lt;FaultDetails&gt;.</Message> 
    </FaultDetails> 
    </detail> 
</s:Fault> 

Esto no se ve bien. En cuanto a las especificaciones de SOAP 1.1, esperaba ver el "código de falla" para tener un valor de "s: Client.MySubFaultCode" cuando uso FaultCode.CreateSenderFaultCode (new FaultCode ("MySubFaultCode")). También un cliente WCF obtiene una estructura incorrecta. El faultException.Code.Name es "MySubFaultCode" en lugar de ser "Sender", y el faultException.Code.SubCode es nulo en lugar de faultException.Code.SubCode.Name que es "MySubFaultCode". Además, faultException.Code.IsSenderFault es falso.

problema similar cuando se utiliza FaultCode.CreateReceiverFaultCode (nueva FaultCode ("MySubFaultCode")):

  • funciona como se espera para SOAP 1.2
  • genera “s: MySubFaultCode” en lugar de “s: Server.MySubFaultCode ”y el faultException.Code.IsReceiverFault es falsa para SOAP 1,1

Este artículo también fue publicado por otra persona en http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=669420&SiteID=1 en 2006 y nadie ha respondido. Me resulta muy difícil creer que nadie se ha encontrado con esto, todavía.

Aquí está otra persona teniendo un problema similar: http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=3883110&SiteID=1&mode=1

Microsoft Connect error: https://connect.microsoft.com/wcf/feedback/ViewFeedback.aspx?FeedbackID=367963

Descripción de cómo los fallos deben trabajar: http://blogs.msdn.com/drnick/archive/2006/12/19/creating-faults-part-3.aspx

estoy haciendo algo mal o se trata realmente de un error en WCF?

Respuesta

8

Ésta es mi solución actual:

/// <summary> 
    /// Replacement for the static methods on FaultCode to generate Sender and Receiver fault codes due 
    /// to what seems like bugs in the implementation for basicHttpBinding (SOAP 1.1). wsHttpBinding 
    /// (SOAP 1.2) seems to work just fine. 
    /// 
    /// The subCode parameter for FaultCode.CreateReceiverFaultCode and FaultCode.CreateSenderFaultCode 
    /// seem to take over the main 'faultcode' value in the SOAP 1.1 response, whereas in SOAP 1.2 the 
    /// subCode is correctly put under the 'Code->SubCode->Value' value in the XML response. 
    /// 
    /// This workaround is to create the FaultCode with Sender/Receiver (SOAP 1.2 terms, but gets 
    /// translated by WCF depending on the binding) and an agnostic namespace found by using reflector 
    /// on the FaultCode class. When that NS is passed in WCF seems to be able to generate the proper 
    /// response with SOAP 1.1 (Client/Server) and SOAP 1.2 (Sender/Receiver) fault codes automatically. 
    /// 
    /// This means that it is not possible to create a FaultCode that works in both bindings with 
    /// subcodes. 
    /// </summary> 
    /// <remarks> 
    /// See http://stackoverflow.com/questions/65008/net-wcf-faults-generating-incorrect-soap-11-faultcode-values 
    /// for more details. 
    /// </remarks> 
    public static class FaultCodeFactory 
    { 
     private const string _ns = "http://schemas.microsoft.com/ws/2005/05/envelope/none"; 

     /// <summary> 
     /// Creates a sender fault code. 
     /// </summary> 
     /// <returns>A FaultCode object.</returns> 
     /// <remarks>Does not support subcodes due to a WCF bug.</remarks> 
     public static FaultCode CreateSenderFaultCode() 
     { 
      return new FaultCode("Sender", _ns); 
     } 

     /// <summary> 
     /// Creates a receiver fault code. 
     /// </summary> 
     /// <returns>A FaultCode object.</returns> 
     /// <remarks>Does not support subcodes due to a WCF bug.</remarks> 
     public static FaultCode CreateReceiverFaultCode() 
     { 
      return new FaultCode("Receiver", _ns); 
     } 
    } 

Lamentablemente no veo una manera de utilizar subcódigos sin romper cualquiera de SOAP 1.1 o 1.2 clientes.

Si usa la sintaxis Code.SubCode, puede crear valores de código de error compatibles con SOAP 1.1 pero rompe SOAP 1.2.

Si utiliza el soporte adecuado de subcódigo en .NET (ya sea a través de los métodos estáticos FaultCode o una de las sobrecargas) rompe SOAP 1.1 pero funciona en SOAP 1.2.

7

respuesta de Microsoft:

Como se discutió en http://msdn.microsoft.com/en-us/library/ms789039.aspx, hay dos métodos descritos en la especificación SOAP 1.1 para los códigos de error personalizados:

(1) Utilizando la notación "punto" como usted la describe

(2) Definición de códigos de falla completamente nuevos

Desafortunadamente, se debe evitar la notación "punto", ya que su uso se desaconseja en la especificación WS-I Basic Profile. Básicamente, esto significa que no hay un equivalente real del SubCode de fallas de Soap 1.2 al usar Soap 1.1.

Por lo tanto, al generar fallas, deberá conocer la MessageVersion definida en el enlace y generar códigos de falla en consecuencia.

Desde "emisor" y "receptor" no son los códigos de error vaild para SOAP 1.1, y no hay un equivalente real de un subcódigo de error, no se debe utilizar los métodos CreateSenderFaultCode y CreateReceiverFaultCode al generar los códigos de error personalizado para SOAP 1.1 .

En su lugar, tendrá que definir su propio faultcode, utilizando su propio espacio de nombres y nombre:

FaultCode customFaultCode = new FaultCode (localName, faultNamespace);

Cuestiones relacionadas