2010-09-08 9 views
6

Estoy tratando de atrapar una FaultException dada en un cliente WCF. Básicamente necesito extraer una descripción interna de la clase de falla para que luego pueda empaquetarla en otra excepción para que las capas superiores hagan lo que sea.FaultException.Detail volver vacío

He hecho esto con éxito varias veces, lo que lo hace diferente esta vez es que la falla se declara como una matriz, como se puede ver en el atributo de referencia de servicio declarado sobre el método que arroja la excepción:

[System.ServiceModel.FaultContractAttribute(typeof(FaultClass[]), Action = "http://whatever/", Name = "whateverBusinessFault")] 

Este es mi código:

try 
{ 
    // call service here 
} 
catch (FaultException<FaultClass[]> ex) 
{ 
    if (ex.Detail != null && ex.Detail.Length > 0) 
    { 
    throw new CustomException(ex.Detail[0].description); 
    } 
    else 
    { 
    throw; 
    } 
} 

problema es Detalle (que es una matriz) está volviendo siempre vacía en el código, incluso si puedo ver los datos (descripción de campo, etc.) en el respo de SOAP nse de traza de WCF.

Así que las cosas que necesito definitivamente vuelven, pero por alguna razón o no se deserializa o no puedo obtenerlo desde el código.

Cualquier ayuda apreciada!

ACTUALIZACIÓN:

Tratando con @Darin sugerencia, pero sin suerte, la cadena que estoy extrayendo del XmlReader es "/ r/n":

var sb = new StringBuilder(); 

using (XmlReader reader = fault.GetReaderAtDetailContents()) 
{ 
    while (reader.Read()) 
    sb.AppendLine(reader.ReadOuterXml()); 
} 

var detail = sb.ToString(); 

se parece a la sección de detalle es ¡no viene para nada!

+0

¿Qué sucede si modifica su código (solo para prueba) para usar solo FaultClass (no matriz)? –

+0

ya lo intenté, no detecta la excepción – JohnIdol

+0

Esta pregunta no se puede responder sin una respuesta de falla de muestra o el esquema real del error personalizado definido en el WSDL –

Respuesta

2

Se me ocurrió el caso de prueba más simple que pude. Espero que te ayude. lado del servidor:

[ServiceContract] 
public interface IService1 
{ 
    [OperationContract] 
    [FaultContract(typeof(FaultClass[]))] 
    string Crash(); 
} 

public class Service1 : IService1 
{ 
    public string Crash() 
    { 
     var exception = new FaultException<FaultClass[]>(new FaultClass[] { new FaultClass { Data = "TEST" } }, new FaultReason("Boom")); 

     throw exception; 
    } 
} 

[DataContract] 
public class FaultClass 
{ 
    [DataMember] 
    public string Data { get; set; } 
} 

lado del cliente:

try 
{ 
    using (var client = new Service1Client()) 
    { 
     client.Crash(); 
    } 
} 
catch(FaultException<FaultClass[]> e) 
{ 
    //Break here 
} 
+1

Gracias, no tengo acceso al servicio en sí (es un servicio de eje java). Estoy consumiendo con un cliente WCF y capta la falla, pero la matriz está vacía, aunque puedo ver (desde la traza) hay un elemento en la respuesta del servicio. – JohnIdol

+0

Puede deberse a una diferencia en un espacio de nombres XML que impediría que los datos en la falla se deserialicen. ¿Comparaste el contenido de la FaultClass de WCF con el contenido de una FaultClass de Java? –

+0

lo único que tengo es el wsdl, del cual genero la referencia del servicio WCF. Comparé el contenido del wsdl con la referencia de servicio generada y se ve bien. Si esto fuera el caso (problemas de espacio de nombres) esperaría tener problemas de deserialización en otros tipos también, ya que las fallas están en el mismo espacio de nombres, ya que el resto de los tipos – JohnIdol

5

Es difícil decir dónde está el problema, pero sospecho que la pistola de fumar es este servicio web eje no generar mensaje estándar. Una forma de solucionar esto sería analizar el código XML sí mismo:

try 
{ 
    proxy.CallSomeMethod(); 
} 
catch (FaultException ex) 
{ 
    var fault = ex.CreateMessageFault(); 
    using (XmlReader reader = fault.GetReaderAtDetailContents()) 
    { 
     // TODO: read the XML fault and extract the necessary information. 
    } 
} 
+0

le darán una oportunidad - tnx – JohnIdol

+0

Creo que nos estamos acercando ! El problema es que no sé cómo se forma ese detalle, así que no sé qué elementos/atributos debería buscar. ¿Será exactamente igual a la respuesta que veo en el jabón que sale del servicio? – JohnIdol

+0

(por alguna razón, SO no me permite votarte, dice que ya voté, que no es el caso) – JohnIdol

1

tuve una situación similar en el intento de comunicar datos con fallos (en concreto un seguimiento de pila). Ver this question. Terminé resolviéndolo creando mi propio rastro de pila serializable e incluyéndolo en una clase FaultException derivada.

2

Me llevó años descubrir cómo obtener el mensaje completo de FaultException como una cadena. Finalmente he averiguado y escribí este método de extensión:

public static string GetDetail(this FaultException faultException) 
{ 
    if (faultException == null) 
     throw new ArgumentNullException(nameof(faultException)); 

    MessageFault messageFault = faultException.CreateMessageFault(); 
    if (messageFault.HasDetail) { 
     using (XmlDictionaryReader reader = messageFault.GetReaderAtDetailContents()) { 
      return reader.ReadContentAsString(); 
     } 
    } 
    return null; 
} 

Al principio yo estaba usando reader.Value pero que sólo apareció a la vuelta de la primera línea de una multilínea detalles del mensaje. reader.ReadContentAsString() parece obtener todo, nuevas líneas incluidas, que es lo que quería.

+0

Me he dado cuenta de que esto funciona bien si los detalles son cadenas multilínea, pero no tan bien si se trata de una jerarquía de elementos XML. –

4

he encontrado la solución en un Foro de UPS:

https://developerkitcommunity.ups.com/index.php/Special:AWCforum/st/id371

". El problema fue el estudio visual no acababa de trazar el ErrorDetail objetos derecha El nodo ErrorDetail se llama 'ErrorDetail', pero el tipo generado para él es "ErrorDetailType". Edité la clase reference.cs generada para cada servicio que estaba usando y agregué un TypeName: "

+1

¡Mi héroe! :) Para aclarar, está hablando de el XmlTypeAttribute, agrega 'TypeName =" ErrorDetail "' allí y funcionará. – stroborobo