MVC + jqGrid = Dolores de cabeza

El titulo refleja lo que estuve padeciendo estos días con MVC y jqGrid y más que una queja es un título para atraer lectores :), porque si bien la combinación me produjo un dolor de cabeza que un anti-migrañas desapareció, en realidad me he estado divirtiendo más que nunca con lo que estoy haciendo J. Pero aquí les presento el problema al que me enfrente:

Como han debido explorar por la web existen muchos y variados artículos que muestran el uso de jqGrid junto a ASP.NET MVC, todos ellos hablan de lo simple que puede ser combinarlos para lograr un grid de prestaciones profesionales en “minutos”, todo ello tiene algo de verdad, aquí les muestro un script (demo.js) que contiene el código que prepara un jqGrid.

clip_image002

Observaran en la captura que he marcado un parámetro llamado url, este parámetro apunta a un “Action Method” de un Controller, que es el responsable de poblar el grid.

El método es como el siguiente:

clip_image004

Como poblaran el grid ya cuestión de cada uno, por cierto este no es un post para cubrir como poblar un jqGrid, para eso saint-google puede ayudarles.

Hasta aquí todo normal, pulsamos F5 en un mundo de desarrollo ideal, el grid se llena de datos.

clip_image006

En mi navegador se puede observar la uri que contiene y que efectivamente corresponde al servidor web de desarrollo que se levanta con Visual Studio.

clip_image008

Hasta aquí todo bien, todas las promesas de un grid con prácticamente con poco esfuerzo casi se cumplen y digo CASI porque pasando al mundo real, es decir llevando esta aplicación a un servidor de pruebas que está ubicado en un host como ser: http://testserver/reportapp/, es donde los problemas comienzan.

Inexplicablemente cuando se inicia la aplicación en el servidor de testeo, el grid no se puebla de datos, aparece totalmente VACIO!!!!, vuelvo a mi máquina de desarrollo y todo funciona de mil maravillas pero en el servidor NO! ¿Qué ocurrió?

Haciendo uso del buen Firebug (a mis amigos que ya me conocen…..mejor no digo nada), logro descubrir el error. Sucede que en mi máquina de desarrollo todo va de maravillas por que la propiedad url del grid, que les muestro nuevamente:

clip_image010

Forma una url completa como la siguiente: http://localhost:34953/Report/FillSatisfactionData, url totalmente valida, PERO, cuando examino la url que se forma en el servidor de testeo es http://testserver/Report/FillSatisfactionData, a los que me están siguiendo con detenimiento en la explicación, se darán cuenta que algo falta en la URL, el link que se ha formado ha omitido el directorio virtual!!!!!

Este “problema” es el que me tuvo entretenido unos minutos y también buscando una solución en saint-google, pero como que parece que nadie hubiera tenido el mismo problema, quizá estoy cometiendo un error de omisión en alguna parte y tenía que dar solución a este inconveniente así que a continuación les muestro como los resolví.

He construido un jscript similar al siguiente:

<script type="text/javascript">
        $.currentPath = function (url) { { return ‘<%= Request.Url.AbsoluteUri%>’ + url; }; }
        $.domain = function (url) {
            {
return ‘<%= string.Format("{0}://{1}{2}{3}", Request.Url.Scheme, Request.Url.Host, Request.Url.Port == 80 ? string.Empty : ":" + Request.Url.Port, Request.ApplicationPath) %>’ + url;
            };
        }
</script>

Este código está dentro del Site.master y como podrán observar tiene 2 funciones, una $.currentPath y la otra $.domain ambas destinadas a devolver la url absoluta “completa” de nuestro servidor, la más útil para resolver el problema es la última función, que sea cual sea el nivel de anidamiento de un directorio virtual nos devolverá o formara correctamente la url.

El código resultante de nuestro .js que contiene la inicialización del jqGrid, se convierte en lo siguiente:

clip_image012

Espero que a alguien le sirva esta pequeña experiencia y si Uds. tienen una mejor solución o una corrección a esta, pues bienvenida.

Un abrazo.

10 comentarios en “MVC + jqGrid = Dolores de cabeza”

  1. Hola, si no me equivoco creo que lo puedes simplificar haciendo uso de Html.RouteLink, tiene un overload para generarte urls absolutas. (ActionLink creo que tambíén, pero no estoy seguro).

    Un saludo.

  2. Hola Javier, Hay un inconveniente con lo que planteas, el script del jqgrid esta en un archivo demo.js separado, en la carpeta Scripts y cuando en ese tipo de archivos intento colocar una expresion < %= ....%> no la reconoce, estas expresiones solo pueden ser usadas en archivos .aspx es decir en la paginas per-se. Gracias por la sugerencia de todas maneras.

  3. ¡Hola, Enrique!

    EMHO, la solución pasa por no utilizar constantes para las rutas, sino generarlas con el helper Url.Action().

    Dado que, como indicas, tienes ese código en un .js, una cosa que puedes hacer es generar la URL desde la vista y pasarla como parámetro al código de script. En otras palabras, si introduces la inicialización de jqGrid en una función (en el .js externo) y la invocas desde la vista (desde donde sí puedes usar el helper), tendrás el problema solucionado.

    Saludos!

  4. Estimado Jose, coincido contigo, pero me gustaria aclarar tu punto de vista para los restantes lectores, estas de acuerdo con mi solucion? La solucion que planteas es una solucion alternativa?, Quiza te animas a un ejemplo para nosotros humildes mortales :{
    Saludos

  5. @HardBit, porque te parece que hay perdida de calidad?, Geeks se está diversificando, y hoy en día hay que continuar evolucionando para que no nos coman…

  6. Hola de nuevo!

    @Enrique, a mi entender el problema en ese código está en que al final en el archivo .js tienes una referencia «hardcoded» hacia /Report/FillSatisfactionData, con lo cual estás asumiendo una estructura de rutas determinada y está afectada por cualquier cambio en ellas, como ocurre al subir el sistema a producción. El uso de los helpers de generación de rutas (como Url.Action) te asegura que todo será consistente y correcto.

    Ahora vamos a por el tema del script independiente.

    Mis scripts de inicialización de jqGrid están siempre en la vista del grid. Quizás sea cuestión de gustos o de percepción, pero salvo que ese código vayas a utilizarlo en muchas otras vistas, no le veo ventaja a aislarlo en un .js independiente.

    Aún así, si tuviera que enviar este script a un archivo externo, no introduciría en él la constante con la ruta, ni siquiera constantes con los elementos del interfaz a utilizar (p.e., el id del grid, o del pager), sino se los suministraría desde la vista.

    Conceptualmente, en la vista incluiría algo como lo siguiente:

    var ruta = ‘<%= Url.Action("NombreDeAccion")'; inicializarGrid(ruta, "#grid", ...); Y en el archivo .js, function inicializarGrid(ruta, grid, ...) { $(grid).jqGrid({ ... url: ruta, }); } De esta forma mantienes las cosas en su sitio. Es la vista la que sabe el id de los elementos visuales, así como su contexto es capaz de generar rutas correctas a las acciones. Espero que ahora quede más claro mi punto de vista. Saludos.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *