Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

17 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
Mostrando entradas con la etiqueta jquery. Mostrar todas las entradas
Mostrando entradas con la etiqueta jquery. Mostrar todas las entradas
lunes, 12 de octubre de 2009

Mientras esperamos impacientes la llegada de ASP.NET MVC 2 con su flamante sistema integrado de validación de datos en cliente y servidor, xVal puede sernos de bastante utilidad al ofrecernos prácticamente las mismas funciones previstas para la versión 2, y alguna más :-)

xVal es un framework para aplicaciones ASP.NET MVC 1.0 (y superiores) creado por Steve Sanderson, y presentado en sociedad el pasado 17 de septiembre, que permite validar la información almacenada en clases del modelo, tanto en el lado cliente como en servidor, de forma automatizada.

Su diseño es muy flexible, permitiéndonos elegir entre distintos marcos de trabajo para la validación en servidor (de serie soporta los atributos DataAnnotations, Castle Validator y NHibernate Validator, aunque se pueden crear proveedores personalizados) y librerías en cliente (inicialmente utiliza el magnífico plugin jQuery Validation).

Vamos a ver, paso a paso, cómo podemos comenzar a utilizarlo de forma inmediata en nuestras aplicaciones ASP.NET MVC 1.0, utilizando las restricciones DataAnnotations y la librería de validación para jQuery citada anteriormente.

1. Preparamos la infraestructura

En primer lugar, vamos a preparar el entorno para utilizar el framework de validación:


  1. Descargamos xVal desde CodePlex. Se distribuye en un fichero .zip que incluye tanto el ensamblado como archivos de soporte, así que lo descomprimimos en cualquier parte para tener los archivos a mano.

  2. Descargamos el plugin de validación de jQuery, por ejemplo, desde el CDN de Microsoft (¿qué es el Microsoft Ajax CDN?) y lo incluimos en la carpeta /scripts de nuestro proyecto. Otra posibilidad sería no descargarlo y referenciarlo directamente nuestras páginas, a gusto del consumidor ;-)

  3. Añadimos a la carpeta /scripts del proyecto la librería xVal.jQuery.Validate.js presente en el raíz del comprimido de xVal. Este archivo, junto con el anterior, son imprescindibles para montar la validación automática en el lado cliente que veremos más adelante. Además, para que los mensajes aparezcan en nuestro idioma, copiamos también al mismo sitio el archivo xVal.Messages.es-ES.js, disponible en la carpeta “internationalization” del zip.

  4. Copiamos al directorio /bin de nuestra aplicación el ensamblado xVal.dll, o simplemente añadimos una referencia en el proyecto hacia dicho archivo, que encontraréis en el raíz del fichero comprimido que hemos descargado en primer lugar.

  5. Retocamos ligeramente el Web.config de nuestro proyecto para que sea incluido automáticamente el espacio de nombres xVal.Html en nuestras vistas, facilitando así el acceso a los helpers suministrados:

    <system.web>
      <pages>
         <namespaces>
            <!-- Añadir la siguiente línea -->
            <add namespace="xVal.Html"/>
        </namespaces>
      </pages>
    </system.web>

Los pasos comentados hasta el momento son genéricos, es decir, tendremos que realizarlos en todos los proyectos en los que vayamos a utilizar este framework de validación. Podría ser interesante, por tanto, crearnos una plantilla de proyecto en la que tengamos ya todo este trabajo realizado.

Diálogo 2. Definimos las restricciones con Data Annotations

