[AX TIP] Errores Interop CLR y nivel de transacciones

Hace un tiempo publiqué un artículo explicando las buenas prácticas recomendadas para el manejo de excepciones CLR y cómo mostrarlas correctamente en el InfoLog de Dynamics AX. Sin embargo olvidé entonces un detalle importante que hay que tener en cuenta al capturar estas excepciones, que es el nivel de transacciones en la base de datos (TTS Level).

En el siguiente código de ejemplo, nuestro try..catch NO funcionará. Si se produce un error en el try, por ejemplo, si el método get_Content() no existe en el objeto en tiempo de ejecución, la ejecución del código terminará directamente sin mostrar nada en el InfoLog, lo que no es muy deseable.

Esto es debido a que, para poder capturar una excepción CLR, el nivel de transacciones debe ser 0. O lo que es lo mismo, no podemos capturar errores del Interop dentro de una transacción. Para que este código funcione tendremos que re-escribirlo para que el manejo de ese objeto CLR genérico se realice antes de abrir la transacción.

CLRObject       obj;


ttsBegin;  // ttsLevel + 1

info(strFmt("TTS level: %1", appl.ttsLevel())); // TTS level: 1

try
{
    obj = response.get_Content();
    if (!CLRInterop::isNull(obj))
    {
        // ...
    }
}
catch(Exception::CLRError) // Este catch nunca se ejecutará porque ttsLevel > 0
{
    error(AifUtil::getClrErrorMessage());
}

ttsCommit; // ttsLevel - 1

En realidad, y debido al alto riesgo de que se produzcan errores CLR que deben capturarse y procesarse de forma especial, el manejo de objetos CLR debe encapsularse siempre en clases o métodos específicos donde quede claro su funcionamiento y aislado el riesgo de problemas.

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 7’ / Rainier

La noticia de que existe una próxima versión de Microsoft Dynamics AX (versión 7) y que ésta va a ser una revolución en cuanto a la tecnología que la mueve y la experiencia de usuario no es nueva, lo comentábamos aquí ya en Agosto de 2013. Microsoft lleva comentando el proyecto Rainier varios años en diferentes eventos, pero las noticias interesantes siguen bajo NDA por lo que no se pueden publicar todavía.

Microsoft Dynamics 'AX 7'

Sin embargo, en recientes eventos que se han organizado en torno al producto, como los recientes AXUG Focus 2015 y ASUG Summit y las pasadas Convergence 2015 y Microsoft Dynamics Technical Conference 2015 se han publicado numerosas imágenes (Por ejemplo: 1 2 3 4 5 6 7) que revelan el aspecto que va teniendo el producto y la nueva interfaz, además de algunas ideas (sin mucho detalle concreto) de los cambios en cuanto a la tecnología, arquitectura y herramientas de desarrollo, todas alineadas con el nuevo mantra de Microsoft: Cloud first, Mobile first.

Continue Reading…

AX TIP: Ejecutar código X++ externo

Siguiendo con el hilo de mi anterior artículo, otro truco parecido consiste en la posibilidad de utilizar la clase XppCompiler para ejecutar manualmente un fragmento de código almacenado de forma externa, ya sea en la base de datos, en una variable, en ficheros de texto, etc.

Para ello podemos utilizar una sintaxis parecida a la siguiente:

static void JAEE_XppCompiler_Code(Args _args)
{
    XppCompiler comp;
   
    Source codigo =
        "InventLocationId findLocation(InventDimId _inventDimId)" +
        "{" +
        "    return InventDim::find(_inventDimId).InventLocationId;" +
        "}";
   
    InventDimId         inventDimId = "1879356425";
    InventLocationId    result;
   
    new ExecutePermission().assert();
   
    comp = new XppCompiler();
   
    if (!comp.compile(codigo))
        throw error("Código no válido.");
   
    result = runBuf(codigo, inventDimId);
   
    CodeAccessPermission::revertAssert();
   
    info(strFmt("Resultado: %1", result));
}

Tal como decía en el artículo anterior, utilizar manualmente este tipo de API es peligroso y debe ser asegurado. En aquel capítulo incluía algunos enlaces de interés para desarrollar código seguro.

Las posibilidades a la hora de utilizar esta técnica son muy diversas. Podemos utilizarlo para ejecutar pequeños snipets de código almacenados en la base de datos de forma que un usuario pueda realizar pequeñas funciones personalizables, o podemos ir mucho más allá. Por ejemplo en este blog de MSDN nos explican cómo, aprovechando estas mismas clases y ejecutándolas desde el .NET Business Connector, se puede hacer una aplicación de consola para ejecutar fragmentos de código X++ desde línea de comandos.

Introducción a PowerShell para desarrolladores Dynamics AX 2012 (PS-I)

PowerShell (lo abreviaremos PS en lo sucesivo) es una herramienta impresionante, entre otras cosas, para la administración de nuestros servidores y aplicaciones, y eso incluye, por supuesto, nuestro Microsoft Dynamics AX 2012. Con esta versión se incluye un módulo propio de PS al que llama “Microsoft Dynamics AX 2012 Management Shell” con algunos comandos que veremos en sucesivas entregas. Estos comandos son muy útiles, pero podemos sacar provecho también de la funcionalidad estándar de PowerShell para muchas tareas.

Todo esto lo veremos en las siguientes entregas de este artículo, de momento es necesario empezar con lo más básico de PS, que nos permitirá comprender y sacar provecho a los siguientes artículos.

Cómo obtener ayuda

Como, a estas alturas, todos debemos saber, PowerShell es una herramienta de administración de Windows a modo de consola de comandos. Una versión mejorada de la antigua consola msdos disponible en versiones anteriores que, como aquella, nos permite crear y reutilizar scripts de comandos.

Dependiendo de la versión de Windows que utilicemos, PowerShell viene instalada por defecto (en las últimas versiones), o habrá que instalarla manualmente. Se puede descargar de manera gratuita de la web oficial de Microsoft. También se puede descargar un editor gratuito (que también viene por defecto en algunas versiones de Windows) que nos permite editar, depurar y ejecutar scripts de PS fácilmente, llamado Windows PowerShell ISE.

Los primeros comandos (en PS llamados: Cmdlets) que debemos aprender son los relativos a la ayuda. Sin duda, nos van a hacer falta. Podemos utilizar el comando Get-Help para obtener ayuda sobre cualquier comando, o para obtener una lista de los comandos disponibles. Para comprobar las posibilidades del sistema de ayuda podemos probar los comandos siguientes y analizar su resultado:

# Ayuda
Get-Help
Get-Help Get-Help -Full

# Ayuda sobre un Cmdlet
Get-Help process
Get-Help Get-Process –Examples
Get-Help Get-Process –Online

# Actualizar ayuda desde internet
Update-Help

Mediante estos comandos vemos cómo obtener una lista de comandos buscando por una palabra clave, cómo buscar información sobre un comando concreto, cómo ir directamente a la página web de Microsoft que nos muestra la ayuda de un comando, y cómo actualizar desde internet la base de datos de ayuda de nuestro sistema local.

001-GetHelp

La curva de aprendizaje de PowerShell es dura, así que seguro que utilizaremos estos comandos a menudo, sobre todo al principio.

Introducción, Pipes y Aliases

A pesar de que se dice de PS que es la nueva versión de la antigua consola msdos, lo cierto es que su utilización no tiene nada que ver, salvo en el simple hecho de que ambas son consolas de comandos, y ambas permiten almacenar y reutilizar scripts.

El resultado de los comandos de PS es siempre un objeto (como los de programación orientada a objetos), no simple texto como en otras consolas. Por tanto, cuando encadenamos la salida de un comando hacia el siguiente, lo que recibe el segundo comando es un objeto o una lista de objetos de los que puede hacer uso de manera completa (no sólo de lo que se muestra por la consola), incluyendo sus propiedades y sus métodos.

Continue Reading…

Errores Interop CLR y manejo de Infolog en Microsoft Dynamics AX 2012

Al trabajar con objetos del framework .NET (algo muy común en AX 2012), debemos tener en cuenta el tratamiento de errores CLR. El tratamiento de errores en Dynamics AX es transparente y no necesita dedicarle demasiada atención durante el desarrollo en X++, pero cuando interviene el Interop con .NET, el manejo de los errores CLR se debe especificar de forma explícita.

El código que suelo utilizar habitualmente (copiado y pegado de mi repositorio personal) como punto de inicio es el siguiente:

static void JAEE_CLRError(Args _args)
{
    System.Exception ex;
   
    new InteropPermission(InteropKind::ClrInterop).assert();  
   
    try
    {
        System.Int32::Parse("JAEE");  // Error: no se puede convertir un texto a Int32
    }
    catch (Exception::CLRError)
    {
        ex = ClrInterop::getLastException();
        if (ex != null)
        {
            info(ex.get_Message());
            ex = ex.get_InnerException();
            if (ex != null)
                error(ex.ToString());
        }
    }    
    catch (Exception::Internal)
    {
        ex = ClrInterop::getLastException();
        if (ex != null)
            info(ex.get_Message());
    }  
   
    CodeAccessPermission::revertAssert();
}

Continue Reading…