viernes, octubre 05, 2007

Cómo consumir desde .NET 2.0 un webservice implementado con PHP 4.4.7/NuSOAP 0.7.2

En los servidores de alojamiento de bajo precio, lo más común es encontrar todavía PHP 4, que no tiene un soporte nativo a webservices en las clases base. En estos casos, hay que recurrir a opciones como NuSOAP, que no requiere extensiones adicionales que de todos modos no son fáciles de instalar y configurar en un servidor compartido.
          En el caso de NuSOAP 0.7.2 (la vigente en octubre de 2007), la forma más directa de implementar un cliente que pueda consumir el webservice es usando el WSDL suministrado por el servidor. Sin embargo, como la última versión liberada de NuSOAP data de marzo de 2004, no incluye soporte para la última especificación de Basic Profile 1.1 de la Web Services Interoperability Organization (WS-I), que es la soportada por .NET 2.0.
          Por esta razón, al intentar consumir desde .NET 2.0 un webservice implementado con esta configuración de PHP 4 / NuSOAP 0.7.2, se obtiene un mensaje de error como este:


The request failed with the error message:

--

<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">

<HTML><HEAD>

<TITLE>301 Moved Permanently</TITLE>

</HEAD><BODY>

<H1>Moved Permanently</H1>

The document has moved <A HREF=\"http://www.server.com/publish/services.php\">here</A>.<P>

</BODY></HTML>



--.


Esto ocurre porque el WSDL generado dinámicamente por NuSOAP en http://www.server.com/publish/services.php?wsdl no genera completa la dirección que el cliente .NET necesita para encontrar el servicio. Lo que el servidor genera es un <soap:address location="http://server.com/publish/services.php"/> (sin el “www”).
          Una forma sencilla de corregir esta situación es grabar la declaración del wsdl que genera el webservice como un archivo (por ejemplo services_wsdl.xml), de tal forma que se pueda publicar en el servidor donde los clientes potenciales puedan encontrarlo. En el archivo hay que completar a mano el wsdl así: <soap:address location="http://www.server.com/publish/services.php"/>
          De esta forma, en el proyecto .NET 2.0 en Visual Studio 2005 se puede usar como WSDL de base http://www.server.com/publish/services_wsdl.xml , tanto para generar una clase proxy usando la herramienta WSDL.EXE como para adicionar un Web Reference. Adicionalmente, hay que cambiar el archivo App.config del proyecto para que incluya la actualización de la ruta del servidor:


< applicationSettings >
  < Module.Properties.Settings >
    < setting name = " Module_com_server_www_publish " serializeAs = " String " >
      < value > http://www.server.com/publish/services.php </ value >
    </ setting >
  </ Module.Properties.Settings >
</ applicationSettings >


Eso es todo. Muchas gracias a Juan Camilo Rincón, sin cuya ayuda todavía estaría preguntándome qué changos le pasó al webservice que funcionaba tan bien al ser consumido desde NuSOAP.

domingo, junio 24, 2007

Sentido del humor ñoño

Creo que ya entendí por qué después de 12 años trabajando como ingeniero, me han empezado a parecer divertidísimas las matrículas de carros como "DBA 073" o "FTP 532":

sábado, junio 16, 2007

Cómo parchar una aplicación Windows Forms

Desarrollé una aplicación WinForms .NET 2.0 de escritorio con Visual Studio 2005 que usa una base de datos implementada en archivos XML. Generé un instalador con el proyecto "Setup" de VisualStudio2005 que ubica el programa (un ejecutable .exe y varios .dll) y los archivos XML en una carpeta dentro de "c:\program files".
          Generé un nuevo instalador con el proyecto "Setup" de VisualStudio2005 de la misma forma que el instalador original pero sin los archivos que no cambiaron y sin los XML para que no los sobreescribiera. Cuando lo ejecuté, Windows me regañó e interrumpió el proceso porque ya hay una versión previa de ese mismo software que ya está instalada.
          Gracias a la recomendación de Jaimir Guerrero probé cambiando el "Assembly version" y el "File version" en las propiedades de la aplicación. Ahora Windows se negaba a instalar argumentando que la versión existente era más reciente que la anterior (???). Entonces probé configurando el instalador para que no verifique si hay instalada una versión más reciente y ya Windows no protestó por la instalación previa, incluso decía que la instalación de la actualización finalizó con éxito, pero cuando probaba la aplicación, aparecía la original y no la actualizada.
          Probé entonces el método "xcopy deployment" sugerido por Ricardo González, que consiste en copiar vilmente los nuevos archivos (el ejecutable .exe y sus .dll) en la carpeta de la aplicación instalada. Aunque logré que un script hiciera la tarea más o menos automáticamente, cuando probaba la aplicación ahora Windows me respondía que la aplicación no coincidía con lo que había salido del instalador original y se rehusaba a ejecutar.
          Desesperado, fui hasta la carpeta misma de la aplicación y di doble clic directamente sobre el ejecutable y... funcionó. Por alguna extraña razón que espero me ayuden a aclarar, los accesos directos a la aplicación que mi instalador original puso en el escritorio, no abren directamente el ejecutable sino que usan algún intermediario que verifica que las versiones cuadren.


Conclusiones:
Al generar una actualización de una aplicación Windows Forms instalada con el instalador generado por el proyecto Setup de VisualStudio 2005 es necesario:



  • Cambiar la propiedad "Version" por un número mayor. Esto provoca que VisualStudio proponga un nuevo valor para la propiedad "ProductCode", lo cual es necesario para que no haya colisiones con la versión previamente instalada.

  • Si aún así Windows protesta, me funcionó cambiar también la propiedad "DetectNewerInstalledVersions" a falso. En teoría esto no es necesario si se ha actualizado la versión, por lo que supongo que hice algo mal.

  • Siempre debe permanecer inalterada la propiedad "UpgradeCode" porque es la que permite a Windows saber que la actualización es otra versión de la misma aplicación y no otra aplicación completamente diferente.

  • En el instalador de la actualización se deben incluir también los accesos directos para que sobrescriban los que ya estaban instalados, no solamente los archivos que cambiaron de una versión a otra. Esta es la razón por la cual el método "xcopy deplyment" es muy útil en aplicaciones web que no usan accesos directos regados por todo Windows, pero que exigen algo más de trabajo en una aplicación de escritorio.

martes, mayo 15, 2007