2010-03-25 13 views
8

Tengo un servicio REST consumido por un cliente .Net WCF.Obteniendo los detalles de error de WCF REST

Cuando se encuentra un error, el servicio REST devuelve una solicitud incorrecta HTTP 400 con el cuerpo de la respuesta que contiene detalles serializados JSON.

Si ejecuto la solicitud usando Fiddler, Javascript o directamente desde C#, puedo acceder fácilmente al cuerpo de la respuesta cuando ocurre un error.

Sin embargo, estoy usando un WCF ChannelFactory con 6 interfaces bastante complejas. La excepción lanzada por este proxy siempre es un ProtocolException, sin detalles útiles.

¿Hay alguna manera de obtener el cuerpo de respuesta cuando recibo este error?


actualización

Soy consciente de que hay un montón de diferentes maneras de hacer esto utilizando .Net y que hay otras maneras de conseguir la respuesta de error. Son útiles para saber pero no responden a esta pregunta.

Los servicios REST que estamos utilizando cambiarán y, cuando lo hagan, las interfaces complejas se actualizarán. Usar el ChannelFactory con las nuevas interfaces significa que obtendremos excepciones de tiempo de compilación (en lugar de tiempo de ejecución) y facilitaremos mucho el mantenimiento y la actualización del código.

¿Hay alguna manera de obtener el cuerpo de la respuesta para un estado HTTP de error al usar canales WCF?

+0

Al leer su explicación, parece que no tiene control sobre el servicio REST en sí, ¿es correcto? –

+0

En realidad, en este caso sí, pero es difícil de cambiar. Nuestro problema es la complejidad: WCF ChannelFactory ofrece una forma realmente agradable de gestionarlo con interfaces. Lo molesto es que descarta el cuerpo de la respuesta cuando el estado del encabezado HTTP es distinto a 200. Cuando obtenemos un error del servicio REST, devuelve un estado HTTP 400 o 500 con detalles en el cuerpo. – Keith

Respuesta

1

No use ChannelFactory :-) En serio. ¿Por qué crearía una interfaz REST y luego usaría el proxy del cliente WCF? ¿Cuál es el beneficio de usar el servicio REST? ¿Por qué no usar wsHttpBinding? Con la clase HttpClient del kit de inicio REST, puede realizar solicitudes HTTP estándar y luego deserializar la respuesta utilizando DataContractSerializer.

E.g.

var httpClient = new HttpClient(); 
var content = httpClient.Get("http://example.org/customer/45").Content; 
var customer = content.ReadAsDataContract<Customer>() 
+2

Me gusta su enfoque simple-es-mejor, pero tenemos una gran cantidad de interfaces, y casi todos los métodos toman contenido POST complejo. La simplicidad del código de la implementación de proxy de 'ChannelFactory' nos ahorra muchísima complejidad de código. Sé que se puede hacer a tu manera, pero lo que realmente quiero saber es: ¿podemos obtener el detalle del error si lo hacemos de la manera 'ChannelFactory'? – Keith

3

Usted podría tratar de lanzar una WebProtocolException del servicio. De esta forma, los detalles del error deberían incluirse en el cuerpo de la respuesta HTTP. Echar un vistazo a este artículo:

Effective Error Handling with WCF & REST

+0

Eso es exactamente lo que hace el servicio: los detalles como JSON se serializan en el cuerpo de la respuesta HTTP. El problema es que ChannelFactory lanza una excepción sin esos detalles para cualquier estado de encabezado HTTP que no sea 200. El servicio funciona, es la implementación del cliente de WCF el problema. – Keith

1

Mis dos centavos WCF es que es bueno en la exposición de la misma clase utilizando muchas ediciones diferentes. Cuando se comunique con C#, use un enlace SOAP que sea bueno para información de excepción. Si debe usar el enlace de estilo REST, puede usar una WebRequest simple para llamar al servicio y usar el serializador JSON para deserializar los resultados. Esto también le dará acceso directo al código de respuesta.

4

puede recuperar el detalle excepción de la siguiente manera:

   Exception innerException = exception.InnerException; 
       WebException webException = innerException as WebException; 
       HttpWebResponse response = webException.Response as HttpWebResponse; 
       string statusDescription = response.StatusDescription; 
       HttpStatusCode statusCode = response.StatusCode; 
1

El enfoque descrito por user653761 funciona para mí; después de tener acceso al objeto HttpWebResponse puedo utilizar la clase DataContractSerializer así:

var serializer = new DataContractSerializer(typeof(MyDataContractType)); 
var deserialized = 
    (serializer.ReadObject(httpWebResponse.GetResponseStream()) as MyDataContractType); 

// ... 

supongo que esto funcionaría para cualquier cosa que WCF puede serializar si se utiliza el serializador derecha, no la prueba de rendimiento (aún) .

3

El InnerException del ProtocolException será un WebException. Puede obtener el HttpWebResponse de eso y llamar al GetResponseStream para leer el cuerpo de la respuesta real. (Recuerde buscar al comienzo de la secuencia antes de leer).

var webException = (WebException) protocolException.InnerException; 
var response = (HttpWebResponse) webException.Response; 
var responseStream = response.GetResponseStream() 
responseStream.Seek(0, SeekOrigin.Begin); 
var reader = new StreamReader(responseStream); 
var responseContent = reader.ReadToEnd(); 
Cuestiones relacionadas