CSharp - ASP.net en La Practica

download CSharp - ASP.net en La Practica

of 54

description

CSharp - ASP.net en La Practica

Transcript of CSharp - ASP.net en La Practica

  • ASP.NET en la prctica

    En este ltimo captulo dedicado a ASP.NET, trataremos algunos aspectos de inters a la horade construir aplicaciones reales. Despus de haber visto en qu consiste una aplicacines web,cmo se crean formularios web en ASP.NET y de qu forma se pueden realizar las tareas mscomunes con las que debe enfrentarse el programador de aplicaciones web, ahoracomentaremos algunos de los aspectos relativos a la organizacin interna de las aplicacionesweb:

    - En primer lugar, comentaremos brevemente algunos de los patrones de diseo quese suelen emplear a la hora de crear la aplicacin web con el objetivo de que stamantenga su flexibilidad y su mantenimiento no resulte tedioso.

    - A continuacin, nos centraremos en los mecanismos existentes que nos facilitanque el aspecto externo de una aplicacin web ASP.NET sea homogneo.

    - Una vez descritos los principios en los que se suelen basar las aplicaciones webbien diseadas, repasaremos cmo se puede hacer que el contenido de nuestrainterfaz web cambie dinmicamente utilizando un mecanismo conocido comoenlace de datos [data binding].

    - Finalmente, cerraremos este captulo centrndonos en la construccin deformularios de manipulacin de datos, como ejemplo ms comn del tipo demdulos que tendremos que implementar en cualquier aplicacin.

  • ASP.NET en la prcticaOrganizacin de la interfaz de usuario..............................125

    Componentes de la interfaz ................................... 125El modelo MVC en ASP.NET .............................. 127Controladores en ASP.NET................................. 129

    Control de la aplicacin.......................................... 135

    Aspecto visual de la aplicacin .........................................140Filtros con mdulos HTTP ..................................... 142La directiva #include .............................................. 143Plantillas................................................................. 145

    Configuracin dinmica de la aplicacin..........................147Listas de opciones ................................................. 149

    Vectores simples: Array y ArrayList..................... 150Pares clave-valor: Hashtable y SortedList........... 151Ficheros XML ...................................................... 153

    Conjuntos de datos ................................................ 157El control asp:Repeater ....................................... 158El control asp:DataList......................................... 161El control asp:DataGrid ....................................... 163

    Formularios de manipulacin de datos.............................170Edicin de datos .................................................... 170Formularios maestro-detalle en ASP.NET............. 174

    124 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • Organizacin de la interfaz de usuario

    Como Steve McConnell expone en su libro Software Project Survival Guide, la mayor partedel trabajo que determina el xito o el fracaso final de un proyecto de desarrollo de softwarese realiza antes de que comience su implementacin: "si el equipo investiga los requisitos afondo, desarrolla el diseo con detalle, crea una buena arquitectura, prepara un plan deentrega por etapas y controla los cambios eficazmente, la construccin [del software]destacar por su firme progreso y la falta de problemas graves". Obviamente, la lista decondiciones que se han de cumplir para que un proyecto de desarrollo de software finalice conxito es extensa, como no poda ser menos dada la complejidad de las tareas que han derealizarse.

    En los primeros apartados de este captulo nos centraremos en una de las bases que sirven deapoyo al xito final del proyecto: la creacin de una buena arquitectura. En concreto, veremoscmo se pueden organizar los distintos elementos que pueden formar parte de la interfaz webde una aplicacin realizada con ASP.NET.

    Componentes de la interfazLa primera tentacin de un programador de aplicaciones web consiste en escribir todo elcdigo de su aplicacin en la propia pgina ASP.NET. Sin embargo, en cuanto la aplicacincomienza a crecer, empiezan a aparecer cierta redundancia. La existencia de fragmentos decdigo duplicados complicarn el mantenimiento de la aplicacin y la realizacin de nuevasmejoras.Cuando situaciones como esta se presentan, lo usual es encapsular la lgica de la aplicacinen componentes independientes. La redundancia se elimina a cambio de un incremento en lacomplejidad de la aplicacin. Cuanto ms compleja sea la aplicacin, ms difcil ser queotros programadores sean capaces de entender correctamente su funcionamiento. Por tanto, lacomplejidad introducida tambin dificulta el mantenimiento de la aplicacin, aunque sea enun sentido totalmente diferente al causado por la existencia de cdigo duplicado.

    Afortunadamente, existen soluciones bien conocidas que consiguen dotar a las aplicaciones decierta flexibilidad sin incrementar excesivamente su complejidad. En el caso del desarrollo deinterfaces de usuario, la solucin ms conocida es el patrn de diseo MVC[Model-View-Controller], en el que se distinguen tres componentes bien diferenciados:

    - El modelo encapsula el comportamiento y los datos correspondientes al dominiode la aplicacin. Habitualmente se construye un modelo de clases del problemacon el que se est trabajando, independientemente de cmo se vayan a presentarlos datos de cara al usuario.

    125ASP.NET en la prctica

    http://csharp.ikor.org/

  • - Las vistas consultan el estado del modelo para mostrrselo al usuario. Porejemplo, un mismo conjunto de datos puede verse en forma de tabla ogrficamente, en una pantalla o en un informe impreso. Cada una de las formas demostrar los constituye una vista independiente y, en vez de tener en cada vista elcdigo necesario para acceder directamente a los datos, cada una de las vistasdelega en el modelo, que es el responsable de obtener los datos y realizar losclculos necesarios.

    - Los controladores, por ltimo, son los encargados de permitir que el usuariorealice acciones. Dichas acciones se traducirn en las respuestas que resultenapropiadas, las cuales pueden involucrar simplemente a las vistas o incluir larealizacin de operaciones sobre el modelo.

    El modelo MVC: Las vistas y los controladores dependen del modelo, peroel modelo no depende ni de la vista ni del controlador. Esto permite que elmodelo se pueda construir y probar independientemente de la presentacin

    visual de la aplicacin. Adems, se pueden mostrar varias vistas de losmismos datos simultneamente.

    El modelo MVC ayuda a modularizar correctamente una aplicacin en la cual el usuariomanipula datos a travs de una interfaz. Si el usuario puede trabajar con los mismos datos dedistintas formas, lo habitual es encapsular el cdigo compartido en un mdulo aparte con elfin de evitar la existencia de cdigo duplicado. Se puede decir que el modelo contiene elcomportamiento comn a las distintas formas que tiene el usuario de manipular los datos. Dehecho, la existencia de un modelo independiente facilita enormemente la construccin desistemas que han de ofrecer varios interfaces. Este sera el caso de una empresa que deseadisponer de una aplicacin Windows para uso interno de sus empleados, una interfaz webpara que sus clientes puedan realizar pedidos y un conjunto de servicios web para facilitar elintercambio de datos con sus proveedores.

    126 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • De hecho, aunque el usuario trabaje con los datos de una nica forma, el cdigocorrespondiente a la interfaz suele cambiar ms frecuentemente que el cdigo correspondientea la lgica de la aplicacin. Por ejemplo, es bastante habitual cambiar el aspecto visual de unaaplicacin manteniendo su funcionalidad intacta. Eso sucede cada vez que ha de adaptarse lainterfaz a un nuevo dispositivo, como puede ser un PDA cuya resolucin es mucho mslimitada que la de un monitor convencional.

    En el caso de las aplicaciones web, los conocimientos necesarios para crear la interfaz (enHTML dinmico por lo general) suelen ser diferentes de los necesarios para implementar lalgica de la aplicacin (para la que se utilizan lenguajes de programacin de alto nivel). Porconsiguiente, la separacin de la interfaz y de la lgica de la aplicacin facilita la divisin deltrabajo en un equipo de desarrollo.Por otro lado, cualquier modificacin requerir comprobar que los cambios realizados no hanintroducido errores en el funcionamiento de la aplicacin. En este sentido, mantener losdistintas partes de una aplicacin lo menos acopladas posible siempre es una buena idea.Adems, comprobar el funcionamiento de la interfaz de usuario es mucho ms complejo ycostoso que realizar pruebas de unidad sobre mdulos independientes (algo que describiremosen la ltima parte de este libro cuando veamos el uso de NUnit para realizar pruebas deunidad).

    Una de las decisiones de diseo fundamentales en laconstruccin de software es aislar la interfaz de la lgica de laaplicacin. Al fin y al cabo, el xito del modelo MVC radicaen esa decisin: separar la lgica de la aplicacin de la lgicacorrespondiente a su presentacin.

    En los dos prximos apartados veremos cmo se utiliza el modelo MVC en ASP.NET y cmose pueden crear controladores que realicen tareas comunes de forma uniforme a lo largo yancho de nuestras aplicaciones.

    El modelo MVC en ASP.NET

    Las aplicaciones web utilizan una variante del modelo MVC conocida como MVC pasivoporque las vistas slo se actualizan cuando se realiza alguna accin a travs del controlador.Esto es, aunque el estado del modelo se vea modificado, la vista no se actualizarautomticamente. El navegador del usuario muestra la vista y responde a las acciones delusuario pero no detecta los cambios que se puedan producir en el servidor. Dichos cambiospueden producirse cuando varios usuarios utilizan concurrentemente una aplicacin o existenotros actores que pueden modificar los datos con los que trabaja nuestra aplicacin. Laspeculiaridades de los interfaces web hacen que, cuando es necesario reflejar en el navegadordel usuario los cambios que se producen en el servidor, tengamos que recurrir a estrategiascomo las descritas al estudiar el protocolo HTTP en el apartado "cuestin de refresco" del

    127ASP.NET en la prctica

    http://csharp.ikor.org/

  • captulo anterior.

    Cuando comenzamos a ver en qu consistan las pginas ASP.NET, vimos que existen dosestilos para la confeccin de pginas ASP.NET:

    - Podemos incluir todo en un nico fichero .aspx o podemos separar los controlesde la interfaz del cdigo de la aplicacin. Si empleamos un nico fichero .aspx,dicho fichero implementa los tres roles diferenciados por el modelo MVC:modelo, vista y controlador aparecen todos revueltos. Entre otros inconvenientes,esto ocasiona que un error introducido en el cdigo al modificar el aspecto visualde una pgina no se detectar hasta que la pgina se ejecute de nuevo.

    - Si empleamos ficheros diferentes, se separan fsicamente la interfaz y la lgica dela aplicacin. El fichero .aspx contendr la presentacin de la pgina (la vistasegn el modelo MVC) mientras que el fichero .aspx.cs combinar el modelocon el controlador. El cdigo comn a distintas pginas se podr reutilizar concomodidad y un cambio que afecte a la funcionalidad comn no requerir quehaya que ir modificando cada una de las pginas. Adems, se podr modificar elaspecto visual de la pgina sin temor a introducir errores en el cdigo de laaplicacin y podremos utilizar todas las facilidades que nos ofrezca el entorno dedesarrollo para desarrollar ese cdigo (al contener el fichero .aspx.cs una claseconvencional escrita en C#).

    Hasta aqu, nada nuevo: el cdigo se escribe en un fichero aparte para facilitar nuestro trabajo(algo que hicimos desde el primer momento). Sin embargo, no estamos utilizando ningn tipode encapsulacin.

    Por un lado, se hace referencia a las variables de instancia de la clase desde el fichero .aspx.Por ejemplo, podemos tener un botn en nuestra pgina ASP.NET:

    Dicho botn, representado por medio de la etiqueta asp:button, hace referencia a unavariable de instancia declarada en el fichero .aspx.cs:

    protected System.Web.UI.WebControls.Button button;

    Por otro lado, el mtodo InitializeComponent define el funcionamiento de la pgina alenlazar los controles de la pgina con el cdigo correspondiente a los distintos eventos:

    private void InitializeComponent()

    128 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • {this.button.Click += new System.EventHandler(this.Btn_Click);this.Load += new System.EventHandler(this.Page_Load);

    }

    Si bien siempre es recomendable separar la interfaz del cdigo, la vista delmodelo/controlador, esta separacin es insuficiente cuando tenemos que desarrollaraplicaciones reales. Tcnicamente, sera posible reutilizar el cdigo del fichero .aspx.cs,aunque eso slo conducira a incrementar el acoplamiento de otras partes de la aplicacin conla pgina ASP.NET. Para evitarlo, se crean clases adicionales que separan el modelo delcontrolador. El controlador contendr nicamente el cdigo necesario para que el usuariopueda manejar la pgina ASP.NET y el modelo ser independiente por completo de la pginaASP.NET.

    En la ltima parte de este libro veremos cmo se crea dicho modelo y cmo, al serindependiente, se pueden desarrollar pruebas de unidad que verifican su correctofuncionamiento. De hecho, tener la lgica de la aplicacin separada por completo de lainterfaz es algo necesario para poder realizar cmodamente pruebas que verifiquen elcomportamiento de la aplicacin. En las aplicaciones web, comprobar el funcionamiento lalgica incluida en una pgina resulta especialmente tedioso, ya que hay que analizar eldocumento HTML que se obtiene como resultado. Separar la lgica de la aplicacin nosfacilita enormemente el trabajo e incluso nos permite automatizarlo con herramientas comoNUnit, que tambin se ver en la ltima parte de este libro.

    Por ahora, nos centraremos en cmo se puede implementar el controlador de una aplicacinweb desarrollada en ASP.NET.:

    Controladores en ASP.NET

    En el modelo MVC, la separacin bsica es la que independiza el modelo de la interfaz de laaplicacin. La separacin entre vistas y controladores es, hasta cierto punto, secundaria. Dehecho, en la mayor parte de entornos de programacin visual, vistas y controladores seimplementan conjuntamente, a pesar de ser una estrategia poco recomendable. En el caso delas aplicaciones web, no obstante, la separacin entre modelo y controlador est muy biendefinida: la vista corresponde al HTML que se muestra en el navegador del usuario mientrasque el controlador se encarga en el servidor de gestionar las solicitudes HTTP. Adems, enuna aplicacin web, distintas acciones del usuario pueden conducir a la realizacin dedistintas tareas (responsabilidad del controlador) aun cuando concluyan en la presentacin dela misma pgina (la vista en el modelo MVC).En el caso de las aplicaciones web, existen dos estrategias para implementar la partecorrespondiente al controlador definido por el modelo MVC, las cuales dan lugar a dos tiposde controladores: los controladores de pgina (especficos para cada una de las pginas de laaplicacin web) y los controladores de aplicacin (cuando un controlador se encarga de todaslas pginas de la aplicacin).

    129ASP.NET en la prctica

    http://csharp.ikor.org/

  • Controladores de pgina

    Usualmente, se utiliza un controlador independiente para cada pgina de la aplicacin web. Elcontrolador se encarga de recibir la solicitud de pgina del cliente, realizar las accionescorrespondientes sobre el modelo y determinar cul es la pgina que se le ha de mostrar alusuario a continuacin.

    En el caso de ASP.NET y de muchas otras plataformas para el desarrollo de aplicaciones web,como JSP o PHP, la plataforma nos proporciona los controladores de pgina, usualmentemezclados con la vista a la que corresponde la pgina. En ASP.NET, los controladores tomanforma de clase encargada de gestionar los eventos recibidos por la pgina .aspx. Estaestrategia nos facilita el trabajo porque, en cada momento, slo tenemos que preocuparnos dela accin con la que se ha de responder a un evento concreto. De esta forma, la complejidaddel controlador puede ser reducida y, dada la dificultad que conlleva probar el funcionamientode una interfaz web, la simplicidad siempre es una buena noticia.

    Usualmente, las aplicaciones web realizan algunas tareas fijas para todas las solicitudesrecibidas, como puede ser la autentificacin de usuarios que ya se trat en el captulo anterior.De hecho, tener un controlador para cada pgina (y, veces, por accin del usuario) sueleconducir a la aparicin de bastante cdigo duplicado. Cuando esto sucede, se suele crear unaclase base que implemente las funciones comunes a todos los controladores y de la quehereden los controladores de cada una de las pginas de la aplicacin. Otra opcin consiste encrear clases auxiliares que implementen utilidades de uso comn. Este caso deberemosacordarnos siempre de invocar a esas utilidades en todas y cada una de las pginas de laaplicacin, mientras que si utilizamos herencia podemos dotar a todos nuestros controladoresde cierta funcionalidad de forma automtica. Cuando la complejidad de esas operacionesauxiliares es destacable, conviene combinar las dos estrategias para mantener la cohesin delos mdulos de la aplicacin y facilitar su mantenimiento. Esto es, se puede utilizar unajerarqua de clases para los controladores y que algn miembro de esta jerarqua(presumiblemente cerca de su base) delegue en clases auxiliares para realizar las tareasconcretas que resulten necesarias.

    Cabecera comn para distintas pginas ASP.NETEn ocasiones, hay que mostrar informacin de forma dinmica en una cabecera comn paratodas las pginas de una aplicacin (por ejemplo, la direccin de correo electrnico delusuario que est actualmente conectado). En vez de duplicar el cdigo correspondiente a lacabecera en las distintas pginas, podemos hacer que la clase base muestre la parte comn ylas subclases se encarguen del contenido que les es especfico. En ASP.NET podemos crearuna relacin de herencia entre pginas y utilizar un mtodo genrico definido en la clasebase que ser implementado de forma diferente en cada subclase.

    En primer lugar, creamos la pgina ASP.NET que servir de base: BasePage.cs. Endicha clase incluiremos un mtodo virtual y realizaremos las tareas que sean comunes paralas distintas pginas:

    130 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • Cabecera comn para distintas pginas ASP.NET

    public class BasePage : System.Web.UI.Page{...

    virtual protected void PageLoadEvent(object sender, System.EventArgs e) {}

    protected void Page_Load (object sender, System.EventArgs e){if (!IsPostBack) {

    eMailLabel.Text = "[email protected]";PageLoadEvent(sender, e);

    }}

    ...

    }

    Tambin se debe crear el fichero que contendr la parte comn del aspecto visual de laspginas: BasePage.inc.

    Hola,usuario

    A continuacin, se crean las distintas pginas de la aplicacin. En los ficheros .aspx hayque incluir la directiva #include en el lugar donde queremos que aparezca la cabecera:

    ...

    ...

    Por ltimo, al implementar la lgica asociada a los controladores de las pginas, seimplementa el mtodo LoadPageEvent particular para cada pgina sin redefinir elmtodo Page_Load que ya se defini en la clase base:

    public class ApplicationPage : BasePage{...

    protected override void PageLoadEvent(object sender, System.EventArgs e) ...

    }

    131ASP.NET en la prctica

    http://csharp.ikor.org/

  • Controladores de aplicacin

    En la mayora de las aplicaciones web convencionales, las pginas se generan de formadinmica pero la navegacin entre las pginas es relativamente esttica. En ocasiones, noobstante, la navegacin entre las distintas partes de la aplicacin es dinmica. Por ejemplo, lospermisos del usuario o de un conjunto de reglas de configuracin podran modificar el "mapade navegacin" de la aplicacin. En ese caso, la implementacin de los controladores depgina comienza a complicarse: aparecen expresiones lgicas complejas para determinar elflujo de la navegacin. Por otro lado, puede que nuestra aplicacin incluya distintos tipos depginas, cada uno con sus peculiaridades. Cuantas ms variantes haya, ms niveles hay queincluir en la jerarqua de clases correspondiente a los controladores. Fuera de control, lajerarqua de controladores puede llegar a ser inmanejable.En situaciones como las descritas en el prrafo anterior, resulta recomendable centralizar elcontrol de la aplicacin en un controlador nico que se encargue de tramitar todas lassolicitudes que recibe la aplicacin web. Un controlador de aplicacin, llamado usualmentefront controller, suele implementarse en dos partes:

    - Por un lado, un manejador [handler] es el que recibe las peticiones. En funcin dela peticin y de la configuracin de la aplicacin (que podra almacenarse en unsencillo fichero XML), el manejador ejecuta la accin adecuada y elige la pginaque se le mostrar al usuario a continuacin.

    - Por otro lado, el conjunto de acciones que puede realizar la aplicacin se modelamediante una jerarqua de comandos, utilizando la misma filosofa que permiteimplementar las operaciones de rehacer/deshacer en muchas aplicaciones. Todoslos comandos implementan una interfaz unificada y cada uno de ellos representauna de las acciones que se pueden realizar.

    Aparte de facilitar la creacin de aplicaciones web realmente dinmicas, usar un controladorcentralizado para una aplicacin tambin repercute en otros aspectos del desarrollo de laaplicacin. Ya se ha mencionado que comprobar el correcto funcionamiento de una interfazde usuario requiere mucho esfuerzo. Lo mismo se puede decir de la lgica asociada a loscontroladores de pgina de una aplicacin web. Al usar un controlador genrico eimplementar las acciones de la aplicacin como comandos independientes tambinfacilitamos la fase de pruebas de la aplicacin.

    Respecto a los controladores de pgina, el uso extensivo de jerarquas de herencia conduce aaplicaciones cuyo diseo es frgil ante la posibilidad de que se tengan que realizar cambios enla aplicacin. Adems, determinadas funciones es mejor implementarlas de formacentralizada para evitar posibles omisiones. Piense, por ejemplo, en lo que podra suceder sien una pgina de una aplicacin de comercio electrnico se le olvidase realizar alguna tareade control de acceso. La centralizacin ayuda a la hora de mejorar la consistencia de unaaplicacin.

    132 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • Controlador comn para distintas pginas ASP.NETSupongamos que partimos de una aplicacin similar a la descrita en el ejemplo de la seccinanterior ("cabecera comn para distintas pginas ASP.NET). El mtodo Page_Load de laclase base BasePage se llama siempre que se accede a una pgina. Supongamos ahora queel formato de la cabecera mostrada dependa de la solicitud concreta, su URL o susparmetros. En funcin de la solicitud, no slo cambiar la cabecera, sino el procesonecesario para rellenarla. Esto podra suceder si nuestra aplicacin web sirve de base paradar soporte a varios clientes, para los cuales hemos personalizado nuestra aplicacin. Laspginas individuales seguirn siendo comunes para los usuarios, pero la parte implementadaen la clase base variar en funcin del caso particular, por lo que se complica laimplementacin de BasePage:

    protected void Page_Load (object sender, System.EventArgs e){string estilo;

    if (!IsPostBack) {estilo = Request["style"];

    if ( estilo!=null && estilo.Equals("vip"))... // Slo VIPs

    else... // Convencional

    PageLoadEvent(sender, e);}

    }

    Conforme se aaden casos particulares, el desastre se va haciendo ms evidente. Cualquiercambio mal realizado puede afectar a aplicaciones que estaban funcionando correctamente,sin causa aparente desde el punto de vista de nuestros enojados clientes.Para crear un controlador de aplicacin que elimine los problemas de mantenimiento a losque podra conducir una situacin como la descrita, lo primero que hemos de hacer es crearun manejador que reciba las peticiones. En ASP.NET podemos utilizar la interfaz a bajonivel IHttpHandler tal como pusimos de manifiesto en el captulo anterior al estudiar losmanejadores y filtros HTTP:

    using System;using System.Web;

    public class Handler : IHttpHandler{public void ProcessRequest (HttpContext context){Command command = CommandFactory.Create(context);

    command.Do (context);}

    133ASP.NET en la prctica

    http://csharp.ikor.org/

  • Controlador comn para distintas pginas ASP.NET

    public bool IsReusable{get { return true;}

    }}

    El comando se limita a implementar una sencilla interfaz:

    using System;using System.Web;

    public interface Command{void Do (HttpContext context);

    }

    En el caso de una aplicacin en la que el usuario debiese tener oportunidad de deshacer susacciones, lo nico que tendramos que hacer es aadirle un mtodo Undo a la interfazCommand (e implementarlo correctamente en todas las clases que implementen dichainterfaz, claro est).En vez de crear directamente los objetos de tipo Command, se utiliza una clase auxiliar en laque se incluye la lgica necesaria para elegir el comando adecuado. Esta fbrica decomandos (CommandFactory) se encargar de determinar el comando adecuado enfuncin del contexto:

    using System;using System.Web;

    public class CommandFactory{public static Command Create (HttpContext context){string estilo = context.Request["style"];Command command = new NullCommand();

    if ( estilo!=null && estilo.Equals("vip"))command = new VIPCommand(context);

    elsecommand = new ConventionalCommand(context);

    return command;}

    }

    Para que nuestra aplicacin utilice el controlador creado, tal como se describi en el captuloanterior al hablar de los filtros HTTP, hemos de incluir lo siguiente en el fichero deconfiguracin Web.config:

    134 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • Controlador comn para distintas pginas ASP.NET

    Finalmente, lo ltimo que nos falta es crear nuestra jerarqua de comandos, que sern los quese encarguen de personalizar el funcionamiento de nuestra aplicacin para cada cliente:

    using System;using System.Web;

    public class AspNetCommand : Command{public void Do (HttpContext context){...

    context.Server.Transfer(url);}

    }

    En realidad, lo nico que hemos hecho ha sido reorganizar las clases que implementan lainterfaz de nuestra aplicacin y reasignar las responsabilidades de cada una de las clases. Si lohacemos correctamente, podemos conseguir un sistema modular con componentes dbilmenteacoplados que se pueden implementar y probar de forma independiente. En la siguienteseccin veremos una forma ms general de conseguir una aplicacin web fcilmentereconfigurable.

    Control de la aplicacinEn una aplicacin web, cada accin del usuario se traduce en una solicitud que da lugar a dosrespuestas de mbito diferente. Por un lado, se ha de realizar la tarea indicada por el usuario.Aparte, se le ha de mostrar al usuario la pgina adecuada, que puede no estar directamenterelacionada con la tarea realizada. De hecho, una misma pgina puede ser la respuesta delsistema ante distintas acciones y una misma accin puede dar lugar a distintas pginas derespuesta en funcin del contexto de la aplicacin.

    En general, a partir del estado actual de la aplicacin (almacenado fundamentalmente en losdiccionarios Application y Session) y de la accin que realice el usuario, el sistema hade decidir dos cosas: las acciones que se han de realizar sobre los objetos con los que trabajala aplicacin y la siguiente pgina que ha de mostrarse en el navegador del usuario.

    En el apartado anterior, vimos cmo los controladores se encargan de tomar ambasdecisiones. Obviamente, el resultado no destaca por su cohesin. En el mejor de los casos, lacohesin del controlador es puramente temporal. Es decir, las operaciones se incluyen en un

    135ASP.NET en la prctica

    http://csharp.ikor.org/

  • mdulo porque han de realizarse al mismo tiempo.

    Para organizar mejor una aplicacin, podemos dividir en dos la parte responsable de lainterfaz de usuario. Esta parte de la aplicacin se denomina habitualmente capa depresentacin. En la capa de presentacin distinguir dos tipos bien diferenciados decomponentes:

    - Los componentes de la interfaz de usuario propiamente dichos: Los controlescon los que los usuarios interactan.

    - Los componentes de procesamiento de la interfaz de usuario (componentes deprocesamiento para abreviar): Estos componentes "orquestan los elementos de lainterfaz de usuario y controlan la interaccin con el usuario".

    Esta distincin entre controles de la interfaz y componentes de procesamiento nos permitediferenciar claramente las dos responsabilidades distintas que antes les habamos asignado alos controladores MVC:

    - Los controles de la interfaz engloban las vistas del modelo MVC con las tareasrealizadas por los controladores MVC para adquirir, validar, visualizar y organizarlos datos en la interfaz de usuario.

    - Los componentes de procesamiento se encargan de mantener el estado de laaplicacin y controlar la navegacin del usuario a travs de sus distintas pginas.

    Cuando un usuario utiliza una aplicacin, lo hace con un objetivo: satisfacer una necesidadconcreta. Una tcnica popular para realizar el anlisis de los requisitos de una aplicacinconsiste en emplear casos de uso. Los casos de uso describen conjuntos de acciones que ha derealizar un usuario para lograr sus objetivos. Cada accin se realiza en un contexto deinteraccin determinado (una pgina en el caso de las aplicaciones web) y el usuario vapasando de un contexto de interaccin a otro conforme va completando etapas del caso de usoque est ejecutando. Mientras que los controles de la interfaz se encargan de garantizar elfuncionamiento de un contexto de interaccin, los componentes de procesamiento controlan elflujo de control de un caso de uso.

    Estos "componentes de procesamiento" se suelen denominarcontroladores de aplicacin, si bien hay que tener en cuentaque estamos refirindonos a algo totalmente distinto a lo quevimos en el apartado anterior cuando estudiamos laposibilidad de usar controladores MVC centralizados para unaaplicacin web. En ocasiones, para evitar malentendidos, sedenominan controladores frontales a los controladores MVCcentralizados, haciendo referencia a que sirven de punto deacceso frontal para las aplicaciones web.

    136 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • Los componentes de procesamiento de la interfaz de usuario, controladores de aplicacin deaqu en adelante, son responsables de gestionar el flujo de control entre las distintas pginasinvolucradas en un caso de uso, decidir cmo afectan las excepciones que se puedan produciry mantener el estado de la aplicacin entre distintas interacciones (para lo cual acumulandatos recogidos de los distintas pginas por las que va pasando el usuario) y ofrecerle a loscontroles de la interfaz los datos que puedan necesitar para mostrrselos al usuario. De estaforma, se separa por completo la visualizacin de las pginas del control de la navegacin porla aplicacin.

    Esta estrategia nos permite, por ejemplo, crear distintas interfaces para una aplicacin sintener que modificar ms que las vistas correspondientes a los distintos contextos deinteraccin en que se puede encontrar el usuario. El controlador de la aplicacin puede ser,por tanto, comn para una aplicacin Windows, una aplicacin web y una aplicacin paraPDAs o telfonos mviles. Adems, se mejora la modularidad del sistema, se fomenta lareutilizacin de componentes y se simplifica el mantenimiento de la aplicacin.

    Un controlador de aplicacin se suele implementar como un conjunto de clases a las que seaccede desde la interfaz de usuario, a modo de capa intermedia entre los controles de lainterfaz de usuario y el resto de la aplicacin. La siguiente clase ilustra el aspecto que podratener el controlador de una aplicacin web de comercio electrnico para el caso de usocorrespondiente a la realizacin de un pedido:

    public class ControladorPedido{private Cliente cliente; // Estado actual del pedidoprivate ArrayList productos;...

    public void MostrarPedido(){if (application.WebInterface) {

    ... // Interfaz webSystem.Web.HttpContext.Current.Response.Redirect

    ("http://csharp.ikor.org/pedidos/Pedido.aspx");} else {

    ... // Interfaz WindowsFormPedido.Show();

    }}

    public void ElegirFormaDePago(){... // Seleccionar la forma de pago ms adecuada para el cliente

    }

    public void RealizarPedido(){if (ConfirmarPedido()) {

    ... // Crear el pedido con los datos facilitados}

    }

    137ASP.NET en la prctica

    http://csharp.ikor.org/

  • public bool ConfirmarPedido(){... // Solicitar una confirmacin por parte del usuario

    }

    public void Cancelar(){... // Vuelta a la pgina/ventana principal

    }

    public void Validar(){... // Comprobar que todo est en orden

    }}

    Si bien el recorrido del usuario a travs de la aplicacin lo determina el controlador deaplicacin, las pginas concretas por las que pase el usuario no tienen por qu estar prefijadasen el cdigo del controlador. Lo habitual es almacenar las transiciones entre pginas concretasen un fichero de configuracin aparte. La lgica condicional para seleccionar la formaadecuada de mostrar la interfaz de usuario tambin se puede eliminar del cdigo delcontrolador de aplicacin si se crea un interfaz genrico que permita mostrar un contexto deinteraccin a partir de una URL independientemente de si estamos construyendo unaaplicacin Windows o una aplicacin web.

    Separar fsicamente el controlador de aplicacin de los controles de la interfaz de usuariotiene otras ventajas. Por ejemplo, un usuario podra intentar realizar un pedido y encontrarsecon algn tipo de problema. Entonces, podra llamar por telfono para que un comercialcompletase los pasos pendientes de su pedido sin tener que repetir el proceso desde elprincipio. De hecho, quiz utilice para ello una aplicacin Windows que comparte con laaplicacin web el controlador de aplicacin.

    Por otro lado, los controladores de aplicacin permiten que un usuario pueda realizar variastareas en paralelo. Por ejemplo, el usuario podra tener abiertas varias ventanas de sunavegador y dejar la realizacin de un pedido a medias mientras consultaba el catlogo deprecios de productos alternativos, por ejemplo. Al encargarse cada controlador de mantener elestado de una nica tarea, se consigue una simplificacin notable en el manejo de actividadesconcurrentes.

    En el caso de las aplicaciones web ASP.NET, los controladores de aplicacin son los objetosalmacenados como estado de la aplicacin en la variable Session. Los manejadores deeventos de las pginas .aspx accedern a dichos controladores en respuesta a las accionesdel usuario.

    En el caso de las aplicaciones Windows, los formulariosincluirn una variable de instancia que haga referencia alcontrolador de aplicacin concreto. Usar variables globalesnunca es una buena idea. Y mucho menos en este mbito.

    138 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • El controlador de aplicacin se coloca entre el modelo y la interfaz deusuario para orquestar la ejecucin de los casos de uso.

    Centremos ahora nuestra atencin en el diseo del controlador de aplicacin. Bsicamente,tenemos que considerar tres aspectos fundamentales a la hora de construir el controlador deaplicacin:

    - La creacin de vistas: Un controlador concreto podra estar asociado a distintasvistas en funcin de la situacin (por ejemplo, cuando se utiliza el mismocontrolador para una aplicacin web y una aplicacin Windows). Lo normal sercrear una clase abstracta con varias subclases concretas para cada tipo de interfaz.En funcin de la configuracin de la aplicacin, se instanciar una ventana o unapgina .aspx. Lo importante es no tener que incluir la seleccin de la vistaconcreta en el cdigo del controlador. Esto es, todo lo contrario de lo que hicimospara ilustrar el aspecto general de un controlador de aplicacin.

    - La transicin entre vistas: Esto resulta ms sencillo si le asignamos unidentificador nico a cada vista. Este identificador se traducir a la URLcorrespondiente en el caso de las aplicaciones web, mientras que en unaaplicacin Windows conducir a la creacin de un formulario de un tipo concreto.De hecho, el mapa de navegacin completo de una aplicacin puede almacenarsecomo un documento XML fcilmente modificable que describa el diagrama deestados de cada caso de uso del sistema.

    - El mantenimiento del estado de las tareas realizadas por el usuario: Lo mssencillo es que el estado de la aplicacin se mantenga en memoria o como partedel estado de la aplicacin web. En ocasiones, no obstante, puede interesaralmacenar el estado del controlador de forma permanente (en una base de datos,por ejemplo) para permitir que el usuario pueda reanudar tareas que dejase amedias en sesiones anteriores.

    139ASP.NET en la prctica

    http://csharp.ikor.org/

  • Aspecto visual de la aplicacin

    En el apartado anterior hemos visto distintas formas de organizar las partes de nuestraaplicacin relacionadas con la interfaz de usuario. Las decisiones de diseo tomadas nosayudan a mejorar la calidad del diseo interno de nuestra aplicacin, si bien esas decisionesno son visibles desde el exterior. De hecho, a la hora de desarrollar una aplicacin, resultarelativamente fcil olvidar algunos de los factores que influyen decisivamente en lapercepcin que tiene el usuario de nuestra aplicacin. Al fin y al cabo, para el usuario, eldiseo de la aplicacin es el diseo de su interfaz. Y en este caso nos referimosexclusivamente al aspecto visual de la aplicacin, no al diseo modular de su capa msexterna. De ah la importancia que tiene conseguir un aspecto visual coherente en nuestrasaplicaciones (aparte de un comportamiento homogneo que facilite su uso por parte delusuario).En este apartado, veremos cmo se pueden utilizar distintas estrategias para conseguir ennuestras aplicaciones un aspecto visual consistente. Adems, lo haremos intentando evitarcualquier tipo de duplicacin, ya que la existencia de fragmentos duplicados en distintaspartes de una aplicacin no hace ms que dificultar su mantenimiento. Por otro lado, tambinnos interesa separar la implementacin de nuestra implementacin de los detallesrelacionados con el diseo grfico de la interfaz de usuario, de forma que sta se puedamodificar libremente sin afectar al funcionamiento de la aplicacin.

    Cualquier aplicacin web, sea del tipo que sea, suele constar de distintas pginas. Esaspginas, habitualmente, compartirn algunos elementos, como pueden ser cabeceras, pies depgina, mens o barras de navegacin. Por lo general, en el diseo de la aplicacin se crearun boceto de la estructura que ha de tener la interfaz de la aplicacin, tal como se muestra enla figura.

    140 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • El espacio disponible en la interfaz de usuario se suele distribuir de lamisma forma para todas las pginas de la aplicacin web.

    En la creacin de sitios web, la distribucin del espacio disponible para los distintoscomponentes de las pginas se puede efectuar, en principio, de dos formas diferentes:utilizando marcos (frames) para cada una de las zonas en las que dividamos el espaciodisponible, o empleando tablas con una estructura fija que proporcione coherencia a lasdistintas pginas de nuestra aplicacin. Si utilizamos marcos, cada marco se crea como unapgina HTML independiente. En cambio, si optamos por usar tablas, cada pginas deberincluir repetidos los elementos comunes a las distintas pginas. Si nuestro anlisis se quedaseah, obviamente nos decantaramos siempre por emplear marcos.

    Desgraciadamente, el uso de marcos tambin presenta inconvenientes. En primer lugar, unapgina creada con marcos no se ver igual siempre: en funcin del navegador y del tamaodel tipo de letra que haya escogido el usuario, una pgina con marcos puede resultarcompletamente inutilizable. En segundo lugar, si los usuarios no siempre acceden a nuestraspginas a travs de la pgina principal, como puede suceder si utilizan los enlacesproporcionados por un buscador, slo vern en su navegador el contenido de uno de losmarcos. En este caso, no podrn navegar por las distintas pginas de nuestro sistema sielementos de la interfaz como la barra de navegacin se muestran en marcos independientes.

    Las desventajas mencionadas de los marcos han propiciado que, casi siempre, las interfacesweb se construyan utilizando tablas. Desde el punto de vista del programador, esto implicaque determinados elementos de la interfaz aparecern duplicados en todas las pginas de unaaplicacin, por lo que se han ideado distintos mecanismos mediante los cuales se puedengenerar dinmicamente las pginas sin necesidad de que fsicamente existan elementosduplicados.

    141ASP.NET en la prctica

    http://csharp.ikor.org/

  • Filtros con mdulos HTTPLa primera idea que se nos puede ocurrir es interceptar todas las solicitudes que llegan alservidor HTTP, de tal forma que podamos realizar tareas de preprocesamiento opostprocesamiento sobre cada solicitud HTTP. En ASP.NET, esto se puede realizar utilizandomdulos HTTP.

    Los mdulos HTTP funcionan como filtros que reciben las solicitudes HTTP antes de questas lleguen a las pginas ASP.NET. Dichos mdulos han de ser completamenteindependientes y este hecho permite que se puedan encadenar varios mdulos HTTP yconstruir filtros complejos por composicin. Usualmente, estos mdulos se utilizan pararealizar tareas a bajo nivel, como puede ser el manejo de distintos juegos de caracteres, el usode tcnicas criptogrficas, la compresin y decompresin de datos, la codificacin ydecodificacin de URLs, o la monitorizacin del funcionamiento del sistema. No obstante,tambin se pueden utilizar como "decoradores", para aadirle funcionalidad de formatransparente a las pginas ASP.NET a las que accede el usuario. Sin tener que modificar laspginas en s, que seguirn siendo independientes, se puede hacer que los mdulos HTTP seencarguen de las tareas comunes a todas las pginas de una aplicacin web.

    Entre las ventajas de los mdulos HTTP destaca su independencia, al ser totalmenteindependientes del resto de la aplicacin. Esta independencia les proporciona una granflexibilidad, ya que pueden combinarse libremente distintos mdulos HTTP. Adems, permitesu instalacin dinmica en una aplicacin, algo conocido como hot deployment en ingls.Finalmente, al ser componentes completamente independientes, son ideales para sureutilizacin en distintas aplicaciones. Un claro ejemplo de esto es el mduloSessionStateModule, que se encarga del mantenimiento de las sesiones de usuario entodas las aplicaciones web ASP.NET.

    ASP.NET proporciona una serie de eventos que se producen durante el procesamiento de unasolicitud HTTP a los que se pueden asociar fragmentos de cdigo. Simplemente, tendremosque crear un mdulo HTTP, que no es ms que una clase que implemente la interfazIHttpModule. Dicha clase incluir un mtodo Init en el que indicaremos los eventos queestemos interesados en capturar. El siguiente ejemplo muestra cmo podemos aadir lo quequeramos al comienzo y al final de la respuesta generada por nuestra aplicacin:

    using System;using System.Web;

    public class DecoratorModule : IHttpModule{public void Init (HttpApplication application){application.BeginRequest += new EventHandler(this.BeginRequest);application.EndRequest += new EventHandler(this.EndRequest);

    }

    142 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • private void BeginRequest (Object source, EventArgs e){HttpApplication application = (HttpApplication)source;HttpContext context = application.Context;context.Response.Write("Cabecera");

    }

    private void EndReq uest (Object source, EventArgs e){HttpApplication application = (HttpApplication)source;HttpContext context = application.Context;context.Response.Write(" Berzal, Cortijo, Cubero");

    }

    public void Dispose(){}

    }

    Una vez que tengamos implementado nuestro mdulo HTTP, lo nico que nos falta esincluirlo en la seccin httpModules del fichero de configuracin Web.config para quese ejecute en nuestra aplicacin web.

    donde DecoratorModule es el nombre de la clase que implementa el mdulo ybiblioteca es el nombre del assembly que contiene dicha clase (esto es,biblioteca.dll).

    Al ejecutarse siempre que se recibe una solicitud HTTP, y conel objetivo de evitar que se conviertan en un cuello de botellapara nuestras aplicaciones, es esencial que los mdulos HTTPsean eficientes.

    La directiva #includeUtilizando mdulos HTTP se puede conseguir que nuestras pginas ASP.NET le lleguen alusuario como una parte de la pgina web que se visualiza en su navegador. Lo mismo sepodra lograr si se crean controles por composicin que representen la cabecera, la barra denavegacin, el men o el pie de las pginas. En este caso, no obstante habr que colocar amano dichos controles en cada una de las pginas de la aplicacin, lo que resulta ms tedioso

    143ASP.NET en la prctica

    http://csharp.ikor.org/

  • y propenso a errores.

    Afortunadamente, ASP.NET nos ofrece un mecanismo ms sencillo que nos permiteconseguir el mismo resultado sin interferir el en desarrollo de las distintas pginas de unaaplicacin. Nos referimos a la posibilidad de incluir en la pgina .aspx un comentario con ladirectiva #include al ms puro estilo del lenguaje de programacin C. Este mecanismo, encierto modo, ya lo estudiamos cuando analizamos el uso de controladores de pgina enASP.NET y, en su versin ms bsica, su utilizacin se puede resumir en los siguientes pasos:

    - Se crean las partes comunes de las pginas en ficheros HTML independientes.

    - Se implementan las distintas pginas de la aplicacin como si se tratase depginas independientes.

    - Se incluyen las directivas #include en el lugar adecuado de las pginas.aspx.

    Por ejemplo, puede que deseemos aadir a una pgina web la posibilidad de que el visitantenos enve ficheros a travs de la web, lo que puede ser til en una aplicacin web para laorganizacin de un congreso o para automatizar la entrega de prcticas de una asignatura. Elformulario en s ser muy simple, pero nos gustara que quedase perfectamente integrado conel resto de las pginas web de nuestro sistema. En ese caso, podemos crear un ficheroheader.inc con la cabecera completa de nuestras pginas y otro fichero footer.inccon todo lo que aparece al final de nuestras pginas. En vez de incluir todo eso en nuestrapgina .aspx, lo nico que haremos ser incluir las directivas #include en los lugarescorrespondientes:

    ...

    Esta estrategia de implementacin es la ideal si las partes comunes de nuestras pginas sonrelativamente estticas. Si no lo son, lo nico que tenemos que hacer es crear una jerarqua decontroladores de pgina, tal como se describi cuando estudiamos el uso del modelo MVC enASP.NET.

    144 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • Aspecto visual de un formulario ASP.NET creado para la organizacin deun congreso. El fichero .aspx slo incluye las directivas #include y los

    controles propios del formulario. El aspecto visual final es el resultado decombinar el sencillo formulario con los detalles de presentacin de la

    pgina, que se especifican en los ficheros header.inc y footer.inc.

    PlantillasEn vez de que cada pgina incluya los detalles correspondientes a una plantilla general,podemos seguir la estrategia opuesta: crear una plantilla general en la cual se va sustituyendoen contenido manteniendo el aspecto general de la pgina. Para implementar esta estrategia enASP.NET, se nos ofrecen dos opciones: usar una pgina maestra o utilizar un control maestro.

    Pgina maestraEl uso de una pgina maestra se puede considerar como una forma de crear un controlador

    145ASP.NET en la prctica

    http://csharp.ikor.org/

  • MVC de aplicacin. El usuario siempre acceder a la misma pgina .aspx pero su contenidovariar en funcin del estado de la sesin. En la pgina maestra se reserva un espacio paramostrar un control u otro en funcin de la solicitud recibida. El evento Page_Load de lapgina maestra contendr, entonces, algo similar a lo siguiente:

    void Page_Load (object sender, System.EventArgs e){Control miControl = LoadControl ("fichero.cs.ascx");

    this.Controls.Add (miControl);}

    En el cdigo de la pgina maestra se tendr que decidir cul es el control concreto que semostrar en el espacio reservado al efecto. Mantener el aspecto visual de las pginas de laaplicacin es una consecuencia directa de la forma de implementar la aplicacin, igual que elhecho de que no se pueden utilizar los mecanismos proporcionados por ASP.NET pararestringir el acceso a las distintas partes de la aplicacin (por el simple hecho de que siemprese accede a la misma pgina). Adems, como las solicitudes han de incluir la informacinnecesaria para decidir qu pgina mostrar, este hecho hace especialmente vulnerable a nuestraaplicacin frente a posibles ataques. Deberemos ser especialmente cuidadosos para que unusuario nunca pueda acceder a las partes de la aplicacin que se supone no puede ver.

    Control maestro

    Para evitar los inconvenientes asociados a la creacin de una pgina maestra, se puede utilizarun control maestro que se incluya en distintas pginas ASP.NET. El control maestro realizalas mismas tareas que la pgina maestra, salvo que, ahora, el usuario accede a distintaspginas .aspx.

    El control maestro se crea como cualquier otro control definido por el usuario en ASP.NET, sibien ha de definir el aspecto visual general de las pginas de nuestra aplicacin e incluir unazona modificable. En esta zona modificable, que puede ser una celda de una tabla, sevisualizar el contenido que cambia dinmicamente de una pgina a otra de la aplicacin.

    La aplicacin, por tanto, constar de un conjunto de pginas .aspx, cada una de las cualesincluye una instancia del control maestro. Al acceder a una pgina, en el evento Form_Load,se establecer el control concreto que ha de mostrar el control maestro.

    146 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • Configuracin dinmica de la aplicacin

    Los captulos anteriores sirvieron para que nos familiarizsemos con la construccin deaplicaciones web en la plataforma .NET. En las secciones anteriores vimos cmo se puedenorganizar las distintas partes de una aplicacin web directamente relacionadas con la interfazde usuario. Por otro lado, analizamos distintas formas de crear aplicaciones web consistentesy homogneas, adems de fcilmente mantenibles. Ahora, ha llegado el momento de dotar decontenido a las pginas .aspx que conforman nuestras aplicaciones ASP.NET.

    Los controles incluidos como parte de la biblioteca de clases de la plataforma .NET ofrecenun mecanismo conocido con el nombre de "enlace de datos" [data binding] mediante el cualpodemos asociarles valores de forma dinmica a sus propiedades. Este mecanismo nospermite, por ejemplo, mostrarle al usuario conjuntos de datos de una forma flexible, cambiarlas opciones existentes a su disposicin o modificar el aspecto de la aplicacin en funcin delas preferencias del usuario, todo ello sin tener que modificar una sola lnea de cdigo eindependientemente de dnde provengan los datos que permiten modificar las propiedades delos controles de nuestra aplicacin. Esos datos pueden provenir de una simple coleccin, deun fichero XML o de un DataSet que, posiblemente, hayamos obtenido a partir de los datosalmacenados en una base de datos convencional.

    A grandes rasgos, se puede decir que existen tres formas diferentes de asociarles valores a laspropiedades de los controles de la interfaz grfica:

    - Como primera opcin, podemos especificar los valores que deseemos comoatributos de las etiquetas asociadas a los controles (esto es, dentro de ). Si estamos utilizando un entorno de desarrollo como el Visual Studio .NET,estos valores los podemos fijar directamente desde la ventana de propiedades.Obviamente, as se le asignan valores a las propiedades de los controles de formaesttica, no dinmica.

    - Una alternativa consiste en implementar fragmentos de cdigo que hagan uso delmodelo orientado a objetos asociado a los controles de nuestros formularios. Estoes, como respuesta a algn evento, como puede ser el evento Form_Load de unformulario web, establecemos a mano los valores adecuados para las propiedadesque deseemos modificar. sta es una opcin perfectamente vlida para rellenarvalores o listas de valores cuando stos se obtienen a partir del estado de la sesinde usuario.

    - Por ltimo, la alternativa ms flexible consiste en obtener de alguna fuente dedatos externa los valores que vamos a asociar a una propiedad de un control. Estaestrategia es extremadamente til para simplificar la implementacin ensituaciones ms complejas. La plataforma .NET nos ofrece un mecanismo,conocido con el nombre de "enlace de datos", que nos facilita el trabajo en este

    147ASP.NET en la prctica

    http://csharp.ikor.org/

  • contexto. En primer lugar, debemos disponer de un objeto que contenga losvalores en cuestin, ya sea una simple coleccin (como un vector, instancia de laclase Array en .NET) o algo ms sofisticado (como un DataSet de los usadosen ADO.NET). A continuacin, simplemente tenemos que asociarle ese objeto ala propiedad adecuada del control. El enlace de datos se realizarautomticamente cuando invoquemos el mtodo DataBind asociado al control.

    El mecanismo de enlace de datos ofrece varias ventajas con respecto a la forma tradicional derellenar dinmicamente los valores de las propiedades de un control (que, recordemos,consiste en implementar las asignaciones correspondientes). La primera de ellas es que nospermite separar claramente el cdigo de nuestra aplicacin de la interfaz de usuario. Al crearun nivel extra de indireccin, se desacoplan los conjuntos de valores de las propiedades de loscontroles a las que luego se asignan. Adems, el mecanismo est implementado de tal formaque podemos enlazar las propiedades de un control a una amplia variedad de fuentes de datos.Es decir, los valores pueden provenir de colecciones (de cualquier tipo de los definidos en labiblioteca de clases .NET, desde Array hasta Hashtable), pero tambin pueden provenirde conjuntos de datos ADO.NET (como el verstil DataSet, la tabla DataTable, la vistaDataView o el eficiente DataReader), los cuales, a su vez, pueden construirse a partir deuna consulta sobre una base de datos relacional o a partir de un fichero XML. De hecho,cualquier objeto que implemente la interfaz IEnumerable puede usarse como fuente dedatos. La existencia de esta interfaz permite que, vengan de donde vengan los valores, laimplementacin del enlace sea siempre la misma, lo que simplifica enormemente elmantenimiento de la aplicacin cuando cambian nuestras fuentes de datos.

    Otro aspecto que siempre debemos tener en mente es que el enlace no es del todo dinmico enASP.NET. A diferencia de los formularios Windows, los cambios que se produzcan en loscontroles ASP.NET que muestran los datos no se propagan al conjunto de datos. En realidad,el mecanismo de enlace de datos en ASP.NET se limita a rellenar las propiedades quehayamos enlazado una nica vez. Si, por el motivo que sea, nuestro conjunto de datos cambiay queremos que ese cambio se refleje en la interfaz de usuario, seremos nosotros los nicosresponsables de hacer que los cambios se reflejen en el momento adecuado.De forma anloga a las etiquetas JSP que se emplean para construir aplicaciones web conJava, en las pginas ASP.NET se pueden incluir expresiones de enlace de datos de la forma. Un poco ms adelante veremos algunos ejemplos que ilustrarn suutilizacin en la prctica. En las siguientes secciones, comenzaremos a ver cmo funciona elenlace de datos en una amplia gama de situaciones.

    El mecanismo de enlace de datos se puede utilizar tanto en laconstruccin de aplicaciones Windows como en la creacinde aplicaciones web con ASP.NET. No obstante, en esteltimo caso, el enlace es unidireccional. Los formulariosWindows permiten automatizar las actualizaciones en elconjunto de datos. En ASP.NET, las actualizacionestendremos que implementarlas manualmente.

    148 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • Listas de opcionesComencemos por el caso ms sencillo (y comn) que se nos puede presentar a la hora de crearla interfaz de usuario de nuestra aplicacin. Es habitual que, en un formulario, determinadoscampos puedan slo tomar un valor dentro de un conjunto de valores preestablecido, comopueden ser el estado civil o la nacionalidad de una persona, el mtodo de pago o la forma deenvo de un pedido. En el caso de ASP.NET, para este tipo de campos utilizaremos alguno delos siguientes controles:

    - un conjunto de botones de radio asp:RadioButtonList, para mostrar unconjunto de opciones mutuamente excluyentes,

    - un conjunto de botones de comprobacin asp:CheckBoxList, cuando lasdistintas opciones no son mutuamente excluyentes,

    - una lista convencional de tipo asp:Listbox, o, incluso,

    - una lista desplegable de valores asp:DropDownList (cuando no dispongamosde demasiado espacio en pantalla).

    Sea cual sea el control utilizado, los valores permitidos se definen utilizando componentes detipo asp:ListItem. Si, por ejemplo, desesemos mostrar una lista de opciones quepermitiese al usuario seleccionar una zona geogrfica determinada, podramos escribir a manolo siguiente (o emplear el editor de propiedades para la coleccin Items del controlcorrespondiente a la lista):

    Sin embargo, resulta mucho ms adecuado utilizar una fuente de datos independiente pararellenar la lista. Si no, qu sucedera cuando nuestra aplicacin abarcase un rea geogrfica

    149ASP.NET en la prctica

    http://csharp.ikor.org/

  • ms amplia? Tendramos que ir modificando, una por una, todas las listas de este tipo quetuvisemos repartidas por la aplicacin.

    El mecanismo de enlace de datos nos es extremadamente til en estas situaciones, ya que nospermite rellenar las listas de valores permitidos a partir de los datos obtenidos de algunafuente externa que tengamos a nuestra disposicin. Si la lista de opciones se tuviese quemodificar, slo habra que modificar la fuente de datos, que debera ser nica, y no loselementos de la lista en todos los lugares donde apareciesen. En definitiva, se separa porcompleto la interfaz de la aplicacin de los datos con los que trabaja la aplicacin, con lo quesu mantenimiento resultar ms sencillo.

    Ahora veremos cmo podemos rellenar dinmicamente una lista de opciones mostrada a partirde distintas fuentes de datos. En concreto usaremos distintos tipos de colecciones y ficherosXML que nos permitirn configurar dinmicamente muchas partes de nuestras aplicaciones.

    Vectores simples: Array y ArrayList

    La clase System.Array es la clase que representa un vector en la plataforma .NET y sirvecomo base para todas las matrices en C#. Por su parte, la claseSystem.Collections.ArrayList nos permite crear vectores de tamao dinmico.Ambas clases implementan el mismo conjunto de interfaces (IList, ICollection,IEnumerable, ICloneable) y pueden utilizarse para enlazar colecciones de datos a laspropiedades de un control.

    Al cargar la pgina ASP.NET, en el evento Form_Load, obtenemos la lista de valores y se laasociamos a la propiedad DataSource de la lista de opciones. Para rellenar la lista deopciones con los valores incluidos en la coleccin de valores, no tenemos ms que llamar almtodo DataBind() del control:

    private void Page_Load(object sender, System.EventArgs e){if (!Page.IsPostBack) {

    ArrayList list = new ArrayList();

    list.Add("Granada");list.Add("Almera");list.Add("Mlaga");list.Add("Jan");list.Add("Crdoba");list.Add("Sevilla");list.Add("Cdiz");list.Add("Huelva");list.Sort();

    provincia.DataSource = list;provincia.DataBind();

    }}

    150 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • Lista de opciones creada dinmicamente a partir de una coleccin.

    Para simplificar el ejemplo, en el mismo evento Form_Load hemos creado la lista de tipoArrayList y hemos aadido los valores correspondientes a las distintas opciones con elmtodo Add(). Una vez que tenemos los elementos en la lista, los hemos ordenado llamandoal mtodo Sort(). Si hubisemos querido mostrarlos en orden inverso, podramos haberusado el mtodo Reverse() una vez que los tuvisemos ordenados.

    Finalmente, el enlace de la coleccin con el control se realiza mediante la propiedadDataSource del control y la llamada al mtodo DataBind() cuando queremos rellenar lalista. En este caso, los elementos del vector se utilizan como texto (Text) y como valor(Value) asociado a los distintos elementos ListItem de la lista, si bien esto no tiene porqu ser as siempre, como veremos a continuacin.

    Pares clave-valor: Hashtable y SortedList

    Generalmente, cuando utilizamos listas de opciones en la interfaz de usuario, una cosa es elmensaje que vea el usuario asociado a cada opcin y otra muy distinta es el valor queinternamente le asignemos a la opcin seleccionada. El mensaje vara, por ejemplo, si nuestra

    151ASP.NET en la prctica

    http://csharp.ikor.org/

  • aplicacin est localizada para varios idiomas, mientras que el valor asociado a la opcin serfijo. Incluso aunque nuestra aplicacin slo funcione en castellano, es buena idea que, en lasopciones de una lista, texto y valor se mantengan independientes. El texto suele ser msdescriptivo y puede variar con mayor facilidad. Adems, no nos gustara que un simplecambio esttico en el texto de una opcin hiciese que nuestra aplicacin dejase de funcionarcorrectamente.

    Cuando queremos asignarle dos valores a las propiedades de cada una de las opciones de unalista, un simple vector no nos es suficiente. Hemos de utilizar colecciones que almacenenpares clave-valor, como es el caso de las colecciones que implementan la interfazIDictionary, como pueden ser Hashtable o SortedList.

    Una tabla hash, implementada en la biblioteca de clases .NET por la claseSystem.Collections.Hashtable, es una estructuras de datos que contiene paresclave-valor y est diseada para que el acceso a un valor concreto sea muy eficiente, O(1)utilizando la terminologa habitual en el anlisis de algoritmos. En nuestro ejemplo de la listade provincias, podramos utilizar una tabla hash para almacenar como clave el cdigocorrespondiente a una provincias y como valor su nombre completo. La clave la asociamos alvalor de la opcin (DataValueField) y, el nombre, al texto de la etiqueta asociada a laopcin (DataTextField):

    private void Page_Load(object sender, System.EventArgs e){if (!Page.IsPostBack) {

    Hashtable table = new Hashtable();

    table.Add("GR", "Granada");table.Add("AL", "Almera");table.Add("MA", "Mlaga");table.Add("J", "Jan");table.Add("CO", "Crdoba");table.Add("SE", "Sevilla");table.Add("CA", "Cdiz");table.Add("HU", "Huelva");

    provincia.DataSource = table;provincia.DataValueField="Key";provincia.DataTextField="Value";provincia.DataBind();

    }}

    El nico inconveniente de usar tablas hash es que no se puede elegir el orden de presentacinde los elementos de la lista. Para que las opciones de la lista aparezcan ordenadas tenemosque usar una coleccin como la proporcionada por la claseSystem.Collections.SortedList, que se emplea exactamente igual que la tablahash y mantiene sus elementos ordenados de forma automtica.

    152 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • Ficheros XML

    Hoy en da, la opcin ms comnmente utilizada para configurar dinmicamente unaaplicacin consiste en la utilizacin de ficheros XML auxiliares que contengan los datosnecesarios para configurar adecuadamente una aplicacin. A partir de datos guardados enficheros XML, se puede personalizar el men de opciones visible para un usuario en funcinde sus permisos, cambiar el aspecto visual de las pginas de la aplicacin en funcin de laspreferencias de un usuario concreto o, incluso, instalar distintas "versiones" de una mismaaplicacin para distintos clientes.

    En el caso de una aplicacin web ASP.NET, para leer un fichero XML slo tenemos queteclear lo siguiente:

    DataSet dataset = new DataSet();dataset.ReadXml ( Server.MapPath("fichero.xml") );

    La funcin ReadXml() construye un conjunto de datos a partir del contenido de un ficheroXML. La funcin Server.MapPath() es la que nos permite buscar el ficherodinmicamente en el lugar adecuado; esto es, en el directorio donde tengamos instalada laaplicacin web.

    Si volvemos a nuestro ejemplo simpln, el de la lista de provincias, podemos crear un ficheroXML auxiliar para rellenar la lista de opciones a partir de dicho fichero. Este fichero puedetener el siguiente formato:

    ALAlmera

    ...

    GRGranada

    ...

    Una vez que tenemos el fichero con los datos, lo nico que tenemos que hacer en el cdigo denuestra aplicacin es cargar dicho fichero en un conjunto de datos creado al efecto y enlazarel conjunto de datos al control que representa la lista de opciones. El resultado es bastantesencillo y cmodo de cara al mantenimiento futuro de la aplicacin:

    153ASP.NET en la prctica

    http://csharp.ikor.org/

  • private void Page_Load(object sender, System.EventArgs e){DataSet dataset;

    if (!Page.IsPostBack) {dataset = new DataSet();dataset.ReadXml(MapPath("provincias.xml"));

    provincia.DataSource = dataset;provincia.DataValueField="id";provincia.DataTextField="nombre";provincia.DataBind();

    }}

    Obsrvese cmo se realiza en enlace de datos con los elementos del fichero XML: elelemento id se hace corresponder con el valor asociado a una opcin de la lista, mientras queel elemento nombre ser lo que se muestre como etiqueta asociada a cada opcin.

    Caso prctico

    En captulos anteriores pusimos como ejemplo una sencilla lista de contactos pero nosdejamos en el tintero cmo se crea dinmicamente la lista desplegable a partir de la cualpodemos ver los datos concretos de cada uno de nuestros contactos. Ahora, ya estamos endisposicin de ver cmo se construye dinmicamente esa lista para completar nuestra sencillaaplicacin de manejo de una agenda de contactos.

    El formulario que nos permite ver los datos de una lista de contactos.

    Antes de ver cmo se rellena esa lista desplegable, no obstante, nos hacen falta algunasrutinas auxiliares que nos permitan leer y escribir los datos asociados a cada contacto. Paralograrlo, podemos utilizar las facilidades que nos ofrece la plataforma .NET para serializarobjetos en XML, algo que podemos implementar de forma genrica en una clase auxiliar:

    154 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • using Systemusing System.IO;using System.Xml;using System.Xml.Serialization;

    public class Utils{// Serializacin

    public static void Serialize (object obj, string filename){XmlSerializer serializer = new XmlSerializer (obj.GetType());TextWriter writer = new StreamWriter (filename, false,

    System.Text.Encoding.GetEncoding("ISO-8859-1"));serializer.Serialize (writer, obj);writer.Close();

    }

    // Deserializacin

    public static object Deserialize (Type type, string filename){object obj = null;XmlSerializer serializer = new XmlSerializer (type);TextReader stream = new StreamReader (filename,

    System.Text.Encoding.GetEncoding("ISO-8859-1"));XmlReader reader = new XmlTextReader(stream);

    if (serializer.CanDeserialize(reader))obj = serializer.Deserialize (reader);

    reader.Close();stream.Close();

    return obj;}

    }

    Las utilidades definidas en la clase anterior, cuando las aplicamos sobre objetos de tipoContact (la clase que utilizamos para encapsular los datos que tenamos de un contactoconcreto), dan lugar a ficheros XML de la siguiente forma:

    [email protected] casa de su dueoYorkshire Terrierimage/mota.jpg

    155ASP.NET en la prctica

    http://csharp.ikor.org/

  • Ahora bien, volvamos a nuestra aplicacin web. Supongamos que los datos relativos anuestros contactos los almacenamos en un subdirectorio denominado contacts deldirectorio que aloja nuestra aplicacin web. Para leer desde un fichero XML los datos de uncontacto, lo nico que tendremos que hacer es escribir algo similar a lo siguiente:

    private Contact GetContact (string filename){FileInfo fi = new FileInfo

    ( Server.MapPath("contacts")+"/"+filename );

    return (Contact) Utils.Deserialize(typeof(Contact), fi.FullName );}

    Por tanto, ya sabemos cmo leer los datos de un contacto. Lo nico que nos falta es rellenar lalista desplegable de opciones que nos servir de ndice en nuestra agenda de contactos. Eso esalgo que podemos hacer fcilmente a partir de lo que ya sabemos:

    private void Page_Load(object sender, System.EventArgs e){DirectoryInfo di;SortedList list;FileInfo[] fi;Contact contact;

    if (!Page.IsPostBack) {

    list = new SortedList();

    di = new DirectoryInfo( Server.MapPath("contacts") );

    if (di!=null) {

    fi = di.GetFiles();

    foreach (FileInfo file in fi) {contact = GetContact( file.Name );list.Add(contact.Name, file.Name);

    }

    ContactList.DataSource = list;ContactList.DataTextField = "Key";ContactList.DataValueField = "Value";ContactList.DataBind();

    Header.Visible = false;ContactList.SelectedIndex = 0;

    }

    } else {UpdateUI();

    }}

    156 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • A partir del contenido del directorio donde almacenamos los datos, vemos los ficheros quehay y creamos una entrada en la lista desplegable. Para saber en cada momento cul es elcontacto cuyos datos hemos de mostrar, lo nico que tenemos que hacer es ver cul es laopcin seleccionada de la lista desplegable. Dicha opcin viene dada por la propiedadSelectedItem de la lista:

    private void UpdateUI (){string filename;Contact contact;

    if (ContactList.SelectedItem!=null) {filename = ContactList.SelectedItem.Value;contact = GetContact(filename);LabelContact.Text = ContactList.SelectedItem.Text;ShowContact(contact);

    }}

    Finalmente, slo nos queda hacer que, siempre que el usuario seleccione una de las opcionesde la lista, los datos que se muestren correspondan a la opcin seleccionada. Para lograrlo,slo tenemos que redefinir la respuesta de nuestro formulario al eventoSelectedIndexChanged de la lista desplegable:

    private void ContactList_SelectedIndexChanged(object sender, System.EventArgs e)

    {UpdateUI();

    }

    Con esto se completa la sencilla agenda de contactos que empezamos a construir hace un parde captulos al comenzar nuestro aprendizaje sobre ASP.NET. No obstante, an nos quedanalgunos temas por tratar, entre los que se encuentra la visualizacin de conjuntos de datos enlos formularios ASP.NET por medio de controles como los que se estudiarn en la siguienteseccin.

    Conjuntos de datosLa mayor parte de las aplicaciones trabajan con conjuntos de datos. Dado que es bastantenormal tener que mostrar un conjunto de datos en una tabla o en un informe, tambin lo esque la biblioteca de clases de la plataforma .NET incluya controles que permitan visualizarconjuntos de datos. En esta seccin veremos los tres controles que se utilizan con este fin enla plataforma .NET y mostraremos cmo se les pueden enlazar conjuntos de datos.

    157ASP.NET en la prctica

    http://csharp.ikor.org/

  • El control asp:Repeater

    La etiqueta asp:Repeater corresponde a un control ASP.NET que permite mostrar listasde una forma ms verstil que los controles vistos en la seccin anterior. El controlasp:Repeater, implementado por la claseSystem.Web.UI.WebControls.Repeater, permite aplicar una plantilla a lavisualizacin de cada uno de los elementos del conjunto de datos.Dichas plantillas, que deberemos crear a mano, especifican el formato en el que se mostrarcada elemento, usualmente mediante el uso de las etiquetas asociadas a la creacin de tablasen HTML. Para crear una tabla, se incluye la etiqueta de comienzo de la tabla y lacabecera de la misma en la plantilla HeaderTemplate, que corresponde a la cabeceragenerada por el control asp:Repeater antes de mostrar los datos. De forma anloga, laetiqueta de cierre de la tabla se incluye en la plantilla FooterTemplate delcontrol asp:Repeater. Por su parte, cada uno de los elementos del conjunto de datos semostrar tal como especifiquemos en la plantilla ItemTemplate, que estar delimitada porlas etiquetas HTML y , correspondientes a una fila de la tabla. Como mnimo,un control asp:Repeater debe incluir la definicin de la plantilla ItemTemplate.Todas las dems plantillas son opcionales.

    Veamos, en la prctica, cmo funciona el control asp:Repeater con el ejemplo quepusimos en la seccin anterior. En primer lugar, tenemos que aadir un controlasp:Repeater al formulario web con el que estemos trabajando. A continuacin, podemosobtener el conjunto de datos desde el fichero XML utilizado en el ltimo ejemplo de laseccin anterior. Dicho conjunto de datos hemos de enlazarlo al control asp:Repeater, loque conseguimos usando su propiedad DataSource:

    protected System.Web.UI.WebControls.Repeater provincia;...

    private void Page_Load(object sender, System.EventArgs e){

    if (!Page.IsPostBack) {DataSet dataset = new DataSet();dataset.ReadXml(MapPath("provincias.xml"));provincia.DataSource = dataset;provincia.DataBind();

    }}

    Por ltimo, hemos de especificar cmo se visualizar cada dato del conjunto de datos en elcontrol asp:Repeater, para lo cual no nos queda ms remedio que editar el cdigo HTMLde la pgina ASP.NET. Mediante el uso de plantillas definimos el aspecto visual de nuestroconjunto de datos:

    158 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • CdigoNombre

    Visualizacin de conjuntos de datos con asp:Repeater

    159ASP.NET en la prctica

    http://csharp.ikor.org/

  • El resultado de la ejecucin de nuestro formulario con el control asp:Repeater se muestraen la parte izquierda de la figura. Para entender su funcionamiento, debemos tener en cuentalo siguiente:

    - La plantilla se muestra al comienzo de la salida asociadaal control asp:Repeater. En este caso, lo nico que hace es crear la cabecerade la tabla.

    - Para cada elemento del conjunto de datos enlazado al asp:Repeater se utilizala plantilla . Esta plantilla la rellenamos con las etiquetasHTML correspondientes a la definicin de una fila de la tabla e incluimosexpresiones del tipo para visualizar los valores que toma campo en los elementos denuestro conjunto de datos.

    - Por ltimo, la plantilla se utiliza para finalizar la salidaasociada al control asp:Repeater, que muchas veces no es ms que cerrar laetiqueta con la que se abri la tabla.

    Obviamente, la tabla mostrada en la parte derecha de la figura anterior es mucho ms vistosaque la sobria tabla que se visualiza con las plantillas que hemos definido para el controlasp:Repeater. Para construir una tabla de este tipo, lo nico que tenemos que hacer esdefinir la plantilla opcional . Si incluimos el cdigoHTML necesario para utilizar distintos colores en y podemos conseguir que las filas de la tabla se muestrencon colores alternos, como en la figura, de forma que se mejore la legibilidad de los datos y elatractivo visual de la tabla. Como su propio nombre sugiere, la plantilla determina la visualizacin de elementos alternos delconjunto de datos. Cuando no se define, se utiliza para todos loselementos del conjunto de datos. Cuando se define, las filas pares e impares se mostrarn deforma distinta en funcin de lo que hayamos especificado en las plantillas y .

    Finalmente, el control asp:Repeater incluye la posibilidad de utilizar una quinta plantillaopcional: la plantilla . Esta plantilla se puede utilizar paradescribir lo que queremos que aparezca entre dos elementos del conjunto de datos.En resumen, el control asp:Repeater muestra los elementos de un conjunto de datosgenerando un fragmento de cdigo HTML a partir de las plantillas que hayamos definido. Enel caso ms sencillo, se define una nica plantilla, la plantilla . En el casoms complejo, se pueden utilizar hasta cinco plantillas que se utilizarn para generar la salidaen el siguiente orden: Header - Item - Separator - AlternatingItem -Separator - Item - ... - Footer.

    Una de las limitaciones del control asp:Repeater es que no admite cmodamente laimplementacin funciones de seleccin ni de edicin. Afortunadamente, en ASP.NET existen

    160 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • otros controles, que se pueden emplear para visualizar e incluso modificar conjuntos de datos.En concreto, nos referimos a los controles System.Web.UI.WebControls.DataListy System.Web.UI.WebControls.DataGrid que usaremos en los dos prximosapartados.

    El control asp:DataList

    El control asp:DataList es similar a asp:Repeater, si bien incluye por defecto unatabla alrededor de los datos. Adems, se puede disear su aspecto de forma visual desde eldiseador de formularios del Visual Studio .NET. Desde el diseador de formularios,podemos seleccionar el control asp:DataList y pinchar con el botn derecho del ratnpara acceder a las opciones de "Editar plantilla" incluidas en su men contextual. Desde ahpodemos definir una amplia gama de propiedades del control de forma visual.

    El control asp:DataList, adems de las cinco plantillas que ya mencionamos al hablar delcontrol asp:Repeater, incluye dos plantillas adicionales: SelectedItemTemplate yEditItemTemplate. Estas plantillas se usan, respectivamente, para resaltar el elementoseleccionado de la lista y permitir la edicin de los valores correspondientes a uno de loselementos del conjunto de datos.Volviendo al ejemplo de la lista de contactos, supongamos que deseamos mostrar,simultneamente, datos relativos a varios de nuestros contactos, sin tener que ir eligindolosuno a uno. Podemos usar un control de tipo asp:DataList y definir visualmente elformato de su plantilla ItemTemplate:

    Edicin visual del formato correspondiente a las plantillas de un controlasp:DataList

    En este caso, cada vez que se muestre un contacto, aparecer una etiqueta asp:Label consu nombre acompaada de un enlace asp:HyperLink en el que figurar su direccin decorreo electrnico. Mediante la opcin (DataBindings) que aparece en el editor de

    161ASP.NET en la prctica

    http://csharp.ikor.org/

  • propiedades de los controles, podemos enlazar el nombre y la direccin de correo con loscontroles correspondientes, tal como se muestra en la figura:

    Manualmente, tenemos que ir seleccionando las propiedades adecuadas de los controles,como puede ser la propiedad NavigateUrl del control asp:HyperLink, e indicar culesvan a ser los valores que se les van a asociar a dichas propiedades. En el caso de la propiedadNavigateUrl, escribiremos algo como lo siguiente:

    "mailto:"+DataBinder.Eval(Container.DataItem,"Email")

    Lo que hacemos visualmente desde el entorno de desarrollo se traduce internamente en unaplantilla similar a las que ya vimos al ver el funcionamiento del control asp:Repeater. Alfinal, nuestro fichero .aspx contendr algo como lo siguiente:

    (

    162 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • )

    Igual que siempre, lo nico que nos queda por hacer es obtener un conjunto de datos yasocirselo a la lista. Por ejemplo, podramos crear una tabla de datos a medida que contenganicamente aquellos datos que queremos mostrar en el control asp:DataList:

    DataTable dt = new DataTable();DataRow dr;int i;

    dt.Columns.Add(new DataColumn("Name", typeof(string)));dt.Columns.Add(new DataColumn("Email", typeof(string)));

    for (i=0; i

  • El control asp:DataGrid es bastante ms complejo que el control asp:DataList, sibien es cierto el entorno de desarrollo nos ayuda mucho para poder disear nuestra tabla deforma visual. Para crear las columnas de la tabla, hemos de seleccionar la opcin "Generadorde propiedades" del men contextual asociado al control. En la ventana que nos aparecepodemos definir las columnas que incluir nuestra tabla como columnas de tipo plantilla:

    Una vez que tenemos definidas las columnas de nuestra tabla, podemos editar las plantillasasociadas a ellas mediante la opcin "Editar plantilla" del men contextual asociado alDataGrid. En el caso de las columnas que contienen una simple etiqueta, el proceso escompletamente anlogo al que se utiliz en la seccin anterior al usar el control DataList.Primero, se crea la plantilla en s:

    164 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • La propiedad Text de etiqueta que aparece en la plantilla la enlazaremos con uno de losvalores contenidos en el conjunto de datos de la misma forma que siempre:

    DataBinder.Eval(Container.DataItem, "Name")

    Seleccionando la opcin "Terminar edicin de plantilla" del men contextual volvemos a lavista general de la tabla para poder editar la plantillas asociadas a las dems columnas. Unavez preparadas las plantillas correspondientes a todas las columnas, lo nico que nos falta porhacer es enlazar el control a un conjunto de datos (mediante su propiedad DataSource) einvocar al mtodo DataBind() para rellenar la tabla con los datos, igual que se hizo con elcontrol DataList.

    Antes de dar por cerrado este apartado, no obstante, veamos cmo se implementan enASP.NET dos de las funciones que con ms asiduidad se repiten en aplicaciones web que hande trabajar con conjuntos de datos: la posibilidad de seleccionar un subconjunto de los datos yla opcin de ordenar los datos de una tabla en funcin de los valores que aparecen en unacolumna.

    Seleccin de subconjuntos de datosCuando queremos darle la posibilidad al usuario de que seleccione algunos de los elementosde un conjunto de datos mostrado en una tabla, lo normal, cuando usamos aplicaciones web,es que se le aada a la tabla una columna en la que aparezca un control de tipo CheckBox:

    165ASP.NET en la prctica

    http://csharp.ikor.org/

  • La plantilla de la columna se crea exactamente igual que cualquier otra plantilla. En tiempo deejecucin, tal como se muestra en la siguiente figura, el control se repetir para cada una delos elementos del conjunto de datos mostrado en la tabla:

    Cuando queramos saber cules son los elementos del conjunto de datos que ha seleccionado elusuario, lo nico que tendremos que hacer es acceder secuencialmente a los elementos de tipoDataGridItem que componen el DataGrid en tiempo de ejecucin, tal como se muestraen el siguiente fragmento de cdigo:

    CheckBox cb;

    foreach (DataGridItem dgi in this.DataGridContacts.Items) {

    cb = (CheckBox) dgi.Cells[0].Controls[1];

    if (cb.Checked) {// Fila seleccionada

    }}

    Ordenacin por columnas

    Otra de las funciones que resultan bastante tiles al trabajar con tablas es la posibilidad deordenar su contenido en funcin de los valores que aparezcan en una columna determinada.

    166 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • Esta funcin resulta bastante vistosa y su implementacin es prcticamente trivial en el casodel control asp:DataGrid.

    Aunque se puede conseguir el mismo resultado modificando directamente el fichero .aspxcorrespondiente a la pgina ASP.NET donde est incluida la tabla y, de hecho, el proceso sepuede realizar a mano sin demasiada dificultad, aqu optaremos por aprovechar las facilidadesque nos ofrece el Visual Studio .NET a la hora de manipular directamente el controlasp:DataGrid desde el propio editor de formularios web.

    En primer lugar, debemos asegurarnos de que nuestro control tiene habilitada la opcin"Permitir ordenar" [AllowSorting] que aparece en la pestaa "General" del generador depropiedades del DataGrid:

    Esto se traduce, simplemente, en la inclusin del atributo AllowSorting en el controlasp:DataGrid que aparece en el fichero .aspx:

    A continuacin, hemos de seleccionar las expresiones de ordenacin para las distintascolumnas de nuestra tabla, algo que tambin podemos hacer desde el generador depropiedades del DataGrid:

    167ASP.NET en la prctica

    http://csharp.ikor.org/

  • Igual que antes, la seleccin se traduce en la inclusin de un atributo: SortExpression.En este caso, el atributo aparece asociado a las plantillas correspondientes a las distintascolumnas de la tabla:

    ...

    En cuanto lo hacemos, automticamente cambia el aspecto de la cabecera de la tabla. Dondeantes aparecan simples etiquetas en las cabeceras de las columnas, ahora se muestran enlacessobre los que se puede pinchar:

    168 Desarrollo Profesional de Aplicaciones con C#

    Fernando Berzal, Francisco J. Cortijo & Juan Carlos Cubero

  • Lo nico que nos falta por hacer es implementar el cdigo necesario para realizar laordenacin de la tabla cuando el usuario pincha sobre los enlaces que encabezan las columnas"ordenables" de la tabla. Eso lo haremos como respuesta al evento SortCommand:

    private void DataGridMessages_SortCommand (object source,System.Web.UI.WebControls.DataGridSortCommandEventArgs e)

    {DataTable dt = (DataTable)Session["contactTable"];

    DataView dv = new DataView(dt);dv.Sort = e.SortExpression;

    DataGridContacts.DataSource = dv;DataGridContacts.DataBind();

    }

    Lo nico que tenemos que hacer es crear una vista sobre la tabla de datos y ordenarla. Unavez que tenemos los datos ordenados, enlazamos la vista al control e invocamos al mtodoDataBind para que se refresquen los datos de la tabla con los datos ordenados de la vistarecin construida.

    Paginacin en ASP.NETCuando los conjuntos de datos son grandes, lo normal es queslo le mostremos al usuario una parte de los datos y le demosla posibilidad de moverse por el conjunto de datos completo.Es lo que se conoce con el nombre de paginacin.

    La paginacin consiste, bsicamente, en no trabajar con msdatos de los que resulten estrictamente necesarios. En el casode las aplicaciones web, esto se traduce en una mejora en laescalabilidad de las aplicaciones al no tener que transmitirms que aquellos datos que los que se muestran en una pginaal usuario.

    Como no poda ser de otra forma, el control DataGridfacilita la posibilidad de usar paginacin (sin ms que ponerla propiedad AllowPaging a true). De hecho, podemosespecificar el nmero de datos que queremos mostrar porpgina (PageSize), as como dnde y cmo tienen queaparecer los botones que se usarn para navegar por elconjunto de datos (PagerStyle). Cuando se cambia depgina, se produce el evento OnPageIndexChanged, quees el que debemos interceptar para mostrar los datosadecuados.

    169ASP.NET en la prctica

    http://csharp.ikor.org/

  • Formularios de manipulacin de datos

    Aparte de mostrar datos, las aplicaciones tambin tienen que manipularlos: realizarinserciones, actualizaciones y borrados. Por tanto, a la hora de implementar la interfaz deusuario, una de las tareas ms habituales con las que ha de enfrentarse un programador es lacreacin de formularios de manipulacin de datos, tambin conocidos como formulariosCRUD porque esas son las iniciales en ingls de las cuatro operaciones bsicas que realizan(creacin, lectura, actualizacin y borrado de datos). Dada su importancia prctica, este es eltema con el que terminaremos nuestro recorrido por ASP.NET.

    Usualmente, los formularios de manipulacin de datos se construyen en torno a trese