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.