Dime WCF ¿Por qué no funcionas?… Not found

¿Siempre que hay un problema con WCF todo lo que obtienes es un “Not found”? No te frustres más, aquí te explico como pedirle a WCF todos esos detalles que te oculta.

WCF es una tecnología tan compleja como Silverlight. Tiene más cosas que una piñata. Es flexible y compatible con muchas tecnologías actuales y otras no tan actuales. WCF es el medio de comunicación preferido cuando trabajamos con Silverlight y, como en toda tecnología, pueden presentarse errores cuando la usamos mal o la desconocemos.

Todos sabemos que no es bueno que el detalle de un mensaje de error le llegue al usuario. Lo peor que puede pasar es que tengamos uno de esos pícaros usuarios que entienden lo que sucedió leyendo el mensaje y por mera curiosidad traten de meter sus narices donde no deben. Para evitar esto lo mejor es atrapar esos duendecillos que molestan nuestras aplicaciones e impedir que el detalle de un error le llegue al usuario… y en esto WCF se pasa de experto.

Si ya has trabajo con WCF habrás notado que cuando tratas de comunicar tu aplicación con uno de esto servicios y algo sale mal obtienes un “Not found”. Si los parámetros con que llamas el servicio no son del tipo correcto obtienes un “Not found”. Si hay alguna restricción que desconoces en el servicio y accidentalmente tratas de sobrepasarla obtienes un “Not found”. Si sabes que el servicio está allí, porque lo ves con tus propios ojos, igual obtienes un “Not found”.

No se diga entonces que WCF quiere enviarle el detalle de un error al usuario. Ese detalle queda tan seguro que incluso nosotros nos vemos en problemas para obtenerlo.

Este inexpresivo mensaje hace parte del comportamiento por defecto de WCF y su única razón de ser es indicarnos que algo anda mal… ¿qué será lo que anda mal? Por supuesto, el mismo WCF nos lo puede decir.

Veamos uno de estos errores en acción. Trataremos de enviarle a un servicio WCF un arreglo de bytes muy grande y obtendremos nuestro querido “Not found” debido a que WCF restringe, pero es configurable, el tamaño de un arreglo que puede recibir.

