HOWTO: Exponer servicios de Microsoft Dynamics AX 2012 en un IIS externo

Para exponer los servicios web de Microsoft Dynamics AX 2012 fuera de nuestra red, es necesario instalar un servicio IIS que maneje las conexiones y la seguridad con “el mundo exterior“. La instalación de este servicio dependerá de nuestra red y lo ideal es que sea realizado por personal especializado en estas tareas (normalmente en un departamento de sistemas). Una vez instalado, la conexión de este servicio IIS con nuestra instancia de AX es muy sencilla.

Antes de empezar la instalación en sí, comprobamos algunos pre-requisitos.

  • El servicio IIS debe estar instalado y funcionando previamente. Si no lo está, para instalarlo hacemos lo siguiente:
    • La mayoría de pre-requisitos se pueden instalar directamente desde el instalador de Microsoft Dynamics AX 2012, pero si esto falla será necesario instalarlo manualmente.
    • Activar el rol Web Services en nuestro servidor y seguir el asistente.
    • Un reinicio es necesario al final del proceso.
    • Las opciones por defecto son suficientes para la instalación de Dynamics AX, pero probablemente será necesario realizar ajustes extra para adaptarlo a la seguridad que deseamos implementar en nuestra empresa, según el caso. No hay que olvidar que la finalidad de esta instalación es exponer este servicio a internet.
    • Puesto que el ejemplo es un servidor de pruebas, mantenemos las opciones por defecto, lo que implementará la seguridad nativa de Windows con Active Directory, solicitando un usuario válido durante la conexión.
  • Una vez instalado y asegurado nuestro servicio IIS, iniciamos el asistente de instalación de Dynamics AX 2012 en el mismo servidor y elegimos la opción Web Services on IIS, y seguimos las instrucciones. Durante el asistente, se nos solicita diversa información sobre nuestra instancia de AOS y las credenciales utilizadas para la conexión, como son:
    • Información sobre la instancia de AOS en sí: Nombre y puertos TCP/IP y WDSL
    • Cuenta de servicio configurada en AX (Business connector proxy)
    • Pool de IIS donde se instalarán y expondrán los servicios de AX
    • Las cuentas de servicio utilizadas para ejecutar nuestras instancias de AOS
  • El propio instalador configura la seguridad por defecto de la aplicación recién instalada en el pool de IIS seleccionado, pero podemos revisarla y configurarla manualmente si es necesario:
    • Se ha creado la aplicación MicrosoftDynamicsAXAif60 en el pool de IIS indicado
    • Se ha creado un nuevo grupo de usuarios local llamado Microsoft Dynamics AX Web Service Administrator incluyendo los usuarios que ejecutan los servicios AOS, según indicamos en el instalador.
    • Se le ha otorgado permiso a este grupo en la carpeta local AifWebServices del servidor IIS

También se ha creado un nuevo servicio en Microsoft Dynamics AX que podemos revisar en Administración del sistema > Configurar > AIF > Sitios web. Utilizaremos este sitio web para asociarlo a un puerto de entrada para poder exponer métodos en nuestros servicios, de esta forma:

  • Crear un nuevo puerto de entrada y seleccionar
    • Adaptador: HTTP
    • URL: Seleccionar la aplicación recién creada de la lista
  • Añadir las operaciones de servicio que se desean exponer mediante el botón Service operations
  • Realizar el resto de configuraciones requeridas en el puerto de entrada, como validaciones o restricciones que vayamos a necesitar. En mi caso voy a limitar las conexiones a un grupo de usuario de AX y a una sola empresa.

Como se puede ver en las imágenes a continuación, las operaciones expuestas de este modo pueden ser consumidas desde una aplicación externa en Visual Studio, a través de la aplicación creada en nuestro IIS:

Espero que este manual paso a paso haya sido útil y pueda servir de referencia para futuras instalaciones 😉

Conectar a servicios externos mediante HTTPS desde Microsoft Dynamics AX 2012

Hace ya bastante tiempo publiqué el código necesario para consumir servicios web externos desde Microsoft Dynamics AX 2012 utilizando únicamente X++. Este código se puede encontrar fácilmente en muchos sitios ya que es básicamente el mismo para casi cualquier servicio WCF, pero a veces necesitamos ajustar algunas propiedades de la conexión, por ejemplo, para conectar a extremos HTTPS.

Según la documentación de MSDN (aquí), en C# el cambio sería muy sencillo, simplemente modificando un par de propiedades del binding durante la conexión:

BasicHttpBinding b = new BasicHttpBinding();
b.Security.Mode = BasicHttpSecurityMode.Transport ;
b.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;

Sin embargo en X++, como suele pasar al utilizar tipos de .NET, la cosa no es tan simple, aunque no es demasiado complicado. Este es el código genérico que suelo usar:

Continue Reading…

Microsoft Dynamics AX 2012, servicios web, .NET Interop, cliente-servidor y arquitectura de aplicación

¡Vaya título! ¿Qué tienen que ver todos estos conceptos y por qué debería tenerlos en cuenta? Es posible que no sea una situación que se nos presente todos los días, pero hay veces donde hay que tener todos esos conceptos en cuenta para hacer que un fragmento de X++ funcione correctamente. Este ha sido mi caso: Tengo que consumir un servicio web externo desde Microsoft Dynamics AX 2012. Parece fácil, ¿no?. El servicio web se va a consumir en un proceso por lotes (servidor), pero también debe poder llamarse manualmente desde formularios (cliente).