Ahora vamos a definir, de forma declarativa, las restricciones que queremos imponer a las propiedades de las clases del modelo, utilizando los atributos denominado data annotations, distribuidos con .NET 3.5 y originalmente diseñados para trabajar con la tecnología Dynamic Data.


  1. Dado que vamos a declarar las restricciones utilizando los atributos data annotations, hay que añadir referencia en el proyecto a  System.ComponentModel.DataAnnotations.

  2. A continuación, tenemos que incluir en el proyecto un método que nos permita recorrer las anotaciones de las clases, ejecutarlas e ir generando los errores apropiadamente.  Este método lo utilizaremos más adelante, desde los componentes del Modelo, para comprobar si los valores presentes en las propiedades cumplen los requisitos impuestos por el dominio del sistema.

    El código es muy sencillo, el propio Sanderson nos facilita uno en el proyecto de demostración de xVal, que podéis copiar y pegar:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using xVal.ServerSide;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel;
     
    namespace MyProject.Validation
    {
     public static class DataAnnotationsValidationRunner
     {
      public static IEnumerable<ErrorInfo> GetErrors(object instance)
      {
        var metadataAttrib = instance.GetType()
                                .GetCustomAttributes(typeof(MetadataTypeAttribute), true)
                                .OfType<MetadataTypeAttribute>().FirstOrDefault();
     
        var buddyClassOrModelClass = metadataAttrib != null ? 
                                        metadataAttrib.MetadataClassType:
                                        instance.GetType();
     
        var buddyClassProperties = TypeDescriptor.GetProperties(buddyClassOrModelClass)
                                .Cast<PropertyDescriptor>();
     
        var modelClassProperties = TypeDescriptor.GetProperties(instance.GetType())
                                .Cast<PropertyDescriptor>();
     
        return from buddyProp in buddyClassProperties
                   join modelProp in modelClassProperties on buddyProp.Name equals modelProp.Name
                   from attribute in buddyProp.Attributes.OfType<ValidationAttribute>()
                   where !attribute.IsValid(modelProp.GetValue(instance))
                   select new ErrorInfo(
                                buddyProp.Name, 
                                attribute.FormatErrorMessage(string.Empty), instance);
      }
     }
    }

    Ojo, esto sólo tenemos que hacerlo cuando estemos utilizando DataAnnotations, como es el caso; si utilizamos otros frameworks como el de Castle o NHibernate no será necesario, puesto que incluyen ya implementaciones para realizar esta tarea.


  3. Marcamos las propiedades de la entidad del modelo con las restricciones a aplicar durante la validación. Podemos utilizar los atributos disponibles para restringir los valores permitidos en cada propiedad como Required , StringLength , Range  y otros (puedes ver la relación completa aquí).

    Un ejemplo podría ser el siguiente, en el que vemos varias restricciones aplicadas a las propiedades de la entidad:

    public class Recluta
    {
        [Required, StringLength(30)]
        public string Nombre { get; set; }
     
        [Required, StringLength(40)]
        public string Apellidos { get; set; }
     
        [Required, Range(1, 4)]
        public int Talla { get; set; }
     
        [Required, DataType(DataType.Date)]
        public DateTime FechaNacimiento { get; set; }
    }

    Sin embargo, muchos os preguntaréis qué ocurre cuando estas entidades de datos las generamos con herramientas automáticas, como el diseñador de Entity Framework. En estos casos, cada vez que generemos el modelo, las clases serían machacadas por las nuevas versiones, y nuestras anotaciones pasarían a mejor vida.

    Afortunadamente, existe la posibilidad de declarar una clase paralela (o, como la llaman, ‘buddy class’), en la que definiremos exclusivamente las propiedades a las que queremos añadir alguna anotación. Además, marcaremos la entidad original (aprovechando que la mayoría de estas herramientas automáticas las generan como parciales) indicando la clase que contiene los metadatos asociados a ésta:

    // Indicamos en la entidad original que los
    // metadatos se encuentran en 'ReclutaMedata'
    [MetadataType(typeof(ReclutaMetadata))]
    public partial class Recluta
    { 
        // Nada más que añadir aquí
    }
     
    // Definimos los metadatos para la entidad 'Recluta'
    public class ReclutaMetadata
    {
        [Required, StringLength(30)]
        public string Nombre { get; set; }
     
        [Required, StringLength(40)]
        public string Apellidos { get; set; }
     
        [Required, Range(1, 4)]
        public int Talla { get; set; }
     
        [Required, DataType(DataType.Date)]
        public DateTime FechaNacimiento { get; set; }
    }

    Como podéis observar, la entidad y la clase de metadatos son prácticamente iguales. Un poco anti-DRY sí que es, pero bueno.

3. Validamos en servidor

