martes, 9 de septiembre de 2008

Cantidad de Visitas al Articulo:

Web Services con Visual Studio 2005

VS2005_2 Errores inesperados

Días atrás me encontré con un error inesperado cuando estaba consumiendo un Web Service de un tercero, al cual no tenía la posibilidad de acceder como para pedir ningún tipo de revisión.

Como comentario adicional antes de seguir en el desarrollo de éste tema, me gustaría hacer referencia al artículo anterior, donde hablo acerca de las facilidades actuales para los programadores, en la búsqueda de soluciones en línea ante problemas inesperados. En otra época, este inconveniente posiblemente hubiera retrasado el desarrollo quizá varios días, mientras que en la actualidad fueron un par de horas, de búsqueda en foros, blogs, etc., mas pruebas.

El problema

Consistía en que utilizando Visual Studio 2005, herramienta de desarrollo de Microsoft, generaba el proxy de conexión a un Web Service de un tercero sin problemas, automáticamente como lo permite este IDE en particular. Luego programaba la utilización de un método específico, y compilaba la aplicación sin errores. El error surgía cuando instanciaba el objeto del Web Service, de la forma:

using (TipoWS ws = new TipoWS()) { }

La excepción indicada era algo como: "Message = "No se puede reflejar el método TipoWS.Metodo."

Y la InnerException indicaba: InnerException {"El elemento XML 'Datos-Respuesta' del espacio de nombres 'urn:TipoWS' hace referencia a un método y a un tipo. Cambie el nombre del mensaje del método utilizando WebMethodAttribute o cambie el elemento raíz del tipo utilizando XmlRootAttribute."}

Luego de leer varios casos similares, y con la imposibilidad de acceder a modificar el WSDL del Web Service, encontré algunos indicios de solución, que me llevaron a resolver el tema, así que aquí lo comparto con Uds. por si alguno se encuentra con este inconveniente en el futuro.

La Solución

Consistió simplemente en modificar el nombre en el atributo SoapDocumentMethodAttribute, en uno de los dos métodos en que se referenciaba. Existían dos métodos del Web Service que se generaban en el archivo Reference.cs, de la forma:

[System.Web.Services.Protocols.SoapDocumentMethodAttribute("", RequestNamespace="urn:TipoWS",
ResponseElementName="Datos-Respuesta", ResponseNamespace="urn:TipoWS", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
[return: System.Xml.Serialization.XmlElementAttribute("Respuesta", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public Respuesta Metodo1([System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)] Encabezado Encabezado, [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)] Parametro Parametro, [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] out respuesta Respuesta) {

[System.Web.Services.Protocols.SoapDocumentMethodAttribute("", RequestNamespace="urn:TipoWS",
ResponseElementName="Datos-Respuesta", ResponseNamespace="urn:TipoWS", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
[return: System.Xml.Serialization.XmlElementAttribute("Respuesta", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public Respuesta Metodo2([System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)] Encabezado Encabezado, [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)] Parametro Parametro, [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] out respuesta Respuesta) {

Los métodos, Metodo1 y Metodo2, en el SoapDocumentMethodAttribute, hacían referencia a ResponseElementName="Datos-Respuesta". Esto provocaba el error en tiempo de ejecución antes mencionado.

La solución fue modificar uno de los dos a ResponseElementName="Datos", y el restante dejarlo como había sido generado.

Luego de compilar nuevamente el proyecto, la aplicación funcionó perfectamente.

Conclusiones

Puedo mencionar como conclusiones lo siguiente:

Es una solución factible, y que funciona, teniendo en cuenta la imposibilidad de acceder a modificar el Web Service o mejor dicho la definición WSDL.
En algún blog leí que el error se producía porque al generarse de esta forma el llamado a los métodos, no se cumplía con cierto estándar, pero no encontré mayor información al respecto como para dar fe de esta afirmación.

Aunque leí acerca de los atributos SoapDocumentMethodAttribute, (aunque en honor a la verdad no demasiado en profundidad) no encontré una razón lógica por la cual se de el error.

Tampoco encontré referencias concretas al porqué se genera así el proxy, como para determinar si en el momento de la generación, el programador a través de parámetros de generación, pude exigir chequeos de ésta naturaleza, de tal forma de evitar tener que retocar a mano el archivo generado automáticamente. Especialmente porque cada vez que se refresca la referencia al Web Service, se debe volver a modificar el archivo nuevamente.

Si algún lector tiene una explicación concreta acerca del problema, y una solución potencial, les pido lo publiquen como comentario de tal forma de poder cerrar este tema de la mejor forma posible. Sino, al menos tienen una ayuda para poder cumplir con los tiempos de desarrollo comprometidos :-).

Imágenes by TinyPic

So far, So good.

Cantidad de Visitas al Articulo:

1 comentarios:

Anónimo dijo...

Hay un sitio que de seguro te va a ser muy util:

beta.stackoverflow.com

sin tener el wsdl es dificil diagnosticar tu problema.
Hay varios tipos de webservices: soap-rpc, document, wrapped y message.
Ademas estan los estandares y si son WS-I.
En general, cuando invocas web services generados con java desde .net casi siempre hay problemas como el que describes.
Saludos, hechale un vistazo a stackoverflow, o si necesitas te puedo conseguir una cuenta beta.
Saludos

 
Este Weblog, InforMateando..., está licenciado bajo Licencia Creative Common - por Gustavo Suhit