Asignación de credenciales para acceder a servicios web

Hace un par de semanas tuve un pequeño problema cuando intentaba acceder a un servicio web publicado en NAV. Disponía de mis desarrollos en asp.net en una máquina virtual con un dominio distinto al servidor donde se encontraba NAV. Por lo tanto, tenía que indicarle de alguna manera el usuario, password y dominio que tenía que utilizar la aplicación web para conectarse. En varios sitios encontré que había que utilizar la siguiente linea de código antes de hacer la llamada a la función del servicio web:

someService.Credentials = new NetworkCredential(“user”, “password”, “domain”);

Hay que recalcar que el último parámetro es optativo pues no es necesario indicarlo cuando el servidor se ubique en el mismo dominio. En mi caso, por encontrarme en un dominio distinto, lo indiqué.

Bien, la aplicación web se conectaba sin problemas y llegados a ese punto me olvidé del tema de las credenciales. Cuando la aplicación web estaba terminada, la publiqué en el servidor definitivo que sí que se encontraba en el mismo dominio y mi sorpresa fue ver que no había forma humana de que funcionara. Constantemente obtenía un error 401 – No autorizado.

La solución: la verdad es que hice bastantes pruebas pero creo que lo hizo que funcionara fue quitarle el parámetro del dominio a la función que otorga las credenciales. A mi entender, no tiene mucho sentido que un método de autenticación falle cuando se le proporciona mas información de la que necesita. En todo caso debería ignoraría pero nunca dar error (y menos si es tan poco descriptivo).

Creación de una BBDD para NAV Developer’s Toolkit

Hace ya bastante tiempo que ando utilizando Developer’s Toolkit (en adelante DevKit) como herramienta para el control de cambios en proyectos de cierta envergadura. Su uso me permite analizar fácilmente las afectaciones que tiene una modificación, los usos que se hacen de un campo o detectar posibles errores que de otro modo se convierten en una odisea. En este post vamos a tratar uno de los puntos que hacen desistir a mucha gente de utilizarlo: Crear la base de datos.

Últimamente vengo utilizando la versión 3.01.410 que podréis encontrar sin problemas en la sección downloads de mibuso.com. En mi caso, me gusta utilizar SQL para alojar la BBDD. Esto permite que varios usuarios puedan utilizar la BBDD y así pueda convertirse en una herramienta ya no personal si no, de todo el equipo de trabajo que pudiera estar involucrado en el proyecto. Así, mientras estéis descargando DevKit podéis ir comprobando que disponéis de Microsoft SQL Express 2008 R2. Acostumbro a utilizar esta versión por varios motivos. Los principales son que es compatible con la versión de NAV que vamos a usar y que no consume excesivos recursos si vamos a utilizar la BBDD de vez en cuando.

Una vez tengamos SQL a punto y hayamos instalado DevKit, lo siguiente que hay que hacer es abrir NAV 2009 SP0. Esto es importante: normalmente la versión que DevKit que viene en el CD de NAV ha sido diseñada para trabajar con la versión antecesora (todavía no entiendo muy bien porque se hace esto). Una vez abierto, creamos una nueva BBDD en nuestro servidor SQL, una nueva empresa e importamos el FOB que hay en la carpeta donde se ha instalado DevKit. Este FOB contiene la estructura de datos y funciones necesaria para que se haga una indexación de la estructura de objetos que importaremos.

Una vez hayamos hecho esto, ya podemos cerrar el cliente de NAV y podemos abrir la BBDD con DevKit. Inicialmente la base de datos no contiene datos. Para crear los datos tenemos dos opciones:

  1. Importar directamente desde NAV. Para poder hacerlo, DevKit utiliza un cliente de NAV que ya tengamos abierto como puente para acceder a todos los objetos de la BBDD y traerse a su BBDD todas sus entrañas.
  2. Importar un TXT generado desde la BBDD. El tiempo de importación es más o menos el mismo, pero a este hay que añadirle el tiempo de exportación.