La propuesta de xVal para el lado del servidor consiste en desplazar la lógica de validación al modelo, dado que es éste el que normalmente impone las restricciones en los datos que han de estar presentes en las entidades del dominio. Una forma de realizarlo sería así:

  • por cada entidad, creamos un método que valide la información del mismo, primero invocando al ValidationRunner (el proceso de validación basado en anotaciones descrito anteriormente), y luego añadiendo aquellas reglas de negocio no incluidas en dichas anotaciones). Un ejemplo podría ser el siguiente:

    private void validar(Recluta recluta)
    {
        var errors = DataAnnotationsValidationRunner.GetErrors(recluta);
        if (errors.Any())
            throw new RulesException(errors);
     
        // Regla de negocio adicional: prohibido alistarse reclutas
        // con hermanos en el cuartel...
        if (tieneHermanos(recluta.Apellidos))
        {
            throw new RulesException("Apellidos",
                        "El recluta tiene hermanos ya alistados", recluta);
        }
    }
     
    Este método podría incluirse en la propia entidad Recluta, o bien donde se implemente la lógica de negocio asociada a la misma.
     
    En cualquier caso, como se puede observar, cuando se producen errores debido a un incumplimiento de las restricciones indicadas en las anotaciones, se lanza una excepción de tipo RulesException (facilitada por xVal) que contiene una descripción de los problemas encontrados. Asimismo, la existencia de otro tipo de problemas, hallados de forma programática, son lanzados también en una excepción del mismo tipo.
     

  • antes de realizar operaciones susceptibles de modificar el estado del sistema, tenemos que asegurarnos de que las entidades son válidas. Observad, por ejemplo, la implementación del método que nos permite añadir un recluta al sistema:

    public void Crear(Recluta recluta)
    {
        validar(recluta);
        reclutas.Add(recluta);
    }

    Si se producen errores en la validación, el método Crear() será interrumpido por la excepción RulesException lanzada desde validar(), y llegará finalmente hasta el Controlador, donde deberá ser procesada. 

  • desde el punto de vista del Controlador, podremos comprobar que el patrón a seguir es realmente sencillo, pues toda la lógica de validación la hemos desplazado al modelo.

    El siguiente código muestra los métodos de acción asociados a la creación de una entidad; el primero de ellos simplemente se encarga de mostrar la vista de edición sobre un objeto recién creado, mientras que el segundo obtiene los datos del recluta desde el formulario, e intenta realizar la operación de creación sobre el modelo:

    public ActionResult Create()
    {
        return View(new Recluta());
    }
     
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Create(Recluta recluta)
    {
        try
        {
            gestorDeReclutas.Crear(recluta);
        }
        catch (RulesException ex)
        {
            ex.AddModelStateErrors(this.ModelState, "");
        }
        if (!ModelState.IsValid)
            return View(recluta);
        else 
            return RedirectToAction("Index");
    }

    Como se puede observar, se capturan las excepciones de validación que se produzcan al realizar el alta, añadiendo al ModelState los errores que se estén informando en éstas y, en función de la validez de los datos, enviando al usuario a la vista correspondiente.
Y esto es todo. Con estas operaciones, ya tenemos las validaciones listas en el lado del servidor, pasemos ahora a solucionarlas en cliente.

4. Validamos en el cliente

Está claro que la validación en el lado del servidor es la que única que debemos hacer obligatoriamente; el lado cliente es sensible al equipo del usuario, que puede estar accediendo desde dispositivos sin javascript (o con esta característica desactivada), o incluso puede ser fácilmente manipulado, por lo que no podemos confiar en que los datos lleguen ya siendo válidos.

Sin embargo, ofrecer validación en cliente es una característica imprescindible hoy en día vistas a realizar interfaces muy usables, capaces de ofrecer al usuario feedback inmediato sobre sus acciones.

Con xVal, añadir en este punto validaciones en cliente es realmente sencillo, pues ya tenemos realizado prácticamente todo el trabajo, quedando simplemente:

  1. incluir las librerías script en las vistas donde vayamos a realizar la edición de las entidades del modelo. Si vamos a utilizarlas en muchos sitios, lo más fácil es añadirlas a la página maestra:

    <script src="../../Scripts/jquery-1.3.2.min.js" type="text/javascript"></script>
    <script src="../../Scripts/jquery.validate.min.js" type="text/javascript"></script>
    <script src="../../Scripts/xVal.jquery.validate.js" type="text/javascript"></script>
    <script src="../../Scripts/xVal.Messages.es-ES.js" type="text/javascript"></script>


  2. generar en la vista los scripts de validación de las entidades que nos interesen. En el siguiente código generamos la lógica para la entidad Recluta:
     
    <%= Html.ClientSideValidation<MiProyecto.Models.Recluta>() %>
        

5. ¡Y hasta aquí hemos llegado!

A lo largo de este post hemos recorrido los pasos necesarios para echar a andar el framework xVal en una aplicación ASP.NET MVC 1.0.

Faltan muchos aspectos por comentar, como la posibilidad de utilizar validaciones Ajax en servidor, permitir la localización en decimales, escribir nuestros propios atributos de anotaciones, etc., pero creo que este post ya es lo suficientemente extenso… ya lo veremos en otra ocasión.

Puedes descargar el proyecto de demostración desde Skydrive:

Publicado en: Variable not found.

miércoles, 20 de mayo de 2009

jQueryEl gran K. Scott Allen comentaba hace unas semanas en OdeToCode un pequeño truco que puede resultar de utilidad cuando tengamos un código jQuery que no funcione correctamente.

Como comenta el autor, la mayoría de los problemas con jQuery se deben a un uso incorrecto de los potentes selectores, así que lo que propone es el uso de la consola javascript incluida en algunas herramientas como Firebug (para Firefox) o las propias herramientas de desarrollo incluidas en Internet Explorer 8 (geniales, por cierto).

Consola en FirebugEsta consola permite en ambos casos introducir instrucciones javascript de forma directa, que serán ejecutadas en el contexto de la página actual como si formaran parte del código de las mismas. Por tanto, en aquellas páginas en las que se incluido jQuery, será posible ejecutar llamadas y selecciones a lo largo del DOM y observar el resultado de forma interactiva.

En la imagen adjunta se ve cómo podemos ir realizando consultas con selectores e ir observando sus resultados con Firebug. Hay que tener en cuenta que la mayoría de operaciones de selección con jQuery retornan una colección con los elementos encontrados, por eso podemos utilizar length para obtener el número de coincidencias. Pero no sólo eso, podríamos utilizar expresiones como la siguiente para mostrar por consola el texto contenido en las etiquetas que cumplan el criterio:

$("div > a").each(function() { console.log($(this).text()) })

Y más aún, si lo que queremos es obtener una representación visual sobre la propia página, podemos alterar los elementos o destacarlos con cualquiera de los métodos de manipulación disponibles en jQuery, por ejemplo:

$("a:contains['sex']").css("background-color", "yellow")

La siguiente captura muestra el resultado de una consulta realizada con las herramientas de desarrollo incluidas en Internet Explorer 8: Consola en IE8


En fin, un pequeño truco para facilitarnos un poco la vida.


Fuente: What I Do When My jQuery Code Doesn’t Work

domingo, 5 de abril de 2009
Una cascada

He actualizado a la versión 1.0 de ASP.NET MVC framework el ejemplo de Helper para crear desplegables enlazados (cascading dropdowns) con jQuery que escribí unos meses atrás.

El contenido del post sigue siendo válido, sólo ha sido necesario retocar algunos detallitos en el código debido a los cambios introducidos en el framework desde la versión Beta.

Descargar proyecto (comprimido en .zip)

Requisitos:

Publicado en: www.variablenotfound.com.

domingo, 14 de diciembre de 2008
Editado [Abril/2009]: el proyecto está actualizado para la versión 1.0 de ASP.NET MVC Framework.

Una cascadaUna de las bases de la reutilización de código y mejora de productividad en el desarrollo de vistas ASP.NET MVC son los helpers, pequeños (o no tan pequeños) métodos de extensión de clases accesibles desde la página que nos permiten generar de forma automática código de uso común de marcado, maquetación o scripting, como XHTML, CSS y javascript.

ASP.NET MVC viene de fábrica con un buen conjunto de helpers, como los que podemos encontrar en el espacio de nombres System.Web.Mvc.Html, que nos facilitan la creación de elementos de la página y la introducción de ciertos automatismos. Por ejemplo, si en lugar de escribir en la Vista el código XHTML correspondiente a un cuadro de edición realizamos una invocación del helper, así: <%= Html.TextBox("name") %>, estaremos generando la etiqueta de forma totalmente correcta, y cargando el valor por defecto si en el ViewData existe una entrada con dicho nombre.

Sin embargo, es obvio que los helpers suministrados no cubren todo lo que vamos a requerir para desarrollar de forma productiva aplicaciones basadas ASP.NET MVC, ni siquiera una pequeña parte, por lo que lo lógico es que terminemos desarrollando nuestras propias funciones a base de generalizar las soluciones a problemas y distintos escenarios con los que nos vayamos encontrando.

Desde hace tiempo tenía interés por crear un helper medianamente complejo para ver los problemas con los que podía encontrarme... y no hay nada como un fin de semana climatológicamente desapacible para dedicarse a estos menesteres.

El resultado ha sido LinkDropDownLists, un helper para el framework ASP.NET MVC 1.0 (abril 2009), cuya función es enlazar de forma muy sencilla dos o más desplegables, recargando mediante Ajax (gracias a jQuery) los contenidos cuando alguno de ellos cambie. En otras palabras, se trata de un sistema de desplegables en cascada como el que describí hace unos meses en "Desplegables en cascada con ASP.NET MVC y jQuery", pero en formato helper, muy flexible y cómodo de utilizar, y adaptado a la versión disponible del framework.