Este sería el código de nuestro servicio:

  1. [ServiceContract(Namespace = “”)]
  2. [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
  3. public class RecibirArregloService
  4. {
  5.     [OperationContract]
  6.     public void RecibirDatos(byte[] arreglo)
  7.     {
  8.         // Hacer algo aquí en el futuro.
  9.     }
  10. }

 

Nada del otro mundo. Ahora en nuestro proyecto Silverlight vamos a enviarle a este servicio un arreglo de gran tamaño. Valgámonos de una pequeña interfaz para hacer nuestras pruebas:

New Picture (13)

con su respectivo código:

  1. private void btnEnviar_Click(object sender, RoutedEventArgs e)
  2. {
  3.     int Cantidad = Convert.ToInt32(tbxCantidad.Text);
  4.     byte[] Arreglo = new Byte[Cantidad];
  5.     for (int i = 0; i < Cantidad; i++)
  6.         Arreglo[i] = 124;
  7.  
  8.     RecibirArregloProxy.RecibirArregloServiceClient Cliente
  9.         = new RecibirArregloProxy.RecibirArregloServiceClient();
  10.  
  11.     Cliente.RecibirDatosCompleted += Cliente_RecibirDatosCompleted;
  12.     Cliente.RecibirDatosAsync(Arreglo);
  13. }
  14.  
  15. void Cliente_RecibirDatosCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
  16. {
  17.     if (e.Error != null)
  18.         txtResultado.Text = e.Error.Message;
  19.     else
  20.         txtResultado.Text = “Arreglo enviado sin problemas.”;
  21. }

Nuevamente nada extraño. Estamos creando un arreglo de bytes tan largo como lo especifiquemos en la caja de texto, creamos una instancia de nuestro servicio WCF, nos vinculamos al evento Completed de nuestra comunicación y procedemos a enviar. Una vez se completa la transmisión verificamos si se presentó un error y mostramos el mensaje adecuado.

Si usando nuestro código intentamos enviar unos 17.000 bytes este será el resultado (visto desde Visual Studio, que muy amablemente atrapa la excepción antes de dejarla seguir):

New Picture (13)

La restricción aplicada aquí para el tamaño de un arreglo por parte de WCF es al rededor de 16K, por ello el servicio hace !plop! y retorna el temido “Not found”. Si intentan ver más detalles de este error, como la excepción interna, se encontrarán con que también dice “Not found”. Si dejamos seguir el error, este llega a nuestra aplicación y nuestro usuario ve algo así:

New Picture (14

Hasta aquí estamos de acuerdo en que esto es lo único que habíamos podido obtener como información de error por parte de WCF. Ahora veamos como configuramos nuestro servicio para que grabe un archivo de log que nos obsequie algo más útil que un simple “Not found”. Para ello veamos un poco, muy poco, de configuración de WCF.

Si hospedan un servicio WCF en un proyecto web ya habrán notado que la configuración del servicio se inserta dentro del archivo web.config. Algo como esto:

xxx

Intimidante ¿cierto?. Todo lo que debemos hacer es adicionar a todo esto unos tags que le indican a WCF que debe grabar el codiciado archivo de log. Afortunadamente para lidiar con esta catarata de tags, y no estoy exagerando, Visual Studio incluye la herramienta que nos dará la mano: el “WCF Service Configuration Editor”, que encontrarán bajo el menú “Herramientas”.

Una vez ejecuten esta herramienta abrimos el archivo web.config en el proyecto web que hospeda su proyecto Silverlight. Obtendremos algo así:

New Picture (1)

Primer paso para activar el log. Seleccionamos el nodo “Diagnostics” y activamos el “Message logging”:

New Picture (3)

Aquí ya podemos observar el nombre del archivo de log. Si deseáramos grabarlo en una carpeta diferente debemos presionar “ServiceModelMessageLoggingListener”, que abre una ventanita donde podemos especificar cualquier otra ruta.

Hasta aquí ya hay archivo de log generándose, pero aun no tenemos suficiente detalle en él para esclarecer el “Not found”.

Segundo paso, agreguemos detalle al log de errores. Seleccionamos “Message logging” y luego cambiamos a “True” las opciones “LogEntireMessage” y “LogMessagesAtServiceLevel”:

New Picture (5)

Eso es todo. Solo nos falta grabar nuestro cambios, en el menú “File”. Estos cambios debieron quedar en nuestro archivo web.config, que ahora debe haber crecido un poco:

New Picture (7)

¿Se imaginan escribir todo esto sin el “WCF Service Configuration Editor”?

Continuemos. Ahora invoquemos de nuevo nuestro error siguiendo estos pasos:

  1. Ejecutemos nuestra aplicación Silverlight.
  2. Enviemos 17000 o más bytes en el arreglo. Obtendremos el error que atrapa Visual Studio.
  3. Dejamos seguir el error presionando “Continue” en el menú “Debug”. El error (que siempre será “Not found”) llega hasta nuestra aplicación que lo despliega tal como le indicamos. En este punto ya tenemos nuestro archivo archivo de log pero es importante terminar los siguientes pasos.
  4. Cerramos la aplicación Silverlight.
  5. Cerramos el servidor de desarrollo Asp.Net. Esto es muy importante ya que este servidor mantiene abierto el archivo de log y necesitamos que lo suelte para nosotros poder abrirlo con otro herramienta.

Abramos el archivo de log haciendo doble click sobre él:

New Picture (8)

El “Microsoft Service Trace Viewer” se abre para facilitarnos la lectura del log:

New Picture (8)

La pestaña “Activity” nos indica que se registraron 4 mensajes. Seleccionamos ese “4” para ver los mensajes en detalle:

New Picture (9)

Aquí podemos ver en detalle lo que se envió y recibió. Seleccionamos el último mensaje, ya que podemos asumir con cierto grado de certeza que después del error no hubo más comunicación, seleccionamos la pestaña “XML” y !Aleluya! he aquí la razón del error. Observen que tenemos un tag <s:Fault> que, entre otras cosas, contiene la razón del error presentado y es la siguiente:

The formatter threw an exception while trying to deserialize the message: Error in deserializing body of request message for operation ‘RecibirDatos’. The maximum array length quota (16384) has been exceeded while reading XML data. This quota may be increased by changing the MaxArrayLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader.

Provoca gritar un !Gracias Dios mío!. Un vulgar “Not found” no es comparable con todo este nivel de detalle. Incluso obtuvimos una recomendación para hacer la corrección necesaria.

Resaltado en amarillo tenemos la razón (que ya intuíamos): un arreglo no puede tener mas de 16.384 elementos. Cualquier intento de enviar un arreglo más grande es rechazado por WCF (con un lindo “Not found”). Finalmente, resaltado en verde, encontramos lo que deberíamos hacer para incrementar este límite: en alguna parte existe un parámetro MaxArrayLength que debemos establecer con un valor un poco más generoso.

Abrimos nuevamente el “WCF Service Configuration Editor”, que ahora podemos invocar un poco más fácilmente haciendo click derecho sobre el archivo web.config. Por alguno de esos misterios de la vida la primera vez que hagan click derecho sobre el web.config el acceso a esta herramienta no va a estar allí.

El parámetro que debemos incrementar está vinculado al Binding de nuestro servicio. De modo que abrimos el nodo “Bindings” y en el único Binding que tenemos seleccionamos “binaryMessageEnconding”. En la parte derecha esta el parámetro que buscamos con un valor cero, lo que  para este caso quiere decir que utiliza un valor por defecto (los 16k anotados en el log). Lo cambiamos a un valor que se ajuste a nuestra necesidad y grabamos:

New Picture (11)

Ejecutamos nuestra aplicación Silverlight y hacemos una nueva prueba, esta vez exitosa:

New Picture (11)

Ah… y no olviden desactivar el log. No querrán quejas de los señores que administran los servidores.


Silverlight y WCF son buenos amigos y a veces el que parece estar de más es uno mismo. Si estás metido en serio con Silverlight te recomiendo entender WCF, una vez aprendas los básico te va a parecer que con los viejos webservices trabajabas con las uñas.

Anuncios

Acerca de SilverIdeas

Instructor y entusiasta en el uso de Silverlight y otras tecnologías XAML.
Esta entrada fue publicada en Silverlight. Guarda el enlace permanente.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s