En Microsoft Dynamics AX 2009, para utilizar un servicio debíamos añadir una referencia de servicio al AOT. En la versión 2012 creamos un proyecto Visual Studio de tipo Librería de clases. En ese proyecto de Visual Studio agregamos una referencia de servicio y agregamos el proyecto al AOT. No voy a entrar en detalle sobre ésto porque esta bien explicado por ejemplo en este white paper.

Una de las cosas a tener en cuenta acerca de los conceptos del título de este post está en las propiedades del proyecto en Visual Studio:

Propiedades Proyecto Visual Studio

Lo relevante aquí es marcar Deploy to Client si queremos que la DLL se despliegue a los clientes y Deploy to Server si queremos que se despliegue al servidor. De esta manera, el sistema copiará la librería cuando sea necesario a la carpeta correspondiente, descargándola de la base de datos (de la Model Store) donde está almacenada. Dependiendo de cómo se ejecute el código X++ que utiliza esta librería podemos marcar uno u otro o los dos.

Continue Reading…

Traducción automática de etiquetas con BING

El pasado viernes Arijit Basu publicó en su blog un experimento, mediante el cual explicaba brevemente como utilizar el servicio web publicado por Microsoft de su producto BING para traducir cadenas de texto desde AX.

Este artículo me llevo a una idea propia de como sacarle utilidad a esa funcionalidad. Cuando uno trabaja en un entorno con varios idiomas, puede ser útil que al generar una etiqueta en nuestro idioma, se generen automáticamente el resto de idiomas ya traducidos.

Yo no he llegado tan lejos (todavía) pero he hecho una pequeña aproximación que paso a compartir, este es el resultado:

InfoLog Result

despues de ejecutar el Job:

/*
   JAEE - www.jaestevan.com

   @created 10/10/2009 tested in AX2009 SP1
*/

static void MicrosoftTranslatorTest(Args _args)
{
   MicrosoftTranslator msTrans = new MicrosoftTranslator();
   ;
   msTrans.createLabel("Ahora axapta puede traducir etiquetas! (jaestevan.com)", "es");
}

Desde aquí (AX class is documented in english too) se puede descargar un fichero XPO con la clase que paso a comentar. En la construcción de la clase indicamos nuestro código de BING (el cual se solicita en su web de forma gratuíta e instantanea) así como una lista de los idiomas que queremos traducir, indicando el código de idioma de AX así como el código del idioma en BING (usualmente el mismo). Por ultimo y de manera opcional podemos indicar el fichero de etiquetas donde se generarán, aunque por defecto utilizaremos el módulo por defecto por lo que este parámetro es opcional. Este es el método en cuestión:

void new(LabelModuleId _modulo = SysLabel::defaultModuleId())
{
   // Axapta Label Module Id
   moduleId = _modulo;

   // Microsoft BING AppID - http://www.bing.com/developers
   appId = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

   // List of languages to translate (AX lang, BING lang) (Idiomas a traducir)
   transLang = new Map(Types::String, Types::String);
   transLang.insert('de','de');
   transLang.insert('ru','ru');
   transLang.insert('en-us','en-us');
   transLang.insert('fr','fr');
}

Esta es la manera de configurar la clase para su uso (si bien está construida para ser un ejemplo, no para servir de cualquier utilidad real).

El kit de la cuestión lo encontramos en el siguiente método, el cual genera la etiqueta (si no existe) en el idioma predeterminado y luego busca la traducción en BING para todos los idiomas configurados en la clase:

public void createLabel(str _txt, str _txtLang)
{
   MapEnumerator       langEnum;
   Label               l;
   str                 res;

   LabelId             labelId;
   SysLabelEdit        labelEd     = new SysLabelEdit();
   SysLabel            sysLabel    = new SysLabel('es');
   ;

   // Find or create the label (busca la etiqueta y si no existe la crea)
   labelId = labelEd.findLabel(_txtLang, _txt);
   if (!labelId)
   {
       sysLabel.insert(_txt, _txt, this.parmModuleId());
       labelId = labelEd.findLabel(_txtLang, _txt);
   }

   //Log
   InfoLog.add(Exception::Info, strfmt("Traduciendo: (%1) %2", _txtLang, _txt));

   // Update the label for each language (actualiza la etiqueta para cada idioma)
   langEnum = new MapEnumerator(this.parmLangs());
   while (langEnum.moveNext())
   {
       // Call to translate (función de traducir)
       res = this.strTranslate(_txt, _txtLang, langEnum.currentValue());

       // Modify label with new translated text (modifica la etiqueta con el texto traducido)
       labelEd.labelModify(langEnum.currentValue(), labelId, res, _txt, SysLabelApplModule::None, true);

       // Log
       InfoLog.add(Exception::Info, strfmt("(%1) %2", langEnum.currentKey(), res));
   }

}

El trabajo de integrar esta funcionalidad con el editor de etiquetas estándar queda pendiente para otra entrega.

Enlaces

Descarga

Consumir Servicios Web desde AX

Leo en el blog de axaptafreak” la publicación de un interesantísimo White Paper del mismo autor en MSDN con un ejemplo práctico de cómo consumir un servicio web externo desde AX 2009.


En el artículo explica paso a paso como hacer que axapta lea información de un servicio web externo que publica tablas de conversión de divisas en un desarrollo nuevo dentro de AX, muy interesante.


Descargar White Paper (Inglés): Microsoft o MS Dynamics AX Developer Center