Introducción

LinkDropDownLists es un método de extensión de la clase AjaxHelper, que nos permite "encadenar" entre sí un conjunto de desplegables, de forma que el cambio de valor de uno de ellos provoque, en cascada, la recarga del resto siguiendo el orden en el que han sido vinculados.

La recarga se realizará obteniendo los datos mediante una petición Ajax con jQuery a una acción del controlador desde el que se ha generado la Vista, que retornará los elementos en formato JSON, y serán introducidos automáticamente en el desplegable correspondiente.

Ampliar
El método LinkDropDownLists lo utilizaremos en la Vista para generar los scripts necesarios para realizar de forma automática la comunicación con el servidor cada vez que cambie un desplegable; la recepción de la llamada Ajax, por otra parte, requerirá una acción en el Controlador, que será la responsable de obtener la información desde el Modelo y retornarlos a la vista para materializarlos como elementos de los controles visuales.

La Vista

Para utilizar el helper, antes de nada hay que asegurarse de que jQuery está incluido en la vista o su página maestra. Dado que MVC framework desde su versión Beta 1 incluye esta librería en las plantillas por defecto, sólo es necesario referenciarla desde el código HTML, por ejemplo:
 <script src="/scripts/jquery-1.2.6.js" 
type="text/javascript"></script>
 
A partir de este momento, podremos utilizar sin problema el helper de la forma que se describe a continuación, siempre que haya sido incluido el espacio de nombres donde fue definido, por ejemplo usando la directiva de página Import Namespace="Jma.Mvc.jQuery.Extensions", o en la sección <namespaces> del archivo Web.config.

Dado que tanto las vistas que heredan de ViewPage o ViewPage<T> (en la práctica, todas) como los controles ViewUserControl, disponen de una propiedad de tipo AjaxHelper llamada Ajax, podremos invocar los métodos de extensión de dicho tipo desde el código ASPX o ASCX de forma muy sencilla:
<%= Ajax.LinkDropDownLists(...)%>
 
Vamos a mostrar algunos ejemplos de uso del helper LinkDropDownLists, imaginando un formulario en el que existe un desplegable llamado "Pais" (es decir, un <select id="Pais">), otro llamado "Provincia" y un último llamado "Ciudad", tales que un cambio en el primero debería forzar una recarga del segundo, y éste una recarga del tercero.

Utilizando el helper LinkDropDownLists, sólo sería necesario introducir el siguiente código en la vista:
 <%= Ajax.LinkDropDownLists(
new [] {"Pais", "Provincia", "Ciudad"}
)
%>
 
¡Ya está! Esto sería todo lo que habría que hacer en la capa cliente para conseguir enlazarlos. Como puede deducirse, mediante esta orden estaríamos creando una cadena de dependencia entre los tres desplegables, de forma que un cambio en cualquiera de ellos forzaría la recarga de los definidos tras él. El helper se encargará de generar el código script que este mágico comportamiento posible.

Pero compliquemos un poco más el escenario. Si, además, en el mismo formulario se encontrara otro conjunto de desplegables, podríamos enlazarlos entre sí usando la misma llamada, especificando en dos arrays independientes las distintas cadenas de vínculos, como sigue:
 <%= Ajax.LinkDropDownLists(
new [] {"Pais", "Provincia", "Ciudad"},
new [] {"Marca", "Modelo" }
)
%>
 
Y aún cabe una vuelta de tuerca más; si dependiendo de la selección en "Pais" fuera necesario cargar otro desplegable, digamos, "Idioma" que mostrara las lenguas usadas en el mismo, podríamos añadir una tercera cadena de enlaces en la que aparecería de nuevo el desplegable "Pais" vinculado al idioma:
 <%= Ajax.LinkDropDownLists(
new [] {"Pais", "Provincia", "Ciudad"},
new [] {"Marca", "Modelo" },
new [] {"Pais", "Idioma" }
)
%>
 
Como se puede deducir de los ejemplos, cada uno de los parámetros consiste en un array de strings que contiene los identificadores de los desplegables, en el mismo orden en que deben ser recargados. Estos controles pueden estar definidos en cualquier punto de la Vista, bien directamente en HTML o bien mediante el helper Html.DropDownList() incluido en el MVC framework.

Por último, el método LinkDropDownLists() dispone de un buen conjunto de sobrecargas, que nos permitirán modificar los siguientes aspectos de su comportamiento por defecto:
  • workingMessage: mensaje que muestra en el desplegable mientras se están obteniendo los datos del servidor.
  • errorMessage: mensaje a mostrar cuando se produce un error de conexión, o se lanza una excepción desde el servidor.
  • javascriptCallbackFunction: nombre de la función javascript que se ejecutará cuando se han obtenido datos del servidor y se ha recargado un desplegable.
  • actionName: nombre de la acción en el controlador (por defecto GetDropDownElements()).
  • imgSrc: URL de la imagen de progreso de carga mostrada durante la petición Ajax (por defecto, "/content/ajax-loading.gif").
  • mainFunctionName: nombre de la función principal que genera el helper (por defecto, loadDropDownList).

El controlador

En el lado servidor, necesitamos una acción en el controlador desde el que se esté lanzando la vista que sea la encargada de procesar las peticiones enviadas desde la capa cliente y retornar los elementos que poblarán el desplegable. Por defecto, esta la acción se llamará GetDropDownElements, aunque puede modificarse utilizando las sobrecargas del helper descritas anteriormente.

Para que pueda disponer de toda la información de contexto necesaria, a esta acción se le pasan los siguientes parámetros de forma automática desde la Vista:
  • source: el desplegable que ha cambiado.
  • value: el nuevo valor que ha tomado.
  • text: el texto mostrado en el desplegable.
  • index: el índice del elemento seleccionado.
  • target: el nombre del desplegable a cargar.

La firma del método deberá contener los parámetros que necesite de los anteriores, no siendo obligatorio ninguno de ellos. Las siguientes signaturas, por tanto, serían válidas, aunque la segunda permitirá acceder a más información sobre la situación en cliente al producirse la invocación Ajax:
 public ActionResult GetDropDownElements(string target) 
{ ... }

public ActionResult GetDropDownElements(
string source, string value,
string text, int index, string target)
{ ... }
 
Dentro de la acción, lo lógico será utilizar el Modelo para obtener los elementos que pueblen el desplegable target. Por ejemplo, si recibimos una petición indicando que debemos llenar el desplegable de provincias debido a un cambio de país (source=="Pais" && target=="Provincia"), deberemos realizar una consulta en el almacén de datos filtrando aquellas cuyo identificador de país sea el contenido en el parámetro value.

Si no encontramos datos para devolver, el retorno de la función será un string serializado en JSON, indicando el error. Este mensaje será mostrado como contenido del desplegable.
  ... 
return Json("No se han definido provincias para " + text);
 
En caso contrario, es decir, si disponemos de elementos para rellenar el desplegable, el retorno será una colección de objetos que deberán presentar las siguientes propiedades públicas:
  • Value: con el valor del elemento (el value del option).
  • Text: que contendrá el texto que será mostrado en el desplegable.
  • Selected: un booleano que indicará si el elemento deberá ser la selección por defecto una vez poblado el desplegable.
Para evitarnos demasiados esfuerzos ;-), una característica muy interesante de la que podemos hacer uso para crear los retornos es de los tipos anónimos, así:
  // Generando los elementos de forma manual...
List<object> elements = new List<object>();
elements.Add(new { Value = 1, Text = "Primero" });
elements.Add(new { Value = 2, Text = "Segundo" });
elements.Add(new { Value = 3, Text = "Tercero" });
elements.Add(new { Value = 4, Text = "Cuarto", Selected = true });
return Json(elements);

// O usando Linq...
var elems = from p in Model.ObtenerProvincias(value)
select new
{
Text = p.NombreProvincia,
Value = p.IdProvincia
};
return Json(elems);
 

Proyecto de demostración

Al pie del post hay un enlace a Skydrive desde donde podréis descargar un proyecto de demostración del helper LinkDropDownLists para ver algunas de sus características en funcionamiento:
  • una única página con dos grupos independientes de desplegables enlazados
  • algunos desplegables definidos mediante helpers y en HTML.
  • retorno de mensajes de error desde el servidor
  • captura de excepciones y errores de comunicación
  • función callback de notificación de llenado de desplegables
  • utilización de textos personalizados
En el propio proyecto encontraréis el código completo del helper en el archivo Extensions/jQueryExtensions.cs.

Ampliar

Enlaces: Descargar proyecto para Visual Studio 2008 SP1 + ASP.NET MVC 1.0.
(También funciona con Visual Web Developer Express 2008 SP1).


Publicado en: www.variablenotfound.com.