Cuando el proceso haya terminado, tendremos una foto de la estructura de datos, funciones y procesos de la BBDD. Podremos por ejemplo saber en que puntos de todo el programa se utiliza un campo, detectar en que sitios se hace un DELETE de una de nuestras tablas, etc.

Además, si somos un poco ordenados con las importaciones y las empresas que creemos, dispondremos de un fantástico control de versiones para poder volver a cualquier estado anterior de los desarrollos que estemos haciendo.

La importancia del nombre

Hoy he tenido una batalla con la instalación de los servicios de tercera capa de NAV 2009. Resulta que había que replicar un entorno real de aplicación con acceso a NAV a través de Microsoft Dynamics NAV Business Web Services. Después de restaurar una copia de la BBDD, replicar la aplicación y cambiar el puerto de la ruta de acceso al Web Service, me he dispuesto a crear una nueva instancia del servicio Microsoft Dynamics NAV Business Web Services. En varios foros he encontrado que la forma rápida de hacerlo consistía en duplicar la carpeta donde se encuentran los servicios de tercera capa de NAV, modificar el archivo *.config para indicarle los nuevos puertos que se van a utilizar e instalar nuevos servicios. El problema ha venido cuando, después de instalar los nuevos servicios y arrancarlos, el que en teoría tenía que ser el servicio Microsoft Dynamics NAV Business Web Services se arrancaba como un Microsoft Dynamics NAV Server. Con lo cual las dos instancias que se estaban creando eran de Microsoft Dynamics NAV Server y al arrancar la segunda daba error pues decía que el puerto utilizado ya estaba siendo utilizado. Después de muchas, muchas pruebas he dado con la siguiente página que me ha resuelto todas las dudas. En ella se explica las 4 ó 5 claves que hay que tener en cuenta a la hora de instalar los servicios y da 2 ejemplos perfectos para copiar y pegar. Después de esto, todo ha ido como la seda. En resumen lo que viene a decir la página es:

  • Lo que define si el servicio que se está creando es “Microsoft Dynamics NAV Server” o “Microsoft Dynamics NAV Business Web Services” es el nombre del servicio. Si el servicio empieza por “MicrosoftDynamicsNAVWS” estaremos instalando una instancia de “Microsoft Dynamics NAV Business Web Services”. Cualquier otra cosa, se tratará de uns instancia de “Microsoft Dynamics NAV Server”.
  • Ofrece dos ejemplos de lo que tiene que ser la línea de comandos idónea para instalar los servicios:
  1. SC CREATE “MicrosoftDynamicsNAV$Svr2” binpath= “C:Program FilesMicrosoft Dynamics NAV60Service2Microsoft.Dynamics.Nav.Server.exe” DisplayName= “MSSvr2”
  2. SC CREATE “MicrosoftDynamicsNAVWS$Svr2″ binpath= “C:Program FilesMicrosoft Dynamics NAV60Service2Microsoft.Dynamics.Nav.Server.exe $Svr2” DisplayName= “MSWSSvr2” type= share

Discos SSD para mejorar el rendimiento de NAV

Hace un tiempo ya tuve la ocasión de ver la mejora que representa la implementación de los discos SSD (sobretodo en portátiles). Recuerdo perfectamente un vídeo donde se comparaba el tiempo de arranque de un ordenador con discos convencionales y uno exactamente igual con discos SSD y la diferencia era notable, por no hablar de la eficiencia de los últimos cuando había vibraciones.

Era cuestión de tiempo que este tipo de tests llegaran al mundo de los servicios de datos y, por supuesto, a NAV. En el siguiente enlace podemos ver un buen estudio de comparativa de varios procesos de NAV. En todos ellos el rendimiento de los discos SSD es bastante bueno, y aunque todavía resultan algo caros, hay que valorar convenientemente el coste de este cambio frente al coste que conlleva la mejora de rendimiento de los procesos.

Estas asignaciones nunca fallan

