martes, 26 de abril de 2011
Si a día de hoy hay algo fatalmente poco resuelto en ASP.NET MVC, es sin duda la localización. Aunque con un poco de paciencia se pueden poner en marcha sistemas completamente adaptados a distintos idiomas y culturas, la verdad es que se echa en falta una mayor consideración, entre otros, con los que osamos utilizar la coma para separar la parte entera de la decimal en un número.
Hace tiempo traté el tema por aquí, y aporté una solución para la versión 2 de ASP.NET MVC, que aún utilizaba las bibliotecas de scripting de Microsoft Ajax. Sin embargo, la versión 3 ha sustituido “de serie” esos componentes por jQuery Validate y el magnífico sistema de validaciones no intrusivas, por lo que todo lo dicho en aquella ocasión no vale ya para nada :-(
El problema radica en que el plugin jQuery Validate utiliza únicamente el punto como separador de decimales, por lo que la validación en cliente de valores de tipo decimal, float o double que utilicen la coma finalizará siempre en un error e impedirá el envío del formulario, como puede observarse en la captura de pantalla de la derecha.
Por cierto, antes de que se me olvide, hace unos meses reportaron este asunto como bug en Microsoft Connect. Si el tema os preocupa, podéis ir y votarlo a ver si conseguimos que este asunto se tenga en cuenta en próximas revisiones.
Sin embargo, estrictamente hablando, no se trata de un bug de ASP.NET MVC, puesto que la validación en cliente ha sido delegada por completo al plugin de jQuery, y éste es el que no tiene en cuenta los aspectos de internacionalización. Desde este punto de vista, quizás tendría más sentido, por tanto, esta issue reportada en Github sobre jQuery Validate, que propone su integración de forma nativa con jQuery Global.
Por tanto, me temo que se trata de un asunto de responsabilidad compartida (y dispersa, por tanto) entre los equipos de MVC, de jQuery Validate, y no sé si de alguno más. Esperemos que entre todos puedan solucionar de forma razonable el problema.
En cualquier caso, los que ya estamos creando aplicaciones con MVC 3 no podemos esperar las soluciones oficiales, que seguro llegarán más tarde o más temprano, y nos vemos obligados a buscar alternativas que nos permitan convivir con este problema de la forma más cómoda posible.
Y esto es lo que veremos en este post: varias posibilidades que tenemos para que la validación en cliente de valores decimales no nos compliquen demasiado la vida. Seguro que hay más, seguro que las hay mejores, pero ahí van unas cuantas opciones que nos pueden ayudar en escenarios como el descrito anteriormente.
Esto podemos conseguirlo de varias formas:
En el blog de Lenard Gunda podéis encontrar de forma muy detallada los cambios a realizar al archivo jquery.validate.js (o a su versión minimizada). Hay, sin embargo, un par de detalles que debemos tener en cuenta si optamos por esta solución:
El siguiente código sería una primera aproximación a la solución del problema. Como podéis observar, simplemente introducimos en
Si incluimos este script en la página cuando la cultura activa sea la nuestra (o cualquier otra que también utilice la coma para separar decimales), tendremos el problema solucionado.
Una fórmula más elegante y universal sería modificar la función
En fin, que como habréis comprobado existen mil y un enfoques posibles para enfrentarnos al problema. Espero que las ideas que hemos ido comentando os sean de utilidad para implementar vuestras propias soluciones hasta que tengamos una vía “oficial” para conseguirlo.
Publicado en: Variable not found.
Hace tiempo traté el tema por aquí, y aporté una solución para la versión 2 de ASP.NET MVC, que aún utilizaba las bibliotecas de scripting de Microsoft Ajax. Sin embargo, la versión 3 ha sustituido “de serie” esos componentes por jQuery Validate y el magnífico sistema de validaciones no intrusivas, por lo que todo lo dicho en aquella ocasión no vale ya para nada :-(
El problema radica en que el plugin jQuery Validate utiliza únicamente el punto como separador de decimales, por lo que la validación en cliente de valores de tipo decimal, float o double que utilicen la coma finalizará siempre en un error e impedirá el envío del formulario, como puede observarse en la captura de pantalla de la derecha.
Por cierto, antes de que se me olvide, hace unos meses reportaron este asunto como bug en Microsoft Connect. Si el tema os preocupa, podéis ir y votarlo a ver si conseguimos que este asunto se tenga en cuenta en próximas revisiones.
Sin embargo, estrictamente hablando, no se trata de un bug de ASP.NET MVC, puesto que la validación en cliente ha sido delegada por completo al plugin de jQuery, y éste es el que no tiene en cuenta los aspectos de internacionalización. Desde este punto de vista, quizás tendría más sentido, por tanto, esta issue reportada en Github sobre jQuery Validate, que propone su integración de forma nativa con jQuery Global.
Por tanto, me temo que se trata de un asunto de responsabilidad compartida (y dispersa, por tanto) entre los equipos de MVC, de jQuery Validate, y no sé si de alguno más. Esperemos que entre todos puedan solucionar de forma razonable el problema.
En cualquier caso, los que ya estamos creando aplicaciones con MVC 3 no podemos esperar las soluciones oficiales, que seguro llegarán más tarde o más temprano, y nos vemos obligados a buscar alternativas que nos permitan convivir con este problema de la forma más cómoda posible.
Y esto es lo que veremos en este post: varias posibilidades que tenemos para que la validación en cliente de valores decimales no nos compliquen demasiado la vida. Seguro que hay más, seguro que las hay mejores, pero ahí van unas cuantas opciones que nos pueden ayudar en escenarios como el descrito anteriormente.
1. Desactivar la validación en cliente
Está claro que el problema es en cliente, por lo que si desactivamos estas validaciones y dejamos que sea el servidor el que se encargue de comprobar que los valores de los distintos campos cumplen las restricciones impuestas por su tipo y las anotaciones de datos, ya no nos afectará más la absoluta indiferencia de jQuery Validate hacia las particularidades culturales.Esto podemos conseguirlo de varias formas:
- desactivar la validación en cliente de forma global, estableciendo a
false
la propiedadclientValidationEnabled
en el web.config, lo cual dejará a toda la aplicación sin validaciones en cliente. Como solución es algo drástica, pero poderse se puede. - desactivar la validación en cliente de forma local, sólo en aquellos formularios en los que existan propiedades de tipo decimal, introduciendo el siguiente código Razor (o su correspondiente en ASPX) antes de la llamada a
BeginForm()
:@{ Html.EnableClientValidation(false); }
- desactivar la validación en cliente sólo en el campo que nos interese, que podemos conseguir introduciendo el siguiente script, imaginando que el campo decimal en el que queremos anular la validación en cliente tiene como identificador “Altura”:
<script type="text/javascript"> $("#Altura").removeAttr("data-val"); </script>
2. Modificar jQuery Validate
Esta es una solución algo bestia que he encontrado por ahí, pero soluciona el problema de un plumazo: modificar el código de jQuery Validate para que acepte comas en lugar de puntos para separar los dígitos decimales de los enteros tanto en la validación numérica como en los rangos.En el blog de Lenard Gunda podéis encontrar de forma muy detallada los cambios a realizar al archivo jquery.validate.js (o a su versión minimizada). Hay, sin embargo, un par de detalles que debemos tener en cuenta si optamos por esta solución:
- primero, que nos estamos separando de la distribución oficial del plugin. Si actualizamos la biblioteca jquery.validate, por ejemplo utilizando Nuget, volveremos a tenerlo todo como al principio, y tendremos que volver a introducir los cambios oportunos.
- segundo, que esto no nos ayudará en aplicaciones adaptadas a varios idiomas; si modificamos el plugin para que acepte comas como separador, ya no volverá a aceptar el punto. Una solución rápida que se me ocurre para esto es tener dos versiones de la biblioteca (la original y la modificada), y referenciar desde la página la apropiada para la cultura actual.
3. Modificar la forma en que jQuery Validate parsea los decimales
Afortunadamente, el plugin de validación para jQuery es muy flexible, y permite introducir código personalizado para la validación de formato numérico y comprobación de rangos, lo que nos brinda la posibilidad de solucionar nuestro problema de forma muy limpia.El siguiente código sería una primera aproximación a la solución del problema. Como podéis observar, simplemente introducimos en
$.validator.methods.number
y $.validator.methods.range
las funciones que queremos utilizar para validar respectivamente los números y los rangos, reemplazando la coma por el punto antes de realizar la conversión con parseFloat()
:<script type="text/javascript">
$.validator.methods.number = function (value, element) {
value = floatValue(value);
return this.optional(element) || !isNaN(value);
}
$.validator.methods.range = function (value, element, param) {
value = floatValue(value);
return this.optional(element) || (value >= param[0] && value <= param[1]);
}
function floatValue(value) {
return parseFloat(value.replace(",", "."));
}
</script>
Si incluimos este script en la página cuando la cultura activa sea la nuestra (o cualquier otra que también utilice la coma para separar decimales), tendremos el problema solucionado.
Una fórmula más elegante y universal sería modificar la función
floatValue()
, y en lugar de reemplazar de forma manual los caracteres, utilizar el plugin Global para realizar la conversión a flotante según la cultura actual. Los detalles de esto, sin embargo, los dejo para otro post.En fin, que como habréis comprobado existen mil y un enfoques posibles para enfrentarnos al problema. Espero que las ideas que hemos ido comentando os sean de utilidad para implementar vuestras propias soluciones hasta que tengamos una vía “oficial” para conseguirlo.
Publicado en: Variable not found.
Publicado por José M. Aguilar a las 11:58 a. m.
Hay
15 comentarios, ¡participa tú también!
Etiquetas: asp.net, aspnetmvc, desarrollo, jquery, localizacion, trucos, validadores
lunes, 25 de abril de 2011
Vaya, tenía programado este post para que fuera publicado automáticamente hace unos días, pero algo habré hecho mal y se ha quedado en la recámara… bueno, pues más vale tarde que nunca O:-)
Como sabréis, hace poco ha finalizado la gira “Make Web Not War”, una serie de eventos organizados por Microsoft en cinco ciudades del país en los que se trataban distintos temas relacionados con el desarrollo para la web, y donde he tenido la oportunidad de participar como ponente, hablando sobre la última versión del framework ASP.NET MVC.
Aunque me ha tenido varias semanas fuera de juego laboral y blogosféricamente hablando (y lo que todavía tardaré en recuperar la normalidad…), he de decir que ha sido un experiencia realmente impresionante, de la que salgo con muy gratos recuerdos y un buen puñado de amigos con los que espero volver a coincidir en posteriores ocasiones.
A lo que iba, unos días atrás se han publicado los materiales y los vídeos de todas las ponencias del evento de Madrid, la última ciudad de la gira, y a los que podéis acceder desde los siguientes enlaces. En general, se trata de contenidos muy atractivos para los que trabajamos con la web, y seguro que vale la pena dedicar una tarde a que fenómenos como Martín, Jorge, Boris, Alex o Rafael nos cuenten cosas interesantes. Bueno, y si queréis conocer algo de MVC 3, pues también ;-)
Y por último, aprovechar para agradecer a la organización, a los chicos del equipo de evangelistas de Microsoft, y al resto de ponentes (inclusive Iván y Ángel, que no estuvieron en Madrid pero sí en otras ciudades) la confianza depositada y los buenos ratos que hemos pasado, paellas y chuletones de la tierra incluidos ;-)
Publicado en: Variable not found.
Como sabréis, hace poco ha finalizado la gira “Make Web Not War”, una serie de eventos organizados por Microsoft en cinco ciudades del país en los que se trataban distintos temas relacionados con el desarrollo para la web, y donde he tenido la oportunidad de participar como ponente, hablando sobre la última versión del framework ASP.NET MVC.
Aunque me ha tenido varias semanas fuera de juego laboral y blogosféricamente hablando (y lo que todavía tardaré en recuperar la normalidad…), he de decir que ha sido un experiencia realmente impresionante, de la que salgo con muy gratos recuerdos y un buen puñado de amigos con los que espero volver a coincidir en posteriores ocasiones.
A lo que iba, unos días atrás se han publicado los materiales y los vídeos de todas las ponencias del evento de Madrid, la última ciudad de la gira, y a los que podéis acceder desde los siguientes enlaces. En general, se trata de contenidos muy atractivos para los que trabajamos con la web, y seguro que vale la pena dedicar una tarde a que fenómenos como Martín, Jorge, Boris, Alex o Rafael nos cuenten cosas interesantes. Bueno, y si queréis conocer algo de MVC 3, pues también ;-)
Estándares Web W3C Martín Álvarez-Espinar (W3C) Descargar presentación Ver vídeo | Migrar a HTML 5 es fácil… si sabes cómo Jorge Casar (Frontend Spain) Descargar presentación Ver vídeo | ||
IE9 para desarrolladores web Boris Armenta (Microsoft) Descargar presentación Ver vídeo | Una web más interoperable Alejandro Hidalgo (Plain Concepts) Descargar presentación Ver vídeo | ||
El poder de los CMS Rafael Gerardo (Vector SF) Descargar presentación Ver vídeo | ASP.NET MVC3 José María Aguilar Descargar presentación Ver vídeo |
Publicado en: Variable not found.
domingo, 24 de abril de 2011
Estos son los enlaces publicados en Variable not found en Facebook y Twitter desde el lunes, 11 de abril de 2011 hasta el domingo, 24 de abril de 2011. Espero que te resulten interesantes. :-)
Publicado en: Variable not found
- Solucionar error al instalar helpers MVC de Facebook, por Lluis Franco
Fecha: 21/04/2011 - Lluis Franco: Sesiones del MIX categorizadas
Fecha: 15/04/2011 - Top 13 JavaScript Mistakes.
Fecha: 14/04/2011 - ASP.NET MVC 3 and EF4.1 Code First: Here are my classes, now you do the rest.
Fecha: 14/04/2011 - Gran lista de bibliotecas gratuitas para .net.
Fecha: 14/04/2011 - EF 4.1. version stamping, por Unai Zorrilla.
Fecha: 13/04/2011 - Phil Haack: Announcing ASP.NET MVC 3 Tools Update
Fecha: 13/04/2011 - Cartujadotnet: grupo de usuarios .net en Sevilla.
Fecha: 13/04/2011 - Ugo Lattanzi: ASP.NET MVC Tools update to support EF4.1, jQuery update and fixes
Fecha: 12/04/2011 - Nuget needs your input, by Phil Haack.
Fecha: 12/04/2011 - Using NonActionAttribute to restrict access to public methods of controller in ASP.NET MVC, by Gunnar Peipman.
Fecha: 12/04/2011 - Ado.net Entity Framework 4.1 RTM is out! Cool!
Fecha: 12/04/2011 - Cuadro de texto con autocompletado usando jQuery, Autocomplete y ASP.NET MVC, por luisruizpavon.
Fecha: 12/04/2011 - IE9ify, plugin de jQuery para pinear sitios, añadir tasks y jumplists en IE9, por Gonzalo Pérez
Fecha: 12/04/2011
Publicado en: Variable not found
martes, 12 de abril de 2011
Ya me parecía que el equipo de MVC llevaba mucho tiempo en silencio ;-). Acaba de publicarse una actualización para las herramientas de ASP.NET MVC 3 en la que se incluyen algunas novedades interesantes, y a las que ya he podido echar un vistazo. Os comento lo que he encontrado de momento en ellas.
El uso de esta nueva plantilla generará un proyecto prácticamente idéntico al habitualmente creado utilizando la plantilla “Aplicación de internet”, pero en lugar de utilizar el sistema de membresía de ASP.NET, utilizará autenticación Windows. Por tanto, ni rastro de controlador Account, ni de su Modelo, ni sus vistas; sólo encontraremos instrucciones para activar en IIS 7 e IIS Express este modelo de seguridad.
Por otra parte, marcando el nuevo checkbox podemos hacer que las vistas sean generadas utilizando marcado semántico HTML5. En la práctica, esto sólo implica que en el marcado del Layout encontraremos tags como
Los nuevos proyectos ASP.NET MVC vienen ya de serie con la versión 1.5.1, pero lo que es más interesante, es que ésta se incorpora en el proyecto como un paquete predescargado de Nuget. Por tanto, nada más abrir el proyecto recién creado, o en cualquier momento a partir de entonces, podemos utilizar Nuget para obtener las actualizaciones del mismo.
Lo mismo ocurre con jquery.Validation y con jQuery.UI. En ambos casos se ha incluido la versión 1.8, y de la misma forma, pueden ser actualizados a través de Nuget.
Eso sí, un detalle a tener en cuenta es que la inclusión de jquery desde nuestro código (el <script src..> que solemos encontrar en nuestro Layout o en algunas vistas) debemos modificarla de forma manual, puesto que el nombre de archivo incluye la versión específica, y Nuget no lo actualizará por nosotros.
Otra novedad al respecto es que se incluye de serie la biblioteca Modernizr, una interesante herramienta que nos facilita la detección de características de browsers, permitiéndonos el uso de tecnologías modernas como HTML5 o CSS3, mientras mantenemos la compatibilidad con navegadores anteriores.
Ahora, tras instalar esta actualización, tendremos a nuestra disposición una herramienta mucho más potente y compleja, que nos permite crear controladores, vistas, e incluso clases de contexto de datos para Entity Framework 4.1 (que se instala de serie en nuestros proyectos) con métodos básicos de acceso a datos.
Disponemos de tres opciones para crear un controlador: vacío, con acciones de edición vacías, y con vistas de lectura y edición usando Entity Framework.
Las dos primeras son equivalentes a lo que podíamos conseguir anteriormente, un controlador únicamente con la acción Index(), o con las acciones habituales CRUD, pero sin demasiado código en su interior.
La tercera opción, sin embargo, supone un gran avance respecto a las demás, puesto que permite, de un plumazo, generar todo el código que necesitamos para cubrir los habituales escenarios CRUD (consulta, altas, bajas, modificaciones y eliminación) basándose en el nuevo Entity Framework 4.1, que por cierto también acaba de salir del horno.
Obviamente, como es habitual, tendremos que retocar el código generado, pero como base no está nada mal la cantidad de trabajo que nos ahorra.
Por ejemplo, supongamos que creamos un proyecto MVC 3 vacío y añadimos a la carpeta Models una clase como la siguiente:
Como siempre, seleccionando la opción “Añadir controlador” sobre la carpeta Controllers del proyecto, podemos generar una clase controlador así:
Observad el desplegable donde se nos solicita la clase del contexto de datos. En ella podemos seleccionar el contexto de objetos (si usamos los tradicionales db-first o model-first de EF 4) o contexto de datos (usando code-first), desde donde se obtendrá la información. Además, si no existe, podemos incluso generar esta clase (para code-first) de forma automática desde este mismo punto.
A continuación, pulsando “Add”, se habrán generado automáticamente los siguientes elementos:
Bueno, y esto es todo de momento. Ya conforme vaya descubriendo más novedades o particularidades las iremos viendo por aquí.
Aquí tenéis el enlace para descargar la actualización de herramientas para MVC 3; en el mismo sitio encontraréis las notas de revisión, que describen los cambios introducidos.
Publicado en: Variable not found.
Novedades a primera vista
El primer pequeño cambio que notamos al instalar esta actualización, es que algunos de los cuadros de diálogo y nombres de plantillas que antes aparecían en español ahora aparecen de nuevo en inglés, como antes de instalar el paquete de idioma correspondiente. La plantilla de aplicaciones MVC 3 vuelve a llamarse “MVC 3 Web Application”, y los cuadros de diálogo vuelven su idioma original. Pero bueno, nada grave.Justo a continuación, ya creando el primer proyecto MVC 3, vemos que en el cuadro de diálogo inicial ha sido introducida una nueva plantilla llamada “Intranet Application”, y aparece un checkbox “use HTML5 semantic markup”.
El uso de esta nueva plantilla generará un proyecto prácticamente idéntico al habitualmente creado utilizando la plantilla “Aplicación de internet”, pero en lugar de utilizar el sistema de membresía de ASP.NET, utilizará autenticación Windows. Por tanto, ni rastro de controlador Account, ni de su Modelo, ni sus vistas; sólo encontraremos instrucciones para activar en IIS 7 e IIS Express este modelo de seguridad.
Por otra parte, marcando el nuevo checkbox podemos hacer que las vistas sean generadas utilizando marcado semántico HTML5. En la práctica, esto sólo implica que en el marcado del Layout encontraremos tags como
HEADER
, NAV
, SECTION
, o FOOTER
.Más scripts, y más actualizados
Si nos quejamos de la velocidad de los chicos de MVC a la hora de sacar releases, los de jQuery no se quedan nada atrás… incluso diría que los superan. Por ejemplo, la plantilla de ASP.NET MVC 3 incluía por defecto jQuery 1.4.4, y recientemente ha aparecido la 1.5.2… en tres meses, han aparecido al menos 4 revisiones.Los nuevos proyectos ASP.NET MVC vienen ya de serie con la versión 1.5.1, pero lo que es más interesante, es que ésta se incorpora en el proyecto como un paquete predescargado de Nuget. Por tanto, nada más abrir el proyecto recién creado, o en cualquier momento a partir de entonces, podemos utilizar Nuget para obtener las actualizaciones del mismo.
Lo mismo ocurre con jquery.Validation y con jQuery.UI. En ambos casos se ha incluido la versión 1.8, y de la misma forma, pueden ser actualizados a través de Nuget.
Eso sí, un detalle a tener en cuenta es que la inclusión de jquery desde nuestro código (el <script src..> que solemos encontrar en nuestro Layout o en algunas vistas) debemos modificarla de forma manual, puesto que el nombre de archivo incluye la versión específica, y Nuget no lo actualizará por nosotros.
Otra novedad al respecto es que se incluye de serie la biblioteca Modernizr, una interesante herramienta que nos facilita la detección de características de browsers, permitiéndonos el uso de tecnologías modernas como HTML5 o CSS3, mientras mantenemos la compatibilidad con navegadores anteriores.
Más andamiaje
El cuadro de diálogo de añadir controladores ha sido potenciado considerablemente. En este diálogo, hasta ahora sólo indicábamos el nombre del controlador y si queríamos generar código de acciones para las operaciones CRUD.Ahora, tras instalar esta actualización, tendremos a nuestra disposición una herramienta mucho más potente y compleja, que nos permite crear controladores, vistas, e incluso clases de contexto de datos para Entity Framework 4.1 (que se instala de serie en nuestros proyectos) con métodos básicos de acceso a datos.
Disponemos de tres opciones para crear un controlador: vacío, con acciones de edición vacías, y con vistas de lectura y edición usando Entity Framework.
Las dos primeras son equivalentes a lo que podíamos conseguir anteriormente, un controlador únicamente con la acción Index(), o con las acciones habituales CRUD, pero sin demasiado código en su interior.
La tercera opción, sin embargo, supone un gran avance respecto a las demás, puesto que permite, de un plumazo, generar todo el código que necesitamos para cubrir los habituales escenarios CRUD (consulta, altas, bajas, modificaciones y eliminación) basándose en el nuevo Entity Framework 4.1, que por cierto también acaba de salir del horno.
Obviamente, como es habitual, tendremos que retocar el código generado, pero como base no está nada mal la cantidad de trabajo que nos ahorra.
Por ejemplo, supongamos que creamos un proyecto MVC 3 vacío y añadimos a la carpeta Models una clase como la siguiente:
public class Persona
{
[Key]
public int IdPersona { get; set; }
[Required]
[StringLength(50)]
public string Nombre { get; set; }
[Required]
[StringLength(50)]
public string Apellidos { get; set; }
public DateTime FechaNacimiento { get; set; }
}
Como siempre, seleccionando la opción “Añadir controlador” sobre la carpeta Controllers del proyecto, podemos generar una clase controlador así:
Observad el desplegable donde se nos solicita la clase del contexto de datos. En ella podemos seleccionar el contexto de objetos (si usamos los tradicionales db-first o model-first de EF 4) o contexto de datos (usando code-first), desde donde se obtendrá la información. Además, si no existe, podemos incluso generar esta clase (para code-first) de forma automática desde este mismo punto.
A continuación, pulsando “Add”, se habrán generado automáticamente los siguientes elementos:
- la clase PersonasController, dentro de la carpeta correspondiente, en cuyo interior encontraremos la implementación completa de las acciones Index, Details, Create, Edit y Delete,
- vistas para cada una de las acciones anteriores, que tienen en cuenta algunas características definidas en el modelo de datos, como las anotaciones o relaciones entre entidades.
Bueno, y esto es todo de momento. Ya conforme vaya descubriendo más novedades o particularidades las iremos viendo por aquí.
Aquí tenéis el enlace para descargar la actualización de herramientas para MVC 3; en el mismo sitio encontraréis las notas de revisión, que describen los cambios introducidos.
Publicado en: Variable not found.
La ruta por defecto de ASP.NET MVC es válida para la gran mayoría de escenarios simples, permitiéndonos acceder a las acciones a través de URLs del tipo
… podríamos acceder a ellas utilizando direcciones tan naturales como /InformacionCorporativa/QuienesSomos, o /InformacionCorporativa/MisionVisionYValores. Sin duda, un gran avance vistas a ofrecer a nuestros usuarios un esquema de rutas limpio, intuitivo, y de paso, mejorar nuestro posicionamiento.
Sin embargo, ¿no os parece que sería mejor aún poder acceder a acciones y controladores utilizando guiones para separar los distintos términos? Me refiero a poder utilizar, por ejemplo, la URL /Informacion-corporativa/Quienes-Somos, o /Informacion-corporativa/Unete-a-nuestro-equipo.
Obviamente no podemos modificar el nombre de nuestros controladores y acciones, puesto que nuestros lenguajes de programación no permiten el uso de guiones en el nombre de los identificadores.
Ante este escenario, una posibilidad sería asignar mediante el atributo
Afortunadamente, existen en el framework bastantes puntos de extensión donde podemos “enganchar” nuestra propia lógica al proceso de las peticiones, y emplearlos para conseguir solucionar de forma global problemas como este. Y uno de ellos es el sistema de routing.
Dado que el guión bajo es perfectamente válido en los nombre de clases y métodos, sólo tendremos que introducir en ellos este carácter en el lugar donde queremos que aparezcan los guiones, y dejar que el sistema de rutado se encargue de realizar la transformación de forma automática. Y, por supuesto, realizaremos esta transformación en sentido bidireccional, es decir, tanto cuando se analiza la URL para determinar el controlador y acción a ejecutar, como cuando se genera la dirección a partir de los parámetros de ruta.
Del código anterior, destacar algunos aspectos:
Observad que una de las ventajas de utilizar esta técnica es que a nivel de código utilizaremos siempre el nombre real de los controladores y acciones (con el guión bajo), es el routing el que realizará las transformaciones. Esto, entre otros beneficios, nos permite seguir utilizando el imprescindible T4MVC para evitar las “magic strings” en nuestro código.
De esta forma, ahora bastaría con referenciar desde el global.asax el espacio de nombres donde hemos definido la clase anterior y ya podemos llenar la tabla de rutas utilizando sentencias como la siguiente:
Así, una vez introducida la ruta anterior en lugar de la que viene por defecto en proyectos ASP.NET MVC, ya nuestro sistema podrá recibir una petición como
Por si os interesa, he dejado código y demo en SkyDrive.
Publicado en: Variable not found.
http://{servidor:puerto}/{controlador}/{accion}Así, dada una clase controlador con acciones como las siguientes:
public class InformacionCorporativaController : Controller
{
public ActionResult QuienesSomos()
{
return View();
}
public ActionResult MisionVisionYValores()
{
return View();
}
public ActionResult UneteANuestroEquipo()
{
return View();
}
}
… podríamos acceder a ellas utilizando direcciones tan naturales como /InformacionCorporativa/QuienesSomos, o /InformacionCorporativa/MisionVisionYValores. Sin duda, un gran avance vistas a ofrecer a nuestros usuarios un esquema de rutas limpio, intuitivo, y de paso, mejorar nuestro posicionamiento.
Sin embargo, ¿no os parece que sería mejor aún poder acceder a acciones y controladores utilizando guiones para separar los distintos términos? Me refiero a poder utilizar, por ejemplo, la URL /Informacion-corporativa/Quienes-Somos, o /Informacion-corporativa/Unete-a-nuestro-equipo.
Obviamente no podemos modificar el nombre de nuestros controladores y acciones, puesto que nuestros lenguajes de programación no permiten el uso de guiones en el nombre de los identificadores.
Ante este escenario, una posibilidad sería asignar mediante el atributo
[ActionName]
un nombre alternativo a cada una de estas acciones. Sin embargo, además del trabajo que esto implica, no habría una forma sencilla de conseguirlo también para los nombres de las clases controlador. Otra opción sería registrar en la tabla de rutas una entrada específica para cada una de las acciones. Aunque no tiene contraindicaciones y cubriría perfectamente nuestras necesidades, uuffff… sin duda es demasiado trabajo a estas alturas.Afortunadamente, existen en el framework bastantes puntos de extensión donde podemos “enganchar” nuestra propia lógica al proceso de las peticiones, y emplearlos para conseguir solucionar de forma global problemas como este. Y uno de ellos es el sistema de routing.
1. ¡Convenciones al poder!
A continuación vamos a ver cómo conseguirlo de forma global utilizando el sistema de routing, y basándonos en una convención muy simple que vamos a establecer: los identificadores de controladores y acciones que contengan un guión bajo (“_”) serán convertidos a nivel de rutas en guiones.Dado que el guión bajo es perfectamente válido en los nombre de clases y métodos, sólo tendremos que introducir en ellos este carácter en el lugar donde queremos que aparezcan los guiones, y dejar que el sistema de rutado se encargue de realizar la transformación de forma automática. Y, por supuesto, realizaremos esta transformación en sentido bidireccional, es decir, tanto cuando se analiza la URL para determinar el controlador y acción a ejecutar, como cuando se genera la dirección a partir de los parámetros de ruta.
2. La clase FriendlyRoute
A continuación, vamos a crear una nueva clase, a la que llamaremosFriendlyRoute
, y que dotaremos de la lógica de transformación de guiones medios en guiones bajos, y viceversa. Nada que no podamos resolver en una escasa veintena de líneas de código:public class FriendlyRoute : Route
{
public FriendlyRoute(string url, object defaults) :
base(url, new RouteValueDictionary(defaults), new MvcRouteHandler()) { }
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var routeData = base.GetRouteData(httpContext);
RouteValueDictionary values = routeData.Values;
values["controller"] = (values["controller"] as string).Replace("-", "_");
values["action"] = (values["action"] as string).Replace("-", "_");
return routeData;
}
public override VirtualPathData GetVirtualPath(RequestContext ctx, RouteValueDictionary values)
{
values["controller"] = (values["controller"] as string).Replace("_", "-").ToLower();
values["action"] = (values["action"] as string).Replace("_", "-").ToLower();
return base.GetVirtualPath(ctx, values);
}
}
Del código anterior, destacar algunos aspectos:
- sólo he creado un constructor, he de decirlo, por pura pereza. En realidad, si quisiéramos cubrir más casuística, como la introducción de restricciones o de espacios de nombre que sí permiten las distintas sobrecargas de la clase
Route
, deberíamos crear todas ellas para nuestra clase. Pero vaya, es trivial en cualquier caso. - el método
GetRouteData()
es utilizado por el framework para obtener los datos de ruta de una petición entrante. Como puede observarse en el código anterior, simplemente ejecutamos la lógica de la clase base, y aplicamos las oportunas transformaciones (de guiones medios a bajos). - el método
GetVirtualPath()
es utilizado para la transformación inversa, es decir, para generar una URL partiendo de valores de los parámetros de ruta. En este caso, primero retocamos ligeramente los valores del nombre de controlador y acción, transformando los guiones bajos en medios y pasándolos a minúsculas, y posteriormente invocamos a la lógica de la clase base para que genere la URL por nosotros.
routes.Add("default",
new FriendlyRoute(
"{controller}/{action}/{id}", // URL con parámetros
new { controller = "inicio", action = "portada_principal", id = UrlParameter.Optional }
)
);
Observad que una de las ventajas de utilizar esta técnica es que a nivel de código utilizaremos siempre el nombre real de los controladores y acciones (con el guión bajo), es el routing el que realizará las transformaciones. Esto, entre otros beneficios, nos permite seguir utilizando el imprescindible T4MVC para evitar las “magic strings” en nuestro código.
3. Pero es queeee… yo estoy acostumbrado a usar routes.MapRoute()… O:-)
No pasa nada, también podemos ponértelo así de fácil. Los métodosMapRoute()
que solemos usar en el método RegisterRoutes
del global.asax no son más que extensores de la clase RouteCollection
, por lo que podemos basarnos en esta misma idea y crear extensiones personalizadas que nos pongan más a mano el mapeo de nuestras amigables rutas:public static class RouteCollectionExtensions
{
public static Route MapFriendlyRoute(this RouteCollection routes, string name, string url, object defaults)
{
var route = new FriendlyRoute(url, defaults);
routes.Add(name, route);
return route;
}
}
De esta forma, ahora bastaría con referenciar desde el global.asax el espacio de nombres donde hemos definido la clase anterior y ya podemos llenar la tabla de rutas utilizando sentencias como la siguiente:
routes.MapFriendlyRoute(
"Default", // Nombre de ruta
"{controller}/{action}/{id}", // URL con parámetros
new { controller = "inicio", action = "portada_principal", id = UrlParameter.Optional }
);
Así, una vez introducida la ruta anterior en lugar de la que viene por defecto en proyectos ASP.NET MVC, ya nuestro sistema podrá recibir una petición como
GET /Nombre-Controlador/Nombre-Accion
y mapearla hacia a la acción Nombre_Accion
de la clase controlador Nombre_ControladorController
. Por si os interesa, he dejado código y demo en SkyDrive.
Publicado en: Variable not found.
domingo, 10 de abril de 2011
Bien, pues tras el parón de la gira Make Web Not War, volvemos a la carga con los enlaces que he ido recopilando durante este tiempo en Variable not found en Facebook y Twitter.
Publicado en: Variable not found
- Ya están las fotos de los #eswebcamp de Barcelona, Valencia, Bilbao, Sevilla y Madrid publicadas
Fecha: 07/04/2011 - Eduard Tomás: ¡Mis primeros artículos en desarrolloweb! Se avecina un gran tutorial de ASP.NET MVC: http://kcy.me/2l2b y http://kcy.me/2l2c
Fecha: 06/04/2011 - David Ebbo: Blogged: Open your solution files as admin
Fecha: 04/04/2011 - Eduard Tomàs: [BlogPost] Como usar el pathInfo para pasar parámetros en ASP.NET MVC
Fecha: 04/04/2011 - Josué Yeray Julián: ¿Tienes Windows Phone 7? ¿Te gusta Geeks.ms? No te pierdas la aplicación que hemos preparado para ti!!
Fecha: 04/04/2011 - Lanzado jQuery 1.5.2.
Fecha: 01/04/2011 - El gran Phil Haack responde a una de las consultas del #eswebcamp de ayer: cómo crear tu propia galería Nuget.
Fecha: 01/04/2011 - "Javascript for c# developers", gran serie de posts de JMBucknall.
Fecha: 01/04/2011 - Phil Haack: Alright, NuGet 1.2 released! :) And check out the updated NuGet.exe and Package Explorer! :)
Fecha: 31/03/2011 - Libro gratuito de jQuery en español: Fundamentos de jQuery.
Fecha: 31/03/2011 - Scaffolding Actions and Unit Tests with MvcScaffolding.
Fecha: 30/03/2011 - Rounding corners using CSS3.
Fecha: 30/03/2011 - Jorge Serrano: Patrón Observador en .NET - pattern Observer
Fecha: 30/03/2011 - Eduard Tomàs: TIP: Javascript Module Pattern (mantén organizado tu código javascript).
Fecha: 30/03/2011 - Wow!! RT Josué Yeray Julián: Ya está disponible el 1º capítulo de mi libro sobre #wp7 gratis y de libre descarga
Fecha: 27/03/2011 - When should a method be a property?
Fecha: 25/03/2011 - Convention based localization with ASP.NET MVC.
Fecha: 25/03/2011 - Building an ASP.NET MVC 3 app with code first and EF 4.1.
Fecha: 25/03/2011 - Scaling a #javaScript codebase
Fecha: 20/03/2011 - Rumores: algunas características de ASP.NET MVC que quizás pasen a la próxima versión de Webforms.
Fecha: 20/03/2011 - Phil Haack: How model binding to decimals in ASP.NET MVC is broken and how to fix it using a custom model binder! :)
Fecha: 19/03/2011 - José Manuel Alarcón: En mi blog técnico: "Cómo crear URLs amigables personalizadas con ASP.NET Web Forms"
Fecha: 18/03/2011 - Ugo Lattanzi: The Big View Engine Comparison – Razor vs. Spark vs. NHaml vs. Web Forms View Engine
Fecha: 16/03/2011 - Gisela Torres: Refrescar un WebGrid cada X tiempo de forma asíncrona
Fecha: 16/03/2011 - Brutal!!! Eduard Tomàs: Previsualizar imágenes subidas en ASP.NET MVC sin guardarlas en servidor. No es ajax.
Fecha: 15/03/2011 - Gran post! Eduard Tomàs: [BlogPost] Previsualización de imágenes en ASP.NET MVC. Primer post (sin usar ajax).
Fecha: 15/03/2011
Publicado en: Variable not found