SOBREPASAMIENTO: ¿A quién no le ha pasado alguna vez lo siguiente? Te piden hacer un proceso “sencillo” para importar información en Navision. Como buen experto que eres lo tienes listo en unos pocos minutos y, para asegurarte, haces unas cuantas pruebas y compruebas que realmente funciona. Te aseguras de que el proceso detecta los duplicados, no estropea datos, es estable, etc. Para acabar de probarlo bien, pides un fichero de pruebas que funciona sin problemas. Al cabo del tiempo, llega el día D y la hora H, necesitas lanzar el proceso y de repente…

SOBREPASAMIENTO. Bien!! No pasa nada, esto no daña tu imagen, pero… a nadie le gusta llevar una mancha en la camisa y… esta te la has colgado en el desayuno (campeón)… Es un error tan tonto y tan básico que incluso la persona que tienes al lado dice “¿no cabe?” a lo que respondes “prfff… más o menos”. No va mal encaminado pues es cierto que “algo no cabe en algún sitio” hasta ahí llegamos todos… Ahora el problema es que hay que encender el debbuger y esperar a que la barrita se vuelva a poner en el 95%. De esto hablaremos otro día pero está comprobado que la probabilidad de que una importación falle viene indicada en la propia barra de proceso y que cuando llegas al 100 es que Navision te ha perdonado la vida.

Volvamos a la parte técnica: Evidentemente, el problema es que hemos intentado almacenar una cadena de caracteres en un campo o variable donde no puede caber. Existe un pequeño truco que nos permite cubrirnos las espaldas ante esto:

variableDestino := COPYSTR(variableOrigen,1,MAXSTRLEN(variableDestino));

Con MAXSTRLEN obtenemos la longitud máxima de la variable destino y con COPYSTR seleccionamos solamente esos primeros caracteres. Con esto conseguimos que el proceso no desate un error, aunque hay que advertir al usuario que el proceso truncará aquellos datos que se excedan de los límites admitidos.

En el caso de los dataports, acostumbro a utilizar variables de anchos generosos (XXL) sobre los que volcar la información para después pasarlo a los campos de las tablas. Es, en el paso de variable a campo, dónde utilizo este trozo de código. Es una forma de asegurarme que no existan sobrepasamientos y de ofrecer una tarea más sencilla a un futuro debbugador del proceso.

Trabajando con recordRefs y fieldRefs

El uso de los tipos recordRef y fieldRef no es muy común en el código de NAV y su uso se reduce prácticamente a funcionalidades que afectan de forma muy globalizada en todo el sistema como por ejemplo la funcionalidad de Log de Cambios.

A mi, personalmente, me gusta utilizarlas cuando veo que una sección de código puede ser útil en varias entidades distintas de la base de datos. Recuerdo un desarrollo que hice ya hace un tiempo en que una función construía el XML necesario para la exportación de facturas, albaranes, abonos, etc. Enseguida detecté que la mayoría de campos eran los mismos y que estaba a punto de cuadriplicar mucho código que realmente hacía lo mismo. En este caso utilicé fieldRefs y recordRefs para apuntar a los registros y campos necesarios dado que estas tablas comparten prácticamente los mismos campos y que, además, están dispuestos con el mismo ID (núm. de campo) fue muy rápido y muy sencillo.

En el siguiente ejemplo os voy a mostrar un ejemplo documentado de una función que utiliza este tipo de variables para hacer de otra forma el acceso a las dimensiones que hace NAV desde los distintos documentos de venta:

Si os fijáis bien, en el Form 132, 130, 134, etc. se utiliza un valor constante en la propiedad RunFormLink del botón dimensiones indicando el número de la tabla asociada. A su vez, en el caso de las líneas, existe una función copiada y pegada que muestra las dimensiones relacionadas.

En este caso vamos a utilizar una función para la visualización de las dimensiones asociadas a documentos de forma que pueda ser invocada sin prestar atención al número de la tabla. Esta función podría incorporarse a la Codeunit 408 y sería ella misma la que determinaría el tipo de dato que la llama y pasaría los datos al formulario. Veréis que esta forma no es mejor y quizás no sea necesario el uso de recordRefs y fieldRefs pero pienso que es un ejemplo bastante didáctico para entender correctamente el uso de este tipo de variables. La función necesaria tendría este aspecto:

Una vez hecho esto procederemos a modificar la función ShowDimensions de la tabla 111, de forma que apunte a la nueva función que acabamos de desarrollar en el anterior punto:

Después de esto, modificaremos el Form 130 dónde añadiremos una nueva opción para mostrar las dimensiones del documento asociadas a la cabecera a través de nuestro nuevo método:

En su interior, escribiremos el siguiente código:

Como podemos ver, tanto el acceso desde las líneas como desde la cabecera funciona correctamente. Ahora sólo queda hacer lo mismo con el resto de documentos de venta:

Espero que os haga gustado y que os sirva de mucha ayuda. Podéis descargar este ejemplo a través del siguiente enlace: Descarga (Cuidado: la importación de éste objeto puede sobreescribir desarrollos. Se recomienda importar en una base de datos de pruebas).

Formulario con acceso a datos temporales

En algunas ocasiones puede ser necesario el uso de formularios con acceso a datos que realmente no existen propiamente en la base de datos. En este post paso a explicar las principales directrices que hay que seguir para conseguir esto.

El primer paso es crear un formulario con acceso a la tabla que queremos mostrar. En el ejemplo he creado un nuevo formulario con Wizard de Navision accediendo a la tabla entero.

El siguiente paso es crear una variable de tipo record con acceso a la misma tabla. En las propiedades de esta tabla indicaremos que se trata de una variable temporal.

Ahora lo que hay que hacer es “engañar” a Navision, de manera que cuando quiera encontrar el primer registro de la tabla, obtenga el primer registro de la tabla temporal y cuando quiera el siguiente, obtenga el siguiente de la tabla temporal. Para ello tenemos que modificar dos disparadores del formulario: OnFindRecord y OnNextRecord.

Por último, para probar el ejemplo, he insertado tres registros en la tabla temporal, al iniciar el formulario.

El resultado de la ejecución es el siguiente:

Si os dais cuenta, no he inventado nada. Esto existe en formularios estándar de Navision como “Navigate” (#344).

Si queréis, os podéis descargar el formulario de ejemplo: Descarga

Comandos para la instalación de nuevo NAS

Durante la instalación de Navision Application Server que vimos hace unos días, comenté que automáticamente se instalaban dos servicios de windows: Uno para NAV nativo y otro para NAV SQL. En este artículo, veremos las diferentes secuencias de comandos disponibles para instalar y desinstalar nuevas instancias a nuestro antojo.

Es muy sencillo. Si queremos instalar una nueva instancia de nas abriremos el editor de comandos (inicio -> ejecutar -> cmd) y nos situaremos sobre la carpeta donde tengamos instalado Navision Application Server. Normalmente la tendremos en C:Program FilesMicrosoft Business Solutions-NavisionApplication Server. Despues ejecutaremos el siguiente comando:

Si utilizamos NAV SQL:
nassql.exe appservername=NOMBRE_SERVICIO, NETTYPE=TCP, servername=NOMBRE_SERVIDOR,database=NOMBRE_BASE_DATOS, company=”Mi empresa S.A. “, nettype=tcp, startupparameter=”PARAM_NAS”, objectcache=40000, installasservice

Si utilizamos NAV Nativo:
nas.exe appservername=NOMBRE_SERVICIO, NETTYPE=TCP, servername=NOMBRE_SERVIDOR,company=”Mi empresa S.A. “, nettype=tcp, startupparameter=”PARAM_NAS”, objectcache=40000, installasservice

Después de esto, veremos el servicio instalado desde el listado de servicios de windows, y también podremos modificar su parametrización a través de Navision Application Server Manager. Sólo nos queda indicarle al servicio con que usuario de windows tiene que iniciarse, configurar este usuario en NAV y arrancar. Tenéis más info sobre estos pasos aquí: Todo sobre NAS.

Uno rapidito: Una función muy útil

No sé si le habrá pasado a alguien más, pero en alguna ocasión he necesitado retornar un valor decimal forzado a dos decimales. Lo que a priori puede parecer que se soluciona con un ROUND acaba conviertiéndose en un dolor de cabeza cuando el número es un entero.

Por ejemplo: “ROUND(1.91,0.01)” nos devuelve “1.91” pero “ROUND(1.90,0.01)” nos devuelve “1.9”. Cuando estamos utilizando esto para exportar datos, los valores nos quedan desordenados y mal tabulados. La solución para mi ha sido utilizar esta línea:

format(round(NUMERO,0.01),0,'<Precision,2:2><Standard Format,0>’);

La versión 2 de ésto ha sido esta útil función que hace lo mismo pero permitiéndole indicar el número de posiciones decimales que quiero:

Todo sobre NAS

Navision Application Server es, en pocas palabras, un cliente de navision sin entorno gráfico. Esto significa que podemos disponer de un cliente que se puede conectar de forma automática si lo instalamos como servicio de windows sin necesidad de ni siquiera iniciar la sesión de forma manual. Al no ofrecer un entorno gráfico, todos los procesos y acciones que se llevan a cabo son “invisibles” a los ojos de alguien que pueda estar utilizando el servidor donde se aloja.

¿Y ésto para que lo quiero? Los usos que ésto tiene son muy variados, pero entre ellos destacan la gestión de sincronización de datos con bases de datos externas, la gestión sobre peticiones externas de datos o la ejecución de procesos almacenados en navision.

Vale… Te lo compro… ¿Cómo me lo instalo? Pensaba que ibas a preguntar algo difícil. Es muy sencillo y sólo necesitas el CD de navision. Una vez dentro hay que buscar la carpeta NAS y ejecutar su setup.exe. Recomiendo utilizar la instalación personalizada para que el proceso nos indique el nombre de los servicios que se van a instalar.

¿Cómo lo conecto a mi base de datos? Para que NAS pueda acceder a una base de datos utilizando un login, necesitamos configurar dos cosas: el acceso a la base de datos y un login :P. Tranquilo, esto no es la ayuda del programa PADRE de AEAT… yo quiero ayudarte: Antes de hacer nada, necesitamos saber si nuestra base de datos es nativa o SQL ya que configuraremos la instancia de nas.exe o nassql.exe respectivamente. Para configurar el servicio utilizaremos Navision Application Server Manager. Al entrar al programa simplemente clickaremos con el botón derecho sobre Navision Application Server Manager, seleccionamos la opción nuevo -> Application Server. En el cuadro que nos aparece indicaremos el nombre que hayamos indicado en la instalación de NAS. Si no habéis modificado el propuesto debería ser NOMBRE_MAQUINA-CLASSIC para nas.exe y NOMBRE_MAQUINA-SQL para nassql.exe.

Si por el motivo que sea, tienes problemas para acceder a Application Server Manager, puedes configurar NAS con comando escritos manualmente. Puedes consultar más información consultando este link: Comandos para instalación de un nuevo NAS. En la parte izquierda del programa apareceran los campos que hay que configurar. Hay que indicar los mismos valores que ponemos en nuestro cliente de navision para conectarnos a la base de datos. En el campo Startup Parameter indicaremos “NAS1”. El valor de este campo lo trataremos en el código de la codeunit 1 de Navision para identificar al NAS que se ha conectado a la base de datos. Esto sólamente es útil cuando utilizamos varios NAS en una misma base de datos que comparten un mismo login. Así por ejemplo podriamos tener a NAS1 que se encarga de la ejecucion de una serie de procesos y a NAS2 que se encarga de una gestión de peticiones online que pudiera hacerle un supuesto portal de negocio o B2B. Cuando acabemos de rellenar el formulario le damos a “Apply changes” y lo encendemos.

Ahora viene cuando te preguntas: “¿Ya está? ¿NAS está dentro de Navision?… ¡¡¿Y que c*ño me estará haciendo?!! Mierda!!”. Tranquilo. Lo más seguro es que haya petado, no diga nada y tampoco esté haciendo nada. ¿Por que? Porque Navision nos pide un usuario y una contraseña para entrar y nosotros no le hemos indicado ninguna. Tenemos que ir a los servicios de Windows para indicarle al servicio qué usuario va a utilizar en su intento de conexión a Navision. Para llegar a esa pantalla iremos a Panel de Control -> Herramientas Administrativas -> Servicios. Ahí tenemos que buscar nuestro “Navision Application Server NOMBRE_MAQUINA-CLASSIC” o parecido según nuestra versión de Navision. Cuando lo tengamos localizado le damos a botón derecho -> Propiedades y entramos en la pestaña de inicio de sesión. Aquí indicaremos el usuario que utilizará NAS para entrar en Navision. Recomiendo utilizar un usuario específico del dominio al cual podemos llamar “NAS” o la cuenta de administrador del dominio al comienzo para descartar algún posible problema de credenciales. Ahora, sólo nos queda abrir Navision y comprobar que este usuario de windows existe en la opción de Windows Logins. Nuevamente, y para descartar errores es recomendable otorgar a este usuario un rol tipo “SUPER” o parecido. Una vez hecho esto ya podemos reiniciar el servicio.

¿Cómo puedo saber si está todo bien? Como ya hemos comentado antes, NAS no tiene entorno gráfico. Esto significa que si en las rutinas de ejecución se encuentra con un FORM.RUNMODAL, por ejemplo, NAS da un error y se para. La forma que tiene NAS de enseñarnos este error, es a través del Visor de sucesos. Podemos acceder al visor de sucesos mediante Panel de control -> Herramientas administrativas -> Visor de sucesos -> Aplicación. Los mensajes que nos dan miedo son los amarillos mientras que los blancos son nuestros chivatos (MESSAGE) que se encuentre NAS en el camino. Si hemos seguido los pasos correctamente y hemos sido buenos, tendremos una especie de mensaje por ahí diciendo que Navision se ha podido conectar sin problemas y nos mostrará los datos que hemos configurado en el Application Server Manager. Cualquier otra cosa, me ponéis un comentario y os lo contesto “mu mablemente”. También podéis ver en las sesiones de la base de datos si está el usuario dentro de navision.

Sigo aterrorizado… ¿que está haciendo esto en mi navision? Seguramente nada de nada. Prácticamente todo el mundo sabe o supone que una de las primeras cosas que se ejecuta cuando accedemos a navision es la función “opencompany” de la codeunit 1. Pero NAS, que es muy listo, ejecuta la función “NASHandler” cuyo parámetro es precisamente el NAS Parameter que habíamos configurado antes. Eso quiere decir que ahí es donde va a empezar nuestra odisea, nuestras rutinas para hacer que NAS haga lo que nosotros queramos: un planificador de tareas, un sistema de alertas, un gestor de sincornizacion, un gestor de peticiones, etc. Os voy a contar un secreto: Si exportáis la codeunit 1 en modo texto veréis que NASHandler es la funcion 99 SIEMPRE. Si no es la 99, NAS no funciona.

Soy una máquina. Ya he empezado a hacer mis cositas con NAS pero siempre estoy duplicando funciones y muchisimas líneas de código para evitar encontrarme con CONFIRMS, FORMS, DIALOGS, etc, etc… Fácil. Si miras una codeunit estandar veras que los DIALOG estan protegidos por una línea que los precede que dice “IF GUIALLOWED THEN”. GUIALLOWED es una función que está en navision, la vemos, no la entendemos y nos da igual. Sólo el ser humano puede hacer estas cosas. GUIALLOWED nos indica si el usuario que esta ejecutando esta línea es capaz de proporcionar entorno gráfico o no. En resumen “IF GUIALLOWED THEN” = “IF NOT ERES_EL_NAS THEN”. Acordaros de ésta función porque seguro que váis a tener que colocar muchas a partir de ahora.