ASP.NET TEMA 1: PRIMEROS PASOS PROCESAMIENTO DINÁMICO Internet se basa en el modelo cliente−servidor. Modelo petición − respuesta: Un equipo contiene información (servidor) y otro solicita la información (cliente). Es estático. No puede proporcionar información dinámica o procesamiento. (HTML) Un equipo contiene información (servidor) y otro solicita la información (cliente) dinámicamente. (ASP). El servidor analiza la información antes de enviarla. Modelo controlado por eventos: El servidor espera a que algo ocurra en el cliente para entrar en acción y ejecutar alguna tarea. (ASP.NET) ASP.NET sabe lo que ocurre en el cliente porque se basa en el procesamiento en el cliente para simular un modelo controlado por eventos. Procesamiento en el cliente Código de programación en una página HTML que el explorador web ejecuta. <html> <head> <script language="JavaScript"> <!−− alert("¡Hola, chicos!"); −−> </script> </head> <body> ¡Bienvenidos a mi clase! </body> </html> 1 Las etiquetas <script> encierran una porción de código que contiene comandos para el cliente, conocida como secuencia de comandos. Hay dos lugares para ejecutar el código: en el servidor, donde todo se devuelve como HTML y en el cliente. Estos dos lugares para el código son distintos y no tienen relación entre sí. En el cliente: No se procesa en el servidor. Se escribe en secuencias de comandos que indican al cliente que haga algo. Se usa para realizar efectos dinámicos en el cliente como cuadros de mensaje. En el servidor: Se ejecuta sólo en el servidor. Todo se convierte en HTML o XML antes de enviarlo al cliente. Se utiliza para procesar resultados y devolver datos. Cómo enlaza ASP.NET los elementos ASP.NET sabe lo que ocurre en el cliente porque éste se comunica con el servidor mediante una petición. A través de las secuencias de comandos en el cliente, ASP.NET proporciona información de lo que éste hace durante las peticiones. Ejemplo: Vas a una biblioteca y el bibliotecario en todo momento sabe lo que necesitas, si te caes te trae una venda, si quieres leer te trae un libro, si tienes sed, agua ¿Cómo lo sabe? Tiene una red de espías que no dejan de observarte aunque tú no lo sepas. Los espías son las secuencias de comandos en el cliente. CREACIÓN DE PÁGINAS ASP.NET <%@ Page Language="VB" %> <script runat="server"> Sub Page_Load(obj as object, e as eventargs) lblMensaje.Text = "¡Recíbeme con alegría soy tu profe de ASP.NET!" End sub </script> <html><body> <asp:Label id="lblMensaje" runat="server"/> </body></html> Un archivo sencillo, se puede escribir en un editor o en un block de notas. Hay que guardarlo en la carpeta inetpub/root. Para visualizarla en el explorador: http://localhost/nombreCarpeta/NombrePagina.aspx. 2 ELEMENTOS DE UNA PÁGINA ASP.NET <%@ Page Language="VB" %> Directiva de página que da la información específica a la página ASP.NET. Nos dice que el lenguaje usado es Visual Basic. <script runat="server"> Sub tbMensaje_Change(Sender As Object, E As EventArgs) lblMensaje.Text = "Hola, " + tbMensaje.Text + "." End Sub </script> Bloque de declaración de código. Se parece al código en el lado del cliente, pero incluye la etiqueta runat="server". Éste es el código que ASP.NET utiliza para procesar sus páginas y es donde controlaremos la funcionalidad de la página. Es mejor colocarlo entre las etiquetas <head> </head> auque pueden colocarse en cualquier parte de la página. <html><body> Empieza la página HTML <font size="5">Aprendiendo ASP.NET Lección 2</font><hr><p> <% Response.Write("Nuestra primera página<p>") %> Éste es el bloque proveedor de código, empieza con <% . Contiene instrucciones que se usan para producir un resultado. Muestra un texto en pantalla. Se van a usar con moderación porque no son compilados. <form runat="server"> Tenemos un elemento HTML, pero con la etiqueta runat=server. Este formulario se convierte en formulario web. Todo lo que contenga será vigilado por ASP.NET. Por favor, teclea tu nombre: <asp:textbox id="tbMensaje" OnTextChanged="tbMensaje_Change" runat=server/> <asp:button id="btSubmit" Text="Enviar" runat=server/><p> <asp:label id="lblMensaje" font−size="20pt" runat=server/> Éstos son controles web. Funcionan de forma similar a los controles HTML, pero pueden usar ASP.NET. Llevan la etiqueta runat=server 3 </form> </body></html > ASP y ASP.NET son totalmente distintos pero pueden operar en conjunto. Esto quiere decir que el servidor web puede procesar tanto páginas ASP como ASP.NET. EJERCICIO Realizar una página que nos muestre un saludo por pantalla. TEMA 2: CREACIÓN DE PÁGINAS ASP.NET UNA APLICACIÓN SENCILLA <%@ Page Language="VB" Debug="True" %> <%@ Page Language="c#" Debug="True" %> <script runat="server"> Sub tbMensaje_Change(Sender As Object, E As EventArgs) lblMensaje.Text = "Hola, " + tbMensaje.Text + "." End Sub </script> <script runat="server"> public void tbMensaje_Change (Object sender, EventArgs E) { lblMensaje.Text = "Hola, " + tbMensaje.Text + "."; } </script> <html><body> <font size="5">Aprendiendo ASP.NET Lección 2</font><hr><p> <% Response.Write("Nuestra primera página<p>") %> <% Response.Write("Nuestra primera página<p>"); %> <form runat="server"> Por favor, teclea tu nombre: 4 <asp:textbox id="tbMensaje" OnTextChanged="tbMensaje_Change" runat=server/> <asp:button id="btSubmit" Text="Enviar" runat=server/><p> <asp:label id="lblMensaje" font−size="20pt" runat=server/> </form> </body></html > Obtiene un valor del usuario y lo despliega con un saludo. No se ha establecido una acción en el formulario, por lo que retorna a sí mismo. <asp:textbox>,<asp:button>, <asp:label> son controles de servidor. El atributo id es un nombre único que damos al control. Todas las etiquetas deben tener apertura y cierre. Si no vamos a poner nada entre ellas podemos ponerlo así <asp:textbox/>. Sin la etiqueta de cierre ASP.NET producirá errores. El cuadro de texto tiene el atributo OnTextChanged=tbMensaje_Change. Tiene un evento que es TextChanged. Hemos indicado a ASP.NET que ejecute el procedimiento tbMensaje_Change cuando ocurra ese evento. Estos eventos se controlan en el servidor. BLOQUES DE DECLARACIÓN DE CÓDIGO <script runat="server"> Sub tbMensaje_Change(Sender As Object, E As EventArgs) lblMensaje.Text = "Hola, " + tbMensaje.Text + "." End Sub </script> <script runat="server"> public void tbMensaje_Change (Object sender, EventArgs E) { lblMensaje.Text = "Hola, " + tbMensaje.Text + "."; } </script> La etiqueta <script> se utiliza en secuencias de comandos del cliente. Delimita una sección de la página que la aplicación manejará de forma dinámica, conocida como bloque de declaración de código. No se convierte en HTML dentro de la página, si no que contiene código que será ejecutado por el servidor. No olvidar incluir runat=server. 5 Es mejor separar el bloque <script> tanto como sea posible del código de presentación o de HTML. <% Response.Write("Nuestra primera página<p>") %> Es equivalente a poner <%="Nuestra primera página<p>" %> FLUJO DE PÁGINA La primera vez que se solicita la página desde el explorador web ASP.NET compilará el código que esté en los bloques de declaración. Por esto el explorador tarda en mostrar la página. Sin embargo, si se solicita una segunda vez sin modificar el código no habrá retardo alguno. Pero si se modifica algo ASP.NET volverá a compilar la página. Una vez que se envía el formulario y se compila el código, ASP.NET empieza a procesar todo el código que hemos generado y cualquier evento que haya ocurrido. En el ejemplo, el evento TextChanged ocurrió cuando se tecleó algo en la caja de texto. El motor de ASP.NET explora este evento, determina que debe hacer y lo hace. En ese momento, ASP.NET convierte cualquier control en elemento HTML. Luego evalúa cualquier bloque proveedor de código y devuelve el HTML necesario. Por último, el HTML resultante se envía al explorador web, que recibe sólo HTML estándar. Por lo que cualquier explorador web puede mostrar la página. ESTADO VISUAL Describe el aspecto de un objeto en un momento determinado. Por ej. Si un botón está o no pulsado. Una aplicación que lleve el control de esta información se conoce como estado de conservación. Si llenamos un formulario HTML y volvemos a él después, es posible que esté vacío. Esto es porque web es un medio sin estado. ASP.NET lleva automáticamente un control del estado visual. Esto quiere decir que si rellenamos un formulario HTML y volvemos a él después los datos estarán allí. ASP.NET hace esto al devolver campos ocultos de formulario HTML siempre que indicamos runat=server en el formulario. COMO ESCRIBIR CÓDIGO DE ASP.NET Y HTML Hay dos formas de escribir código de ASP.NET: en los bloques de declaración de código o en los bloques proveedores de código. Es mejor el primer método. También hay varias formas de escribir HTML puro mediante ASP.NET, como con Response.Write o con la etiqueta <%=. Debemos: Separar el código ASP.NET del HTML tanto como podamos mediante bloques de declaración de código. No debemos: Utilizar bloques proveedores de código para intercalar código o resultados HTML (con Response.Write) cuando otro método cumpla mejor con el trabajo. 6 COMENTARIOS EN EL CÓDIGO Hay tres formas de comentar el código: <!− − y − − > Para comentar sólo el código HTML. ` (apóstrofo) con Visual Basic // /* comentario */ con c# <%− − y − − %> comentarios para el servidor COMO SE DIVIDE EN VARIAS LÍNEAS Con Visual Basic: <% Response.Write _ (hola) %> <% Response.Write (Te estoy & _ saludando) %> Con C#: No se hace nada especial. COMO IMPORTAR ESPACIOS DE NOMBRES <%@ Import Namespace=System.Drawing %> para VB <%@ Import Namespace="System.Data" %> para c# Importa todas las clases del espacio de nombre System.Drawing, como font e image. De forma predeterminada, se importan automáticamente los siguientes a todas las páginas ASP.NET: System System.Collections System.IO System.Web System.Web.IU System.Web.IU.HtmlControls System.Web.IU.WebConstrols TEMA 3: USO DE OBJETOS EN ASP.NET 7 EL OBJETO RESPONSE Permite la interacción del servidor con el cliente. Cuando un usuario solicita una página asp.net genera una instancias del objeto HttpResponse, el cual contiene información (propiedades y métodos) necesaria para comunicarse con el cliente. El nombre de la instancia es Response, de modo que podrá utilizar este nombre para acceder a las propiedades y métodos del objeto HttpResponse. El método Write <%@ Page Language="VB" %> <script runat="server"> Sub Page_Load(obj as object, e as eventargs) Dim i As Integer Response.Write("Éste es un ejemplo") Necesita una cadena como parámetro Response.Write("<HR width=100%>") For i = 1 To 5 Response.Write("<font size=" & i & ">¡Hola!<br></font>") Next End Sub </script> <html><body> </body></html> <%@ Page Language="c#" %> <script runat="server"> public void Page_Load (Object sender, EventArgs E) { int i; Response.Write("Éste es un ejemplo"); Response.Write("<HR width=100%>"); 8 for ( i = 1;i<5;i++) { Response.Write("<font size=" + i + ">¡Hola!<br></font>"); } } </script> <html><body> </body></html> VB.Net realiza cierta conversión de tipos de datos automáticamente. La conversión de un integer a string podría servir como ejemplo. Es por ello que se puede utilizar Response.Write (6). Pero c# no realiza la misma conversión automáticamente, por lo tanto, usar Response.Write (6) produciría un error. Hay que usarlo así: Response.Write (int.ToString(6)) COMO ALMACENAR PAGINAS EN EL BUFER El almacenamiento en el búfer permite controlas en qué momento se enviará el resultado al explorador web. Cuando se almacena el resultado en el búfer, no se envía nada al explorador web mientras no se ejecute todo el código. Este es el método predeterminado en asp.net. El almacenamiento en el búfer es un buen acelerador de rendimiento. Para desactivarlo: BufferOutput=false. <% Response.Buffer=False %> Para controlar el búfer métodos Clear, Flush y End. Clear: vacía el búfer Flush: envía inmediatamente al explorador lo que hay en el búfer End: evita que response envíe algo nuevo al explorador, sólo se envía la salida que haya actualmente en el búfer. EJERCICO: ANALIZAR LA SALIDA DE ESTE PROGRAMA <%@ Page Language="VB" %> <script runat="server"> 9 Sub Page_Load(obj as object, e as eventargs) Dim i As Integer Response.Write("Antes de vaciar<br>") Response.Flush() For i = 0 To 5000 ' Sólo para perder el tiempo Next Response.Write("Luego de vaciar, antes de limpiar<br>") Response.Clear() For i = 0 To 5000 ' Sólo para perder el tiempo Next Response.Write("Luego de limpiar, antes de finalizar <br>") Response.End() For i = 0 To 5000 ' Sólo para perder el tiempo Next Response.Write("Luego de finalizar<br>") End Sub </script> <html><body> </body></html> <%@ Page Language="c#" %> <script runat="server"> public void Page_Load (Object sender, EventArgs E) { 10 int i; Response.Write("Antes de vaciar<br>"); Response.Flush(); For (i = 0;i<500;i++) { // Sólo para perder el tiempo } Response.Write("Luego de vaciar, antes de limpiar<br>"); Response.Clear(); For (i = 0;i<500;i++) { // Sólo para perder el tiempo } Response.Write("Luego de limpiar, antes de finalizar <br>"); Response.End(); For (i = 0;i<500;i++) { // Sólo para perder el tiempo } Response.Write("Luego de finalizar<br>"); } </script> <html><body> </body></html> VER BUFFER.ASPX COMO REDIRIGIR A LOS USUARIOS 11 Método Rediret. <%@ Page Language="VB" %> <script runat="server"> Sub Page_Load(obj as object, e as eventargs) Response.Redirect(http://www.marian.com) End Sub </script> <html><body> ¡Hola! </body></html> Cuando un usuario esta página, será enviado inmediatamente a www.marian.com y nunca verá el mensaje de saludo. Por ejemplo, es un método muy útil para enviar a un usuario a algún lugar de acuerdo con su login y su password capturados en un formulario. EL OBJETO REQUEST Permite la interacción del explorador web con el servidor. El explorador envía información al servidor cuando solita una página. Cuando esto ocurre, se genera un objeto HttpRequest para tratar con la información enviada. Este objeto se llama Request. El objeto request representa la petición de un cliente, y el servidor web envía una respuesta utilizando los objetos request y response. COMO AVERIGUAR LA INFORMACIÓN DEL CLIENTE Una función del objeto Request es obtener informació personal a través del explorador web, por ejemplo, lo que ha capturado un usuario en un formulario o los valores de cadena de consulta, por ejemplo, http://www.marian.com?id=yo&edad=33 La cadena de consulta, ?id=yo&edad=33, presenta los datos en forma de pares de valor, clave. El primer par siempre está precedido de la ? y los siguientes separados por &. Esta cadena es útil para pasar información de una página a otra. Response.Redirect (mipagina.aspx?id=yo) Sólo se pueden reconocer hasta 255 caracteres en esta cadena. Request.Querystring devuelve id=yo&edad=33 Request.Querystring(id) devuelve yo 12 Request.Form devuelve todos los campos de un formulario Request.Form (nombre) devuelve un valor indicado por nombre Tanto las propiedades Querystring como Form representan colecciones de información. Otras colecciones utilizadas por Request son ServerVariables y Cookies. La primera devuelve información del servidor, como la IP o el protocolo http. La segunda devuelve información de las coookies. Variables de entorno URL .... el url de la página asp.net empezando después del servidor y nombre de dominio, después de http://www.marian.com/ PATH_INFO lo mismo que url PATH_TRANSLATED Toda la ruta física de asp.net en el servidor. SERVER_NAME El nombre del servidor web SERVER_SOFTWARE El nombre del software del servidor web. (Microsoft IIS 5.0) EL OBJETO HttpCookie Una cookie es un pequeño archivo en la computadora del usuario que contiene información específica para un sitio web. El objeto HttpCookie ofrece métodos para acceder y generar esas cookies. La forma común de manejar las cookies es mediante los objetos Request y Response, los cuales cuentan con una propiedad Cookies que devuelve una referencia a un objeto HttpCookie. COMO GENERAR COOKIES Dos formas de hacerlo: Generar varias cookies, cada una con un valor en particular, o puede generar una cookie con diversos pares de clave, valor. Para vb: Response.Cookies(MiCookie).Value=Una cookie Response.Cookies(MiCookie2) (Usuario)=yo Response.Cookies(MiCookie2) (edad)=33 En c#con [] en lugar de () Propiedad Expires para que la cookie quede inhabilitada cuando le digamos: Response.Cookies(MiCookie2).Expires=DateTime.FromString(1/1/2005) 13 Response.Cookies(MiCookie2).Expires=DateTime.Now.AddMonths(1) Para suprimir una cookie del cliente establecer expires a una fecha anterior o a 0. Propiedades: Domain: Restringe el uso de la cookie al dominio que le indiquemos. Path: Similar a Domain, pero solo permite el acceso a la cookie a las páginas ASP.Net que se encuentren en una ruta específica del servidor. HasKeys:Indica si esta cookie tiene claves o es una cookie con un único valor. Secure: Indica a Asp.net si debe o no transmitir la cookie de forma segura, es decir, sólo bajo el protocolo HTTPS. El valor predeterminado es false. COMO ACCEDER A LAS COOKIES Utilizar el objeto Request Response.Write (Request.Cookies (Micookie).Value) Response.Write (Request.Cookies (Micookie2).(Usuario)) Para iterar por las claves de la cookie. La mayor parte del código se encuentra en el controlador de eventos Page_Load. <%@ Page Language="VB" %> <script runat="server"> Sub Page_Load(obj as object, e as eventArgs) Dim strVariable As String ' Establezco algunos valores de cookie Response.Cookies("temp").Value = "HI" Response.Cookies("CookieDe21la")("Nombreusuario") = "Tania" Response.Cookies("CookieDe21la")("Preferencia") = _ "800x640" Response.Cookies("CookieDe21la")("Contrasenia") = _ "QueInteresanteCookie" Response.Cookies("CookieDe21la")("UltimaVisita") = _ DateTime.Now.ToString 14 Response.Cookies("CookieDe21la")("UserAgent") = _ Request.ServerVariables("HTTP_USER_AGENT") Devuelve el valor del user Agent (Ej. Mozilla/4.0) Devolvemos los valores de las cookies con ayuda de un bucle for... each. for each strVariable in Response.Cookies _ ("CookieDe21la").Values Label1.Text += "<b>" & strVariable & "</b>: " & _ Request.Cookies("CookieDe21la")(strVariable) & "<br>" next end sub </script> <html><body> <form runat="server"> <asp:Label id="Label1" runat="server"/> </form> </body></html> <%@ Page Language="c#" %> <script runat="server"> public void Page_Load (Object sender, EventArgs E) { string strVariable; Response.Cookies["temp"].Value = "HI"; Response.Cookies["CookieDe21la"]["Nombreusuario"] = "Tania"; Response.Cookies["CookieDe21la"]["Preferencia"] = "800x640"; Response.Cookies["CookieDe21la"]["Contrasenia"] = "QueInteresanteCookie"; Response.Cookies["CookieDe21la"]["UltimaVisita"] = DateTime.Now.ToString; 15 Response.Cookies["CookieDe21la"]["UserAgent"] = Request.ServerVariables("HTTP_USER_AGENT"); foreach (strVariable in Response.Cookies ["CookieDe21la"].Values) { Label1.Text += "<b>" + strVariable + "</b>: " + Request.Cookies["CookieDe21la"](strVariable) + "<br>"; } } </script> <html><body> <form runat="server"> <asp:Label id="Label1" runat="server"/> </form> </body></html> MÁS SOBRE COOKIES Escritura de las cookies Para escribir una cookie se utiliza la propiedad Response de la página, que muestra un objeto que permite agregar datos a la información que la página envía al explorador. El objeto Response admite una colección llamada Cookies, a la que agregará las cookies que desee escribir en el explorador. Se pueden agregar cookies a la colección Response.Cookies de dos maneras diferentes. En el siguiente ejemplo se muestran dos métodos para realizar esta tarea: Response.Cookies("userName").Value = "mike" Response.Cookies("userName").Expires = DateTime.Now.AddDays(1) Dim aCookie As New HttpCookie("lastVisit") aCookie.Value = DateTime.Now.ToString aCookie.Expires = DateTime.Now.AddDays(1) Response.Cookies.Add(aCookie) Response.Cookies["userName"].Value = "mike" 16 Response.Cookies["userName"].Expires = DateTime.Now.AddDays(1) Para crear una cookie con subclaves, puede utilizar una variación de la sintaxis que se utiliza para escribir una cookie individual. En el siguiente ejemplo se muestran dos formas de escribir la misma cookie, ambas con dos subclaves: Response.Cookies("userInfo")("userName") = "mike" Response.Cookies("userInfo")("lastVisit") = DateTime.Now.ToString Response.Cookies("userInfo").Expires = DateTime.Now.AddDays(1) Dim aCookie As New HttpCookie("userInfo") aCookie.Values("userName") = "mike" aCookie.Values("lastVisit") = DateTime.Now.ToString aCookie.Expires = DateTime.Now.AddDays(1) Response.Cookies.Add(aCookie) Response.Cookies["marian"]["BackColor"]="#99ccff"; Response.Cookies["marian"]["ForeColor"]="#0000cc"; Response.Cookies["marian"]["LinkColor"]="#ffcccc"; Response.Cookies["marian"]["FontSize"]="12pt"; Response.Cookies["marian"]["FontName"]="Comic Sans MS"; Response.Cookies["marian"].Expires=DateTime.Now.AddMonths(1); <%@ Page Language="c#" %> <script runat="server"> public void Page_Load(Object obj,EventArgs e) { HttpCookie aCookie = new HttpCookie("userInfo"); aCookie.Values["userName"] = "mike"; aCookie.Values["lastVisit"] = DateTime.Now.ToString(); aCookie.Expires = DateTime.Now.AddDays(1); Response.Cookies.Add(aCookie); 17 } </script> Limitar las cookies a una carpeta o aplicación Para limitar las cookies a una carpeta del servidor, establezca la propiedad Path de éstas tal como se describe a continuación: Dim appCookie As New HttpCookie("AppCookie") appCookie.Value = "Escrita " & Now.ToString appCookie.Expires = Now.AddDays(1) appCookie.Path = "/Application1" Response.Cookies.Add(appCookie) Limitar el ámbito de las cookies a un dominio De forma predeterminada, las cookies se asocian a un determinado dominio. Por ejemplo, en el sitio www.contoso.com, las cookies que escriba se enviarán al servidor cuando los usuarios soliciten cualquier página de este sitio. (Excepto las cookies con un valor de ruta específico, tal como ya hemos visto en el apartado anterior a éste). Si el sitio contiene subdominios por ejemplo, contoso.com, ventas.contoso.com y soporte.contoso.com podrá asociar las cookies a un determinado subdominio. Para ello, establezca la propiedad Domain de la cookie de la siguiente forma: Response.Cookies("domain").Value = DateTime.Now.ToString Response.Cookies("domain").Expires = DateTime.Now.AddDays(1) Response.Cookies("domain").Domain = "support.contoso.com" Cuando el dominio se establece de este modo, la cookie únicamente estará disponible para las páginas del subdominio que se haya especificado. También puede utilizar la propiedad Domain para crear una cookie que puedan compartir varios subdominios. Por ejemplo, establezca el dominio como se muestra a continuación: Response.Cookies("domain").Value = DateTime.Now.ToString Response.Cookies("domain").Expires = DateTime.Now.AddDays(1) Response.Cookies("domain").Domain = "contoso.com" Lectura de las cookies Cuando un explorador realiza una solicitud al servidor, envía junto con ésta las cookies para el servidor. En las aplicaciones ASP.NET, puede leer las cookies mediante la utilización del objeto Request. La estructura del objeto Request es básicamente la misma que la del objeto Response, por lo que puede leer las cookies del objeto Request de un modo muy similar a cómo las escribió en el objeto Response. Los siguientes ejemplos 18 muestran dos modos de obtener el valor de una cookie llamada "userName" y mostrarlo en un control Label: If Not Request.Cookies("userName") Is Nothing Then Label1.Text = Server.HtmlEncode(Request.Cookies("userName").Value) End If If Not Request.Cookies("userName") Is Nothing Then Dim aCookie As HttpCookie = Request.Cookies("userName") Label1.Text = Server.HtmlEncode(aCookie.Value) End If Antes de intentar obtener el valor de una cookie, debe asegurarse de que ésta existe. De lo contrario, obtendrá una excepción System.NullReferenceException. Observe igualmente que realizo una llamada al método HttpServerUtility.HtmlEncode para codificar el contenido de una cookie antes de mostrarla en la página. El motivo para que proceda de ese modo es que estoy mostrando el contenido de una cookie (algo que generalmente no se hace) y quiero asegurarme de que un usuario malintencionado no haya introducido secuencias de comandos ejecutables. Asimismo, el valor de una subclave de una cookie se lee de un modo similar a como se configura. Esta es una forma de obtener el valor de una subclave: If Not Request.Cookies("userInfo") Is Nothing Then Label1.Text = _ Server.HtmlEncode(Request.Cookies("userInfo")("userName")) Label2.text = _ Server.HtmlEncode(Request.Cookies("userInfo")("lastVisit")) End If Lectura de las colecciones de cookies En los ejemplos anteriores se asume que desea leer una determinada cookie cuyo nombre ya conoce. Puede que en ocasiones deba leer todas las cookies disponibles para la página. Para leer los nombres y valores de todas estas cookies puede recorrer la colección Request.Cookies utilizando código como éste: Dim i As Integer Dim output As String = "" Dim aCookie As HttpCookie For i = 0 to Request.Cookies.Count − 1 19 aCookie = Request.Cookies(i) output &= "Nombre de cookie = " & Server.HtmlEncode(aCookie.Name) & "<br>" output &= "Valor de cookie = " & Server.HtmlEncode(aCookie.Value) & _ & "<br><br>" Next Label1.Text = output Request.Cookies["marian"]["FontSize"] Request.Cookies["marian"].Value Nota Cuando ejecute este código, probablemente verá una cookie llamada "ASP.NET_SessionId". Se trata de una cookie que ASP.NET utiliza para almacenar un identificador único para su sesión y que no se guardará en el disco duro de su equipo. Comprobar si un explorador acepta cookies Sub Page_Load() If Not Page.IsPostBack Then If Request.QueryString("AcceptsCookies") Is Nothing Then Response.Cookies("TestCookie").Value = "ok" Response.Cookies("TestCookie").Expires = _ DateTime.Now.AddMinutes(1) Response.Redirect("TestForCookies.aspx?redirect=" & _ Server.UrlEncode(Request.Url.ToString)) Else labelAcceptsCookies.Text = "Aceptar cookies = " & _ Request.QueryString("AcceptsCookies") End If End If End Sub EJERCICIO: 20 Mediante el uso de Cookies personalizar la página del cliente. Al pulsar personalizar aparece: 21 Seleccionamos y mostramos el resultado: 22 (Solución ejercicio Tema3−cookies−mariancookies) EL OBJETO PAGE Contiene todas las propiedades y métodos de toda la página asp.net que genere. Cuando ejecutamos una página asp.net ésta heredará de la clase Page del .NET Framework Herencia: Una clase define algunos parámetros y métodos para los objetos que se basen en ella. Cuando genere otra clase que se herede de la principal, también heredará sus miembros. También podemos generar sus propios miembros en la clase secundaria. Las páginas asp.net son los objetos secundarios del objeto Page. Cualquier método o propiedad que defina en la página asp.net se convertirá en miembro del objeto basado en su página. Esto significa que si genero otra página podré acceder a los métodos y propiedades de la primera. Miembros útiles integrados: 23 IsPostBack: Indica si un formulario de esta página fue enviado a la misma. DataBind: Enlaza todas las expresiones de datos a los controles de la página. Evento Load: Se desencadena cuando la página comienza a cargarse en el explorador. Eventos: Init: este evento es lanzado cuando la página es inicializada, cuando es lanzado este evento todavía no se han creado por completo los distintos controles de la página. Este evento es tratado en el método Page_Init. Load: este evento se lanzaría a continuación del método Init y es lanzado cuando la página se ha cargado, en este caso todos los controles de la página ya han sido creados. Este evento se lanzará cada vez que la página ASP .NET es ejecutada. Este evento es tratado en el método Page_Load. PreRender: el evento se lanzará justo antes de enviar la información al cliente. Este evento es tratado en el método Page_PreRender, y siempre es lanzado después del evento Load. UnLoad: este otro evento se lanzará en último lugar, y tiene lugar cuando la página ha finalizado de procesarse, es decir, cuando se ha terminado la ejecución de la página y toda la información ha sido enviada al cliente. Este evento es tratado en el método Page_UnLoad. Error: este evento se lanzará cuando se produzca una excepción no tratada dentro de la página. El método Page_Error se utilizará cuando deseemos realizar nuestro propio tratamiento de errores, esto lo veremos más en detalle en el capítulo dedicado al tratamiento de errores y depuración. Propiedades: IsPostBack: esta propiedad de la clase Bolean devolverá true si la página ASP .NET actual ya ha sido enviada al servidor en alguna ocasión. Si tiene el valor false indicará que la página es la primera vez que se carga y nos servirá de indicador para poder inicializar los controles Web de la página o bien realizar otras labores de inicialización. Application: esta propiedad nos va a ofrecer una referencia a un objeto de la clase System.Web.HttpApplicationState, este objeto nos va a permitir almacenar y acceder a información que va a ser común a toda la aplicación Web, es decir, es una información compartida por todos los clientes de una aplicación Web determinada. Esta propiedad es equivalente al objeto integrado Application de anteriores versiones de ASP. Uso del evento Page_Load. Analiza este código <%@ Page Language="VB" %> <script runat="server"> Sub Page_Load(obj as object, e as eventArgs) tbMyText.Value = "¡Éste es el evento Page_Load!" End Sub </script> 24 <html><body> <form runat="server"> <input type="text" size="25" id="tbMyText" runat="server" /> </form> </body></html> <%@ Page Language="c#" %> <script runat="server"> public void Page_Load (Object sender, EventArgs E) { tbMyText.Value = "¡Éste es el evento Page_Load!"; } </script> <html><body> <form runat="server"> <input type="text" size="25" id="tbMyText" runat="server" /> </form> </body></html> En el evento Load se verifica la identidad del usuario, se cargan los datos de una base de datos y se redirige al usuario, por ejemplo. Ejemplo de formatos de fechas correctas para DateTime: <%@ Page Language="VB" %> <script runat="server"> sub Page_Load(obj as object, e as eventArgs) Dim Ahora as DateTime = DateTime.Now Dim intHora as Integer = Ahora.Hour 25 Label1.Text = "En este momento son " & _ Ahora.ToString("d") + "<p>" Label1.Text += Ahora.ToString("D") + "<p>" Label1.Text += Ahora.ToString("f") + "<p>" Label1.Text += Ahora.ToString("F") + "<p>" Label1.Text += Ahora.ToString("g") + "<p>" Label1.Text += Ahora.ToString("G") + "<p>" Label1.Text += Ahora.ToString("m") + "<p>" Label1.Text += Ahora.ToString("r") + "<p>" Label1.Text += Ahora.ToString("s") + "<p>" Label1.Text += Ahora.ToString("t") + "<p>" Label1.Text += Ahora.ToString("T") + "<p>" Label1.Text += Ahora.ToString("u") + "<p>" Label1.Text += Ahora.ToString("U") + "<p>" Label1.Text += Ahora.ToString("y") + "<p>" Label1.Text += Ahora.ToString("dddd, MMMM dd yyyy") + "<p>" Label1.Text += Ahora.ToString("ddd, MMM d ""'""yy") + "<p>" Label1.Text += Ahora.ToString("dddd, MMMM dd") + "<p>" Label1.Text += Ahora.ToString("M/yy") + "<p>" Label1.Text += Ahora.ToString("dd−MM−yy") + "<p>" if intHora < 12 then Label1.Text += "¡Buenos días!" elseif intHora > 12 And intHora < 18 then Label1.Text += "¡Buenas tardes!" else Label1.Text += "¡Buenas noches!" 26 end if end sub </script> <html><body> <form runat="server"> <asp:Label id="Label1" runat="server"/> </form> </body></html> Ejercicio: Mostrar al usuario distintos mensajes dependiendo de la hora a la que se conecte, en C# Solución Tema3−fechas Archivo Global.asax Además de escribir código para interfaces de usuario, los programadores también pueden agregar lógica del nivel de aplicación y código de control de eventos a sus aplicaciones Web. Este código no se encarga de generar interfaces de usuario y no se invoca normalmente en respuesta a solicitudes de páginas individuales. En vez de ello, se encarga de procesar eventos de la aplicación de nivel superior, tales como Application_Start, Application_End, Session_Start, Session_End, etc. Los programadores crean esta lógica mediante un archivo Global.asax ubicado en la raíz del árbol de directorios virtuales de una aplicación Web. ASP.NET analiza y compila automáticamente este archivo para producir una clase dinámica de .NET Framework, la cual extiende la clase base HttpApplication (la primera vez que se activa o se solicita cualquier recurso o URL dentro del espacio de nombres de la aplicación). ASP.NET analiza y compila dinámicamente el archivo Global.asax para producir una clase de .NET Framework la primera vez que se activa o se solicita cualquier recurso o URL dentro del espacio de nombres de la aplicación. El archivo Global.asax está configurado para rechazar automáticamente cualquier solicitud de URL directa de modo que los usuarios externos no puedan descargar o ver el código interno. Eventos cuyo ámbito es una sesión o una aplicación Los programadores pueden definir controladores para eventos de la clase base HttpApplication creando métodos en el archivo Global.asax que se ajusten al modelo de nomenclatura "NombreDeEventoDeLaAplicación(FirmaDeArgumentosDelEvento)". Por ejemplo: <script language="C#" runat="server"> void Application_Start(object sender, EventArgs e) { // Application startup code goes here 27 }</script> Si el código de control de eventos necesita importar espacios de nombres adicionales, se puede utilizar la directiva @ import en una página .aspx, como se indica a continuación: <%@ Import Namespace="System.Text" %> El siguiente ejemplo ilustra el período de vida de Application, Session y Request. Ver ejemplo Tema3−global La primera vez que se abre la página, se provoca el evento Start para la aplicación y la sesión: void Application_Start(object sender, EventArgs e) { // Application startup code goes here } void Session_Start(object sender, EventArgs e) { Response.Write("Session is Starting...<br>"); Session.Timeout = 1; } Los eventos BeginRequest y EndRequest se provocan en cada solicitud. Cuando la página se actualiza, sólo aparecen mensajes de BeginRequest, EndRequest y el método Page_Load. Observa que, al abandonar la sesión actual (hacer clic en el botón "Finalizar esta sesión"), se crea una nueva sesión y se provoca de nuevo el evento Session_Start. Sub Application_Start(Sender As Object, E As EventArgs) ' Application startup code goes here End Sub Sub Session_Start(Sender As Object, E As EventArgs) Response.Write("Session is Starting...<br>") Session.Timeout = 1 End Sub function Application_Start(sender:Object, E:EventArgs) : void { // Application startup code goes here } 28 function Session_Start(sender:Object, e:EventArgs) : void { Response.Write("Session is Starting...<br>"); Session.Timeout = 1; } EL OBJETO SESSION Debido a que Web es un medio sin estado es difícil llevar un control de la información del usuario. No hay forma de utilizar http para saber si una serie de peticiones proviene de un usuario o de varios. El objeto Session permite almacenar elementos propios de un usuario, como variables, objetos, cadenas...) en un solo lugar del servidor. Al tiempo que un usuario pasa en un sitio se le conoce como sesión. Explicar este código: <%@ Page Language="VB" %> <%@ Page Language="c#" %> <script runat="server"> Sub Enviar_Click(obj as object, e as EventArgs) If tbNombre.Value <> "" Session("Nombre") = tbNombre.Value Response.Write("¡Hola, " & Session("Nombre") & "!") Else Response.Write("Olvidó capturar un nombre.") End if End Sub public void Enviar_Click (Object sender, EventArgs E) { if(tbNombre.Value != "") { Session["Nombre"] = tbNombre.Value ; Response.Write("¡Hola, " + Session["Nombre"] + "!") ; 29 } else { Response.Write("Olvidó escribir un nombre."); } } </script> <html><body> <form runat="server"> Por favor, teclee su nombre: <input type="text" id="tbNombre" runat="server"/> <p> <asp:Button id="btEnviar" text="Enviar"runat="server" OnClick="Enviar_Click" /> </form> </body></html> COMO RECUPERAR VARIABLES DE SESSION <%@ Page Language="VB" %> <script runat="server"> sub Page_Load(obj as object, e as eventArgs) Etiqueta1.Text = "¡Bienvenido de vuelta " & Session("Nombre") & "!" end sub </script> <html><body> <form runat="server"> <asp:Label id="Etiqueta1" runat="server"/> </form> 30 </body></html> <%@ Page Language="c#" %> <script runat="server"> public void Page_Load(Object obj, EventArgs e) Etiqueta1.Text = "¡Bienvenido de vuelta " + Session["Nombre"] + "!" ; } </script> <html><body> <form runat="server"> <asp:Label id="Etiqueta1" runat="server"/> </form> </body></html> Ver ejemplo − tema3\sesion\ejemploSesion ¿Cómo logra asp.net llevar un control de las sesiones? Cuando un usuario visita el sitio e inicia sesión, el equipo genera un identificador único para él que almacena en el equipo cliente en forma de cookie. Response.Write(Session.SessionID) Cuando la sesión expire se eliminará la cookie. CONTROL DE SESSION Timeout: Tiempo que puede estar inactiva una sesión antes que asp.net la deje. 20 minutos es el valor predeterminado. Para modificarlo: Session.Timeout= x donde x es el tiempo en minutos Session.Abandon: hace que la sesión termine. USO DE SESSION Se usa como cualquier matriz. <%@ Page Language="VB" %> <script runat="server"> Sub Page_Load(obj as object, e as eventArgs) 31 Dim strVariable As String ' Establezco algunas variables de sesión Session("Nombre") = "Tania" Session("ColorFavorito") = "Naranja" Session("ColorOjos") = "Café" Session("UnMensaje") = "Bienvenido a mi mundo." Session("ASPNET") = "¡Es a genial!" For Each strVariable In Session.Contents Label1.Text += "<b>" & strVariable & "</b>: " & _ Session(strVariable) & "<br>" Next End Sub </script> <html><body> <form runat="server"> <asp:Label id="Label1" runat="server"/> </form> </body></html> <%@ Page Language="C#" %> <script runat="server"> public void Page_Load(object obj, eventArgs e){ string strVariable; ' Establezco algunas variables de sesión Session["Nombre"] = "Tania" Session["ColorFavorito"]= "Naranja" Session["ColorOjos"] = "Café" 32 Session["UnMensaje"] = "Bienvenido a mi mundo." Session["ASPNET"] = "¡Es genial!" foreach (strVariable In Session.Contents){ Label1.Text += "<b>" + strVariable + "</b>: " + Session[strVariable] + "<br>" } } </script> <html><body> <form runat="server"> <asp:Label id="Label1" runat="server"/> </form> </body></html> Si el usuario no soporta cookies asp.net coloca el identificador de la sesión cifrado en cada vínculo de la página. Es posible almacenar los datos con ámbito de sesión a fin de proporcionar datos individuales a un usuario durante una sesión. En el ejemplo siguiente se inicializan los valores de preferencias de usuario en el evento Session_Start del archivo Global.asax. void Session_Start() { Session["BackColor"] = "beige"; ... } Se modifican los valores de las preferencias de usuario en el controlador de eventos Submit_Click con la información aportada por el usuario. protected void Submit_Click(Object sender, EventArgs e) { Session["BackColor"] = BackColor.Value; ... } Configurar el estado de una sesión: es posible configurar las características del estado de una sesión en la sección <sessionState> de un archivo web.config. Para doblar el tiempo de espera predeterminado de 20 33 minutos, se puede agregar el código siguiente al archivo web.config de una aplicación: <sessionState timeout=40 /> Protected GetStyle(key As String) As String Return(Session(key).ToString()) End Sub protected function GetStyle(key:String) : String { return Session(key).ToString(); } Sub Session_Start() Session("BackColor") = "beige" ... End Sub function Session_Start() : void { Session("BackColor") = "beige"; ... } EJERCICIO: Realizar el mismo ejercicio de las cookies pero con variables de sesión. Solución:tema3−sesion−mariansesion1 EL OBJETO HttpApplication Aplicación: Conjunto de archivos que hay en un directorio virtual y sus subdirectorios. ASP.net genera un objeto HttpApplication llamado Application cuando arranca su aplicación, es decir, cuando alguien solicita la página por primera vez. Sólo se genera un objeto Application para toda la aplicación. Al igual que Session puede usarse para almacenar variables y objetos. Por ejemplo un pie de página que vamos a colocar en cada página. Application(pie)=Derechos de autor 2004 Escribiríamos en cada página: 34 Response.Write(Application(pie)) EL OBJETO HttpSeverUtility Podemos utilizar el nombre Server para acceder a los miembros de este objeto. COMO REDIRIGIR A LOS USUARIOS Con el objeto Response. Con los métodos Execute y Transfer del objeto HttpSeverUtility. Server.Transfer lleva la ejecución a otra página. If (strContraseña == micontraseña) Server.Transfer(PuedoEntrar.aspx) Server.Execute lleva la ejecución de asp.net as otra página, pero regresa a la misma cuando termine. Esto es útil si se necesita ejecutar cierto código en otra página (como un procesamiento de datos) pero continuar en la misma página. COMO DAR FORMATO A LAS CADENAS Cuando envíe alguna salida al explorador, será interpretada como HTML. Response.Write (<br>) Si en lugar de un salto de línea quiero que aparezca <br> usaré el método HtmlEncode del objeto HttpServerUtility. Esto daría como resultado &lt;br&gt; y el usuario vería <br> en el explorador. UrlEncode hace algo similar, pero da formato a una cadena en particular con las reglas URL. Por ejemplo el & y ? tienen un significado especial en un url. Server.HtmlDecode y Server.UrlDecode realizan estas operaciones a la inversa. El método MapPath traduce una ruta virtual en una física en el servidor. Server.MapPath(/asp/tema4) Se traduce en C:\inetpub\wwwroot\asp\tema4 COMO CONTROLAR SECUENCIAS DE COMANDOS Con el método ScriptTimeout indicamos el tiempo que vamos a esperar antes de finalizar la secuencia de comandos. Por ejemplo si escribimos un código con un bucle infinito.... Server.ScriptTimeout=90 (segundos) COMO GENERAR OBJETOS 35 Con el método CreateObject creamos una instancia de un objeto COM. EJERCICIOS: • Generar una página ASP.NET en C# que actúe como inicio de sesión seguro. Permita que el usuario capture un nombre y una contraseña en el cuadro de texto. Si concuerdan con una cadena que indiquemos, redirigiremos al usuario a una página de aceptación, de otro modo, mostramos un error. Si el nombreusuario es válido, guardar en una variable de sesión. • Escribir una página de aceptación. Mostar un mensaje de bienvenida adaptado para el usuario con ayuda del evento Load del objeto Page y un control Label. Indicar al usuario la hora en curso y su identificador de sesión. Verificar la propiedad IsPostback del objeto Page para asegurarse de que este mensaje sólo aparece la primera vez que el usuario llegue a la página. Agregar un botón para que pueda finalizar la sesión, con un mensaje de confirmación. Soluciones: tema3/tema3ej1y2 TEMA 4: INTRODUCCIÓN A LOS FORMULARIOS WEB Permiten un control programático de la interfaz del usuario mediante el uso de objetos residentes en el servidor. PRESENTACIÓN DE LOS FORMULARIOS Un cliente envía una petición a un servidor para obtener cierta información y que éste responda a su envío. Es el modelo petición−respuesta. <html><body> <form method ="post"> Teclea tu nombre <input type="text" size= 20> <input type="Submit" Value=enviar> </form> </body></html> El cliente también puede enviar datos al servidor. Los formularios HTML permiten la interacción del usuario con páginas web. Cuando el usuario hace clic en el botón Enviar, el formulario envía al servidor los datos que haya capturado. Los formularios HTML se basan por completo en el cliente. Entre el cliente y el servidor es difícil intercambiar información. Tan pronto como el servidor envía los datos, olvida todo lo que el formulario indica y pierde el rastro de lo que sucede. PRESENTACIÓN DE LOS FORMULARIOS WEB Son muy similares a los HTML. La diferencia es que se basan en el servidor. Genera los elementos del 36 usuario en el servidor. El servidor tendrá conocimiento de la apariencia de la interfaz, qué puede hacer, qué datos recibirá, etc. En el servidor generaremos objetos llamados controles de servidor, que pueden controlarse por completo: tienen propiedades, eventos y métodos que podemos manejar. Tan pronto como el cliente solicita la página, ASP.NET convierte los controles a HTML. A través de la secuencia de comandos que asp.net genera automáticamente en el cliente, estos controles avisan al servidor cuando algo sucede, como cuando se hace clic en un botón. MODELO DE PROGRAMACIÓN DE LOS FORMULARIOS WEB Los formularios web están divididos en dos partes: los elementos visuales y la lógica de la interfaz. Están separados entre sí en el plano conceptual y en el físico. CONTROLES DE SERVIDOR Los controles ASP .NET son una serie de objetos de servidor que generarán el correspondiente código HTML para que el usuario pueda utilizarlos en la página cargada en su navegador al ejecutarse la página ASP .NET correspondiente los controles de servidor de ASP .NET generarán todo el código equivalente en el lenguaje HTML, para que así pueda ser interpretado el resultado de la ejecución de la página por cualquier navegador Web. Cada control se corresponde con una clase determinada perteneciente a un espacio con nombre determinado. Existe un gran número de controles de servidor y cada uno de ellos pertenece a una clase del .NET Framework. Son los elementos de la interfaz de usuario de un formulario web. Hay cuatro tipos de estos controles en asp.net: controles HTML de servidor, controles web, controles de validación, controles de usuario. Los controles HTML de servidor representan a los elementos normales de los formularios HTML, como los cuadros de texto y los botones, pero se crean en el servidor donde podemos controlarlos. Los controles web son semejantes, pero ofrecen una mayor funcinalidad y pueden representar interfaces de usuario más complejas. Los controles de validación se utilizan para validar lo capturado por el usuario. Los controles de usuario son aquellos programados a medida para realizar cierta funcionalidad. Todos tienen propiedades, métodos y eventos. EVENTOS DE LOS CONTROLES DE SERVIDOR 37 Hacer clic en un botón, en un vínculo, llenar un cuadro de texto, seleccionar un elemento de una lista.... Un evento activo necesita una acción explícita del usuario. Un evento pasivo se puede ejecutar sin intención directa del usuario, como mover el cursor por una imagen. Sólo los eventos activos se manejan en el servidor. Hay dos formas de enviar los eventos al servidor: conforme ocurren o todos juntos en un solo envío. Es conveniente utilizar el segundo método. Permanecen en la caché del usuario hasta que éste se decida a enviar los datos. Los controles generan eventos automáticamente siempre que sucede algo. Para controlar el evento en el servidor, necesitará indicar al control qué método utilizar. <%@ Page Language="VB" %> <script runat="server"> Sub Button1_Click(obj as object, e as EventArgs) Label1.Text="Hizo clic en <b>" & obj.Text & "</b>" Esta línea establece la propiedad Text del control Label1. Esta línea da el mismo resutado: Label1.Text="Hizo clic en <b>" & Button1.Text & "</b>" End Sub </script> <html><body> <font size="5"> Tema 4</font><hr><p> <form runat="server"> <asp:Button id=Button1 runat="server" Text="Botón1" onClick="Button1_Click" /> <p> <asp:Label id=Label1 runat=server /> </form> </body></html> <%@ Page Language="c#" %> 38 <script runat="server"> public void Button1_Click(Object obj, EventArgs e) { Label1.Text="Hizo clic en <b>" + ((Button)obj).Text + "</b>"; } </script> <html><body> <font size="5"> Tema 4</font><hr><p> <form runat="server"> <asp:Button id=Button1 runat="server" Text="Botón1" onClick="Button1_Click" /> <p> <asp:Label id=Label1 runat=server /> </form> </body></html> Ver tema4−tm4ejemplo1.aspx Si especificamos en el controlador del servidor que un método deberá controlar un evento: <asp:Button runat=server OnClick=UnMetodo /> Si no genero este método en alguna parte del bloque de declaración de código, recibiré un error. COMO ENVIAR FORMULARIOS WEB Una situación típica, cuando la página se cargue en el explorador, mostramos un mensaje de bienvenida en un control de servidor. Este mensaje formará parte del estado visual del control y asp.net lo recordará siempre. El objeto Page tiene una propiedad llamada IsPostBack que informa si el formulario ya ha sido o no enviado. Se puede verificar esta propiedad y decidir si se llena o no con los controles de servidor. Ejemplo: <%@ Page Language="VB" %> <script runat="server"> 39 Sub Page_Load(obj as object, e as EventArgs) If Not Page.IsPostBack Then lblMensaje.Text = "¡Hola, mundo!" End If End Sub Evalúa la propiedad IsPostBack, y si es verdadera(el formulario ha sido enviado) no ejecuta la siguiente línea. Asp.net llenará la etiqueta por ti cada vez que el formulario se envía. Sub Enviar(obj as object, e as EventArgs) lblMensaje2.Text = "Formulario enviado." End Sub </script> <html><body> <form runat="server"> <asp:Button id="btEnviar" runat="server" Text="Enviar" onClick="Enviar" /> <p> <asp:Label id="lblMensaje" runat=server /> <p> <asp:Label id="lblMensaje2" runat=server /> </form> </body></html> <%@ Page Language="c#" %> <script runat="server"> public void Page_Load (Object sender, EventArgs E) { if (!Page.IsPostBack) { 40 lblMensaje.Text = "¡Hola, mundo!"; } } Evalúa la propiedad IsPostBack, y si es verdadera (el formulario ha sido enviado) no ejecuta la siguiente línea. Asp.net llenará la etiqueta por ti cada vez que el formulario se envía. public void Enviar (Object sender, EventArgs E) { lblMensaje2.Text = "Formulario enviado."; } </script> <html><body> <form runat="server"> <asp:Button id="btEnviar" runat="server" Text="Enviar" onClick="Enviar"/> <p> <asp:Label id="lblMensaje" runat=server /> <p> <asp:Label id="lblMensaje2" runat=server /> </form> </body></html> Ver tema4−tm4ejemplo2.aspx COMO GUARDAR EL ESTADO Los formularios web guardan el estado visual de cada control en el formulario mediante campos ocultos. Este estado visual le indica lo que se ha tecleado en el control, ya sea que éste se encuentre o no seleccionado, qué elemento lo está, etc Hay otra forma de guardar información en los formularios web. Utilizar el saco de estado o state bag, un objeto que contiene los valores cuando se envía un formulario. Cuando coloca algo en el saco de estado y envías el formulario, el servidor guarda la información y la devuelve al cliente cuando finaliza su proceso. Es una forma sencilla de almacenar información personalizada que un usuario no haya tecleado, por ejemplo un cálculo. Se accede al saco de estado mediante la variable ViewState. Ejemplo: Guardar la hora en curso en el saco de estado tan pronto como se carga la página. Cuando el usuario 41 hace clic en el botón Enviar, se compara la hora de inicio con la nueva hora. <%@ Page Language="VB" %> <script runat="server"> Sub Page_Load(obj as object, e as EventArgs) If Not Page.IsPostBack then ViewState("HoraInicio") = DateTime.Now lblMensaje.Text = "Ahora son: " & _ ViewState("HoraInicio") End If End Sub Como se necesita almacenar la hora la primera vez que se accede a la página, tenemos que verificar la propiedad IsPostBack. Si es el primer acceso almacenamos la hora en la variable ViewState. Sub Enviar(obj as object, e as EventArgs) lblMensaje.Text = "Ahora son: " & _ DateTime.Now & "<br>iniciado a las: " & _ ViewState("HoraInicio") End Sub </script> <html><body> <font size="5">Aprendiendo ASP.NET </font><hr><p> <form runat="server"> <asp:Button id="btEnviar" runat="server" Text="Enviar" onClick="Enviar" /> <p> <asp:Label id="lblMensaje" runat=server /> </form> </body></html> 42 <%@ Page Language="c#" %> <script runat="server"> public void Page_Load (Object sender, EventArgs E) { if (!Page.IsPostBack) { ViewState["HoraInicio"] = DateTime.Now; lblMensaje.Text = "Ahora son: " + ViewState["HoraInicio"]; } } Como se necesita almacenar la hora la primera vez que se accede a la página, tenemos que verificar la propiedad IsPostBack. Si es el primer acceso almacenamos la hora en la variable ViewState. public void Enviar(Object sender, EventArgs E) { lblMensaje.Text = "Ahora son: " + DateTime.Now + "<br>iniciado a las: " + ViewState["HoraInicio"]; } </script> <html><body> <font size="5">Aprendiendo ASP.NET </font><hr><p> <form runat="server"> <asp:Button id="btEnviar" runat="server" Text="Enviar" onClick="Enviar" /> <p> <asp:Label id="lblMensaje" runat=server /> </form></body></html> 43 (ver tema4−estado) EJERCICIO: 44 45 46 Solución: tema−saco−prueba3 ORDEN DE PROCESAMIENTO DE LOS FORMULARIOS WEB 1 La página se solicita (o envía) 2 Se restaura el estado visual de los controles 3 Ocurre el evento Page_Load 4 Los eventos se controlan, se ejecutan los métodos que controlan eventos. 5 Ocurre el evento Page_Unload CONTOLES HTML DE SERVIDOR Los controles HTML ofrecen a los desarrolladores de entornos Web la potencia de los Web Forms 47 manteniendo la familiaridad y facilidad de uso de las etiquetas HTML que representan los campos de un formulario. Estos controles tienen el mismo aspecto que una etiqueta HTML a excepción de que presentan el atributo runat con el valor server. Si queremos realizar el tratamiento de eventos con código del servidor, utilizaremos el atributo onserverevento, a este atributo se le indica como valor el nombre del método que queremos ejecutar. Los elementos HTML están totalmente basados en el cliente. Un explorador conoce el aspecto y funcionamiento de <input type=text> y lo interpreta de acuerdo con eso. Los controles HTML de servidor son elementos u objetos que se crean en éste, con propiedades, métodos y eventos que podemos controlar. Son muy fáciles de generar: sólo hay que agregar el atributo runat=server a cualquier elemento HTML. Todos estos controles pertenecen al espacio de nombres System.Web.UI.HtmlControls. <%@ Page Language="VB" %> <script runat="server"> Sub Clic(obj as object, e as EventArgs) select case obj.Value case "Izquierda" word_image.align = "left" case "Derecha" word_image.align = "right" case "Centro" word_image.align = "center" end select Aquí establezco el estilo de los botones. Quiero que el botón que fue oprimido aparezca sumido. Por eso hay que sacar el resto con el valor notset. Izquierda.Style("Border−Style") = "notset" Derecha.Style("Border−Style") = "notset" Centro.Style("Border−Style") = "notset" Establezco a inset la propiedad del botón representado por obj. 48 obj.Style("Border−Style") = "inset" end Sub </script> Aquí tenemos 6 elementos HTML: un formulario, tres botones, una imagen y una sección <div>. Los controles HtmlInputButton (botones) tienen un evento llamado ServerClick, que sucede cuando se oprimen. <html><body> <font size="5">Aprendiendo ASP.NET: </font><hr><p> <form runat="server"> <input type="Button" id="Izquierda" runat="server" Value="Izquierda" OnServerClick="Clic" /> <input type="Button" id="Centro" runat="server" Value="Centro" OnServerClick="Clic" /> <input type="Button" id="Derecha" runat="server" Value="Derecha" OnServerClick="Clic" /> </form> <img src="carita.jpg" id="word_image" runat="server"> <div id="Label1" runat="server">Éste es un texto de ejemplo. Cuando los botones de arriba se opriman, la imagen se moverá por el texto para acomodarse en la posición elegida.<p> Este ejemplo demuestra los controles HtmlImage y HtmlInputButton. </div> </body></html> Ver ejercicios/tema4/caritavb/prueba4vb.aspx EJERCICIO Realizar ese mismo ejercicio con C#. Solución: ejercicios/tema4/caritaCsharp HtmlAnchor : 49 Esta clase se corresponde con la etiqueta <a>, es decir, es el control HTML que nos permite manejar enlaces. El elemento HTML <a> permite crear un hipervínculo para desplazarse a otra ubicación de la página o a otra página Web. HmlButton : Este control HTML generará la etiqueta <button> de HTML Esta control HTML se utilizará cuando sea necesario personalizar al máximo el aspecto de un botón permite incluir texto con formato, imágenes u otros controles de formularios Web Forms. HtmlForm : Esta clase representa a la etiqueta <form> en el servidor, es la que permite definir un Web Form, que va a realizar la labor de contenedor para una serie de controles de servidor dentro de la página ASP .NET. Todos los controles ASP .NET que deseemos enviar al servidor (post) debemos incluirlos dentro de un control de la clase HtmlForm. HtmlGenericControl : Esta clase se utilizará para representar las etiquetas HTML que no poseen una correspondencia directa con las clases del .NET Framework, como puede suceder con las etiquetas <span>, <div> o <body>, entre otras. HtmlImage : Esta clase permite utilizar la etiqueta <img> de HTML en el servidor, es decir, el control <img runat=server>. Nos permite por lo tanto manejar imágenes. HtmlInputCheckBox : se corresponde con la etiqueta <input type=checkbox>, y gracias a el tenemos acceso en el servidor a este tipo de elemento Para determinar si se selecciona el control, utilice la propiedad Checked. HtmlInputRadioButton : El control HTML que es instancia de esta clase generará en el cliente una etiqueta <input type=radio>, permitiendo al código de servidor interactuar con este elemento. No tiene funcionalidad integrada para mostrar un título para el botón de opción Para determinar si el control HtmlInputRadioButton está seleccionado, pruebe la propiedad Checked. HtmlInputText: Se corresponde con las etiquetas <input type=text> y <input type=password>. El tipo de caja de texto que se genera viene dado por el valor de la propiedad type. Este control ya lo hemos visto en acción en varios ejemplos. HtmlSelect: 50 Este control HTML se corresponde con una lista desplegable del lenguaje HTML, es decir, con una etiqueta <select>. HtmlTable : Este control se corresponde con una tabla del lenguaje HTML, es decir, permite el acceso desde el código de servidor a una etiqueta <table>. Esta clase posee una colección llamada Rows, que contiene objetos de la clase HtmlTableRow. Propiedades: Border:Use la propiedad Border para especificar el ancho del borde (en píxeles). BgColor:Obtiene o establece el color de fondo CellPadding:Obtiene o establece la cantidad de espacio entre el contenido de una celda y el borde de la misma CellSpacing:Obtiene o establece la cantidad de espacio (en píxeles) entre las celdas adyacentes HtmlTableRow Clase relacionada con la anterior, es el control HTML que permite manipular una fila de una tabla. Esta clase posee una colección llamada Cells, que contiene objetos de la clase HtmlTableCell. HtmlTableCell Clase que permite el acceso a las celdas de una tabla, es decir, se corresponde con las etiquetas <td> y <th>. CONTOLES WEB DE SERVIDOR Los controles Web ofrecen un mayor nivel de abstracción que los controles HTML, y su modelo de objetos no refleja la sintaxis HTML necesariamente. Cuando la página se carga en el navegador, el control Web determina el tipo de navegador que ha realizado la petición, y de acuerdo con esta información genera el código HTML apropiado, podemos decir que en este aspecto se trata de controles inteligentes. Son similares a los controles HTML de servidor. Se generan en el servidor y permiten crear interfaces de usuario complejas con facilidad. Necesitan el atributo runat=server. No necesariamente se relacionan con elementos HTML y pueden representar elementos más complejos de la interfaz de usuario. Por ejemplo, el control web Calendar. Para crear un control web, utilizar la siguiente sintaxis: <asp:Control id=nombre runat=server> La clase de base System.Web.UI.WebControls.WebControl contiene todas las propiedades comunes. La mayoría de los controles Web de servidor derivan de esta clase. Para usar un control Web de servidor, use la sintaxis siguiente (que usa el control TextBox como ejemplo): <asp:textbox text="hello world" runat=server /> 51 Los controles Web básicos proporcionan la misma funcionalidad que sus correspondientes controles HTML de servidor. Sin embargo, los controles Web básicos incluyen métodos, eventos y propiedades adicionales que puede usar par programar. Tres tipos de controles Web: controles Web intrínsecos (que son los equivalentes a los controles HTML), controles Web de lista, controles Web ricos controles Web de validación Los beneficios que se desprenden de utilizar controles Web intrínsecos sobre los controles HTML vistos anteriormente son: Se ofrece una convención de nomenclatura para controles similares. Existen propiedades comunes para todos los controles, ofreciéndose un modelo de objetos más robusto. Se incluyen propiedades específicas de los controles. Se genera código HTML específico para cada navegador Web. Similitud con Controles HTML Al igual que sucedía con los controles HTML, para permitir hacer referencia a los controles dentro del código fuente de la página, se debe utilizar el atributo id. Diferencias con Controles HTML Al declarar los controles. Algunos nombres de las propiedades cambian En los métodos para el tratamiento de eventos de la pulsación de un botón del ratón en los controles HTML utilizamos la propiedad onserverclick, y en los controles Web utilizamos la propiedad onclick. Button: Este control Web representa un botón, se corresponde con la etiqueta <input type=submit>, es decir, un botón que envía el contenido de un formulario al servidor. Esta clase se corresponde con el control Web <asp:Button> CheckBox : Control Web que se corresponde con una etiqueta <input type=checkbox> del lenguaje HTML. Propiedad AutoPostBack:establece un valor que indica si el estado del control CheckBos se devuelve automáticamente al servidor cuando se hace clic en él. CheckBoxList 52 Este control permite utilizar una lista de selección múltiple de elementos checkbox. Este objeto posee una colección Items que contiene todos los objetos CheckBox. Se puede especificar a través de las propiedades RepeatDirection y RepeatLayout la distribución de los CheckBox en la página. DropDownList : Este control Web representa una lista desplegable, y se corresponde con la etiqueta <select> de HTML PostBack Cada uno de los elementos del control DropDownList se indica con un objeto de la clase ListItem. HyperLink Este otro control Web representa un enlace en la página, por lo tanto generará en el cliente una etiqueta <a>. Image Control Web que representa una imagen dentro de una página ASP .NET, generará como resultado de su ejecución una etiqueta <img> de HTML. Para indicar la imagen que deseamos mostrar se utilizará la propiedad ImageURL. ImageButton Este control es muy similar al anterior, pero además de mostrar una imagen posee la característica adicional de funcionar como un botón de tipo submit, es decir, al pulsar el botón se envían los contenidos del formulario al servidor. Este control generan en el cliente la etiqueta HTML <input type=image>. LinkButton Este control va a representar un botón que presenta un estilo similar a los enlaces, el control LinkButton presenta una apariencia similar a un control Hyperlink, pero sin embargo ofrece la misma funcionalidad que un control Button, es decir, presenta un texto a modo de enlace que al pulsarlo enviará el formulario en el que se encuentre al servidor. ListBox Este nuevo control Web representa una lista de selección sencilla o múltiple, es similar al control DropDownList, pero en este caso se muestran varios elementos de la lista y se permite la selección múltiple. Este control Web también se corresponde con una etiqueta <select> en el código HTML Rows:indicamos el número de filas visibles SelectionMode: indicamos si se permite la selección múltiple, mediante el valor Multiple, o bien la selección simple mediante el valor Single. Panel Este otro control Web intrínseco se utiliza para agrupar controles y realizar la función de contenedor de los 53 mismos. El control Panel posee una propiedad llamada Controls que es una colección que contiene todos los controles incluidos dentro del objeto Panel. PlaceHolder Control Web que realiza también la función de un contenedor de controles Web, pero en este caso no genera ningún código HTML, se utiliza para añadir controles Web de forma dinámica en la página ASP .NET en un punto determinado, para ello se utiliza su propiedad Controls. RadioButton Este control representa un botón de opción que se corresponde con el elemento <input type=radio> de HTML. Muestra la misma funcionalidad, es decir, permite seleccionar una opción dentro de un mismo grupo de opciones. Las opciones se agrupan mediante la propiedad GroupName . RadioButtonList Este control permite utilizar una lista de selección múltiple de controles RadioButton. Este objeto posee una colección Items que contiene todos los objetos RadioButton. Se puede especificar a través de las propiedades RepeatDirection y RepeatLayout la distribución de los RadioButton en la página, como se puede apreciar es muy similar al control CheckBoxList, pero en este caso se utilizan controles RadioButton. Table, TableRow y TableCell Estos controles Web se encuentran muy relacionados entre sí, mediante la utilización de todos ellos podremos generar tablas en HTML. El control Web Table se corresponde con una tabla del lenguaje HTML, es decir, permite generar tablas del lenguaje HTML. Esta clase posee una colección llamada Rows, que contiene objetos de la clase TableRow. Aplicando estilos a los controles Los controles Web ofrecen un completo soporte para las hojas de estilo, es decir, podemos aplicar los estilos de forma similar a como lo hacemos en HTML para personalizar el aspecto de nuestros controles. Tres formas de aplicar estilos: Mediante propiedades: Es mediante la propiedad CssClass Mediante la propiedad Style: Es una colección que nos permite asignar valores a las distintas propiedades del estilo del control. <%@ Page Language="VB" %> <script runat="server"> Sub Enviar(obj as object, e as eventargs) Dim strIngreso As String = lbIngreso.SelectedItem.Text 54 Dim strEdad As String = rlEdad.SelectedItem.Text lblMensaje.Text = "¡Hola, " & tbNombre.Text & "!<p>" & _ "Su ingreso es de: " & strIngreso & "<br>" & _ "Su edad es: " & strEdad & "<br>" If rlEdad.SelectedIndex < 3 Then lblMensaje.Text += "¡Eres joven!<p>" Else lblMensaje.Text += "¡Eres experimentado!<p>" End If If cbBoletin.Checked Then lblMensaje.Text += "Pronto recibirá nuestro " & _ "boletín." End If End Sub </script> <html><body> <form runat="server"> <asp:Label id="lblEncabezado" runat="server" Height="25px" Width="100%" BackColor="#ddaa66" ForeColor="white" Font−Bold="true" Text="Un ejemplo de controles Web" /> <br> <asp:Label id="lblMensaje" runat="server" /><p> Teclee su nombre: <asp:TextBox id="tbNombre" runat="server" /><p> Seleccione su edad:<br> 55 <asp:RadioButtonList id="rlEdad" runat="server" RepeatDirection="horizontal"> <asp:ListItem><18</asp:ListItem> <asp:ListItem>19−24</asp:ListItem> <asp:ListItem>25−34</asp:ListItem> <asp:ListItem>35−49</asp:ListItem> <asp:ListItem>50−65</asp:ListItem> </asp:RadioButtonList><p> Elija sus ingresos:<br> <asp:ListBox id="lbIngreso" runat="server" size=1> <asp:ListItem>< 999€ al año</asp:ListItem> <asp:ListItem>1000€−9999€</asp:ListItem> <asp:ListItem>10000€−49999€</asp:ListItem> <asp:ListItem>> 50000€</asp:ListItem> </asp:ListBox><p> ¿Quiere recibir nuestro boletín?<br> <asp:CheckBox id="cbBoletin" runat="server" Text="¡Sí!" /><p> <asp:Button id="btEnviar" runat="server" Text="Enviar" OnClick="Enviar" /> </form> </body></html> Ver ejercicios/tema4/demografico/demograficoVB EJERCICIO Realizar ese mismo ejercicio con C#. 56 Solución: ejercicios/tema4/demografico/demograficoC CÓMO ENVIAR DATOS INMEDIATAMENTE Por ejemplo, imaginar un formulario que muestra las provincias de un país. Una vez seleccionada una provincia, se envía el formulario, se realiza cierto procesamiento y se filtra la lista de ciudades de esa provincia. Se puede enviar datos inmediatamente con la propiedad AutoPostBack de los controles web. A true indica al control que envíe los datos tan pronto como ocurra el evento. <%@ Page Language="VB" %> <%@ Import Namespace="System.Drawing" %> Se importa para poder usar el objeto Color. <script runat="server"> Sub ControladorDeNombre(obj as object, e as eventargs) lblMensaje.Text = tbNombre.Text & ", elija un color: " end sub Sub ControladorDeLista(obj as object, e as eventargs) Dim strColor As String Select Case obj.SelectedItem.Text Case "Rojo": strColor = "red" Case "Azul": strColor = "blue" Case "Verde": strColor = "green" Case "Blanco": strColor = "white" End Select El método Color.FromName crea un objeto Color de acuerdo al color indicado. Se puede utilizar este objeto par establecer el color del listbox. lbColor.BackColor = Color.FromName _ (strColor) End Sub </script> 57 <html><body> <form runat="server"> Declaro un control web TextBox. Cuando ocurre el evento TextChanged se ejecuta el método ControladorDeNombre porque la propiedad AutoPostBack está a trae. <asp:TextBox id="tbNombre" runat="server" OnTextChanged="ControladorDeNombre" AutoPostBack="true" /><p> <asp:Label id="lblMensaje" runat="server" Text="Elija un color: " /><p> <asp:ListBox id="lbColor" runat="server" OnSelectedIndexChanged="ControladorDeLista" AutoPostBack="true" > Lo mismo aquí. <asp:Listitem>Rojo</asp:Listitem> <asp:Listitem>Azul</asp:Listitem> <asp:Listitem>Verde</asp:Listitem> <asp:Listitem>Blanco</asp:Listitem> </asp:ListBox> </form> </body></html> Ver ejercicios/tema4/autopostback/ autopostbackVB EJERCICIO: Cuando se seleccione un item le da lista aparecerá una etiqueta informando cuál se ha seleccionado. Al escribir un nombre en la caja de texto aparecerá en la etiqueta el nombre seguido de elige un color, al elegir un color de la lista cambiará el color de la lista 58 59 Solución: Ejercicios/tema4/Autopostback/aaa Debemos: Utilizar elementos HTML regulares cuando no necesitemos controlarlos de forma programática. Por ejemplo, no necesitamos manipular un vínculo, así que será mejor usar la etiqueta <a ref> en lugar de un control HtmlAnchor o HyperLink. Utilizar controles HTML de servidor cuando no deseemos invertir mucho tiempo en convertir páginas existentes a formularios web. Utilizar controles web de servidor cuando generemos formularios web que necesiten un acceso programado. Con Asp net en distintas llamadas al formulario se mantiene el estado del mismo, es decir, se mantiene en la lista el elemento seleccionado, sin que tengamos que escribir ningún código adicional, esto es posible gracias al campo oculto que genera el Web Form y que se denomina _VIEWSTATE. Por lo tanto los Web Forms nos permiten en distintas peticiones conservar los valores de los campos de los formularios. 60 EJERCICIOS: • Genera una aplicación para elegir el nombre de un bebé. El usuario elegirá el sexo del bebé, y, entonces, un listBox mostrará algunos nombres posibles. Cuando el usuario elija un nombre, se mostrará un mensaje con el nombre elegido. Solución: tema4−bebe • Genera una página estándar para registrar usuarios con los siguientes campos: nombre (necesario), fax y dirección de correo electrónico (necesario). Si falta alguno de los campos necesarios, muestra un mensaje de error al usuario. Solución: tema4−Registro PREGUNTAS PARA ENTREGAR: • ¿Cómo llevan un control del estado visual los formularios web? • ¿Qué hace el saco de estado, y cómo se puede acceder a él? • Verdadero o falso: Los eventos de los formularios Web se procesan antes que el evento Page_Load. • ¿Cuál es la lista de parámetros estándar de un evento? • ¿Cuál es la importancia de la etiqueta runat=server? • ¿Para qué deberías utilizar controles HTML del servidor? • ¿Cuál es el error en la siguiente sección de código? <asp:Button id=btEnviar Clic=ControlaEsto> • ¿Qué propiedad puedes utilizar para enviar código inmediatamente al servidor al ocurrir un evento? • ¿Cuándo deberías utilizar controles Web en lugar de controles HTML de servidor? TEMA 5: UN POCO MÁS DE FORMULARIOS WEB CONTROLES DE USUARIO Permiten guardar y reutilizar la funcionalidad que se desee de la interfaz de usuario. Esquema típico: un formulario de inicio de sesión. Suelen tener dos cajas de texto (usuario y contraseña) y un botón Enviar. Podemos crear un control de usuario que realice la misma tarea. COMO GENERAR CONTROLES DE USUARIO Un control de usuario es un archivo ASP.NET con una extensión .ascx. Contiene elementos de la interfaz de usuario y código para controlarlos. Las diferencia es que los controles de usuario están integrados en otras páginas en lugar de ser independientes. El siguiente listado lo guardaríamos con extensión ascx. Sería un típico inicio de sesión. No contiene las etiquetas <html>,<form> o <body>. <%=colorFondo%> es un bloque proveedor de código. Establece el color de fondo recogiéndolo de la variable colorFondo. No podemos visualizarlo si no lo colocamos en una página asp.net. <table style="background−color:<%=colorFondo%>;font: 10pt verdana;border−width:1;border−style:solid;border−color:black;" cellspacing=15> <tr> 61 <td><b>Inicio de sesión: </b></td> <td><ASP:TextBox id="Usuario" runat="server"/></td> </tr> <tr> <td><b>Contraseña: </b></td> <td><ASP:TextBox id="Contr" TextMode="password" runat="server"/></td> </tr> <tr> <td></td> <td><ASP:Button Text="Enviar" runat="server" OnClick="Enviar" /></td> </tr> </tabla> <p> <ASP:Label id="lblMensaje" runat="server"/> Vamos a ver la página asp.net en la que se basa el control de usuario. <%@ Page Language="C#" %> <script runat="server"> string nombreUsuario; string contrasenia; string colorFondo; Public void Enviar(Object obj, Eventargs e) { lblMensaje.Text = "nombreUsuario: <b>" + Usuario.Text + "</b><br>" +"contrasenia: <b>" + Contr.Text + "</b><p>"; } </script> 62 <html><body> <form runat="server"> <table style="background−color:<%=colorFondo%>; font: 10pt verdana;border−width:1; border−style:solid;border−color:black;" cellspacing=15> <tr> <td><b>Inicio de sesión: </b></td> <td><ASP:TextBox id="Usuario" runat="server"/></td> </tr> <tr> <td><b>Contraseña: </b></td> <td><ASP:TextBox id="Contr" TextMode="password" runat="server"/></td> </tr> <tr> <td></td> <td><ASP:Button Text="Enviar" runat="server" OnClick="Enviar" /></td> </tr> </table> <p> <ASP:Label id="lblMensaje" runat="server"/> </form> </body></html> Ver tema5−inicio(no está en block de notas) 63 Declaro las variables nombreUsuario, contrasenia y colorFondo, y método enviar. Hay 3 pasos para convertir una página ASP.NET en control de usuario. • Quitar las etiquetas <html>,<form> y <body>. • Modificar el archivo para que tenga extensión ascx. • Cambiar la directiva Page por Control. <%@ Page Language=C# %> sería <%@ Control Language=C# %> La declaración del código del control de usuario sería: <script runat="server" language="c#"> public string nombreUsuario; public string contrasenia; public string colorFondo="White"; public void Enviar(Object obj, EventArgs e) { lblMensaje.Text = "nombreUsuario: <b>" + Usuario.Text + "</b><br>" +"contrasenia: <b>" + Contr.Text + "</b><p>"; } </script> <table style="background−color:<%=colorFondo%>; font: 10pt verdana;border−width:1; border−style:solid;border−color:black;" cellspacing=15> <tr> <td><b>Inicio de sesión: </b></td> <td><ASP:TextBox id="Usuario" runat="server"/></td> </tr> <tr> <td><b>Contraseña: </b></td> 64 <td><ASP:TextBox id="Contr" TextMode="password" runat="server"/></td> </tr> <tr> <td></td> <td><ASP:Button Text="Enviar" runat="server" OnClick="Enviar" ID="Button1"/></td> </tr> </table> <p> <ASP:Label id="lblMensaje" runat="server"/>v COMO UTILIZAR CONTROLES DE USUARIO Se utilizan como cualquier otro control. Creando una instancia en la porción de la interfaz de la página. Para colocar controles de usuario en otras páginas asp.net, primero hay que registrarlos con la directiva @Register Al registrar un control le decimos a asp.net que queremos extender el formulario web con un control de servidor nuevo. Se hace con el propósito de que la página tenga una ruta válida y un nombre definido para utilizar el control: <%@ Register TagPrefix=Prefijo TagName=nombreControl src=rutaDelArchivo Namespace=Nombre %> El atributo TagPrefix define al grupo al que pertenece el control. Puede tener el TagPrefix que yo quiera. La propiedad TagName da al control un nombre. La propiedad src indica el lugar de origen del control de usuario. El atributo Namespace es un elemento opcional que establece un espacio de nombre que se asociará con el TagPrefix. Esto sirve para agrupar y clasificar posteriormente los controles de usuario. <%@ Page Language="VB" %> <%@ Register TagPrefix="AASPNET" TagName="inicioSesion" src="inicioSesion.ascx" %> <script runat="server"> Sub Page_Load(obj as object, e as eventargs) lblMensaje.Text = "Propiedades del control " & _ 65 "de usuario:<br> " & _ "identificador: " & inicioSesion1.id & "<br>" & _ "colorFondo: " & inicioSesion1.colorFondo & "<br>" & _ "nombreUsuario: " & inicioSesion1.nombreUsuario & "<br>" & _ "contrasenia: " & inicioSesion1.contrasenia end sub </script> <html><body> <form runat="server"> <AASPNET:inicioSesion id="inicioSesion1" runat="server" contrasenia="MiContrasenia" nombreUsuario="David" colorFondo="Beige" /> </form> <p> <asp:Label id="lblMensaje" runat="server" /> <p> </body></html> <%@ Page Language="C#" %> <%@ Register TagPrefix="AASPNET" TagName="inicioSesion" src="inicioSesion.ascx" %> Establece su prefijo como AASPNET y su nombre de control en inicioSesion <script runat="server"> public void Page_Load(Object obj, EventArgs e) { lblMensaje.Text = "Propiedades del control de usuario:<br> " + "colorFondo: " + inicioSesion1.colorFondo + "<br>" + 66 "nombreUsuario: " + inicioSesion1.nombreUsuario + "<br>" + "contrasenia: " + inicioSesion1.contrasenia; } Muestra las propiedades del control en la etiqueta. </script> <html><body> <form runat="server"> Son las propiedades públicas del control <AASPNET:inicioSesion id="inicioSesion1" runat="server" contrasenia="MiContrasenia" nombreUsuario="David" colorFondo="Beige" /> </form> <p> <asp:Label id="lblMensaje" runat="server" /> <p> </body></html> Ver tema5−EjemploUserControl CONTROLES PERSONALIZADOS No son controles de usuario. En lugar de encapsular cierta funcionalidad de la interfaz del usuario, pueden definir su comportamiento totalmente original. Por ejemplo, ASP.NET no ofrece un control integrado para interpretar dibujos monocromáticos. Un desarrollador podría generar un control personalizado para ofrecer esta funcionalidad. Los controles de usuario se utilizan cuando se desea combinar la funcionalidad de controles existentes, los controles personalizados se utilizan cuando ninguno de los controles existentes cumple con sus necesidades. Todos los objetos en el marco de trabajo de los formularios Web se derivan directa o indirectamente de la clase System.Web.UI.Control. Se puede insertar un control personalizado en cualquier parte de esta jerarquía, siempre y cuando derive de alguna manera de la clase Control. EJERCICIOS: Generar un planificador de juntas. Deberá incluir un calendario, un cuadro de texto para capturas del 67 usuario y una etiqueta que muestre los datos en curso. Utilizar AutoPostBack y el evento TextChanged cuando el usuario teclee notas en el cuadro de texto. Almacenar dichas notas en variables de sesión de modo que el usuario pueda verlas posteriormente. Cuando se agregue una nota, generar dinámicamente una etiqueta para recibir alguna reacción. Será un control .ascx y se incluirá en una página .aspx Solución tema5/ Tema5Ej PREGUNTAS PARA ENTREGAR: • Verdadero o falso: Un control de usuario puede utilizarse de manera independiente. • ¿Cuáles son los tres requerimientos para convertir un archivo .aspx en control de usuario? TEMA 6: VALIDACIÓN DE LAS PÁGINAS ASP.NET ESQUEMAS DE VALIDACIÓN La validación de lo que captura el usuario en los formularios es una de las tareas más importantes para los desarrolladores. Una situación típica donde se requiere validación: La interfaz pide el nombre y apellidos, dirección de correo electrónico, domicilio, ciudad, estado, código postal y número de teléfono del usuario. <html><body> <form runat="server"> <asp:Label id="lblEncabezado" runat="server" Height="25px" Width="100%" BackColor="#ddaa66" ForeColor="white" Font−Bold="true" Text="Un ejemplo de validación" /> <asp:Label id="lblMensaje" runat="server" /><br> <asp:Panel id="Panel1" runat="server"> <table> <tr> <td width="100" valign="top"> Nombre y apellidos: </td> <td width="300" valign="top"> 68 <asp:TextBox id="tbNombre" runat="server" /> <asp:TextBox id="tbApellidos" runat="server" /> </td> </tr> <tr> <td valign="top">Correo electrónico:</td> <td valign="top"> <asp:TextBox id="tbCorreoE" runat="server" /> </td> </tr> <tr> <td valign="top">Domicilio:</td> <td valign="top"> <asp:TextBox id="tbDomicilio" runat="server" /> </td> </tr> <tr> <td valign="top">Ciudad, Estado y Código postal:</td> <td valign="top"> <asp:TextBox id="tbCiudad" runat="server" />, <asp:TextBox id="tbEstado" runat="server" size=2 />&nbsp; <asp:TextBox id="tbCodigoPostal" runat="server" 69 size=5 /> </td> </tr> <tr> <td valign="top">Teléfono:</td> <td valign="top"> <asp:TextBox id="tbTelefono" runat="server" size=11 /><p> </td> </tr> <tr> <td colspan="2" valign="top" align="right"> <asp:Button id="btEnviar" runat="server" text="Agregar" /> </td> </tr> </table> </asp:Panel> </form> </body></html> 70 Se puede validar la captura de usuario con instrucciones if. Después de verificar todo lo capturado de esta forma, se puede tomar dos rutas. Si todo está en el formato correcto, se puede insertar en una base de datos. Si alguno de los datos no es correcto, hay que avisar al usuario dónde está el error y permitirle corregirlo antes de insertar los datos. VALIDACIÓN EN ASP.NET Permiten validar con facilidad cualquier dato que se haya capturado en un formulario Web. Admiten validaciones como campos necesarios, comparación de patrones o validaciones personalizadas. Permiten personalizar los mensajes de error. El trabajo de un control de validación es vigilar otro control de servidor y validar su contenido. Un mismo control puede tener distintos tipos de validación, es decir, se pueden utilizar distintos controles de validación sobre un mismo control a validar. 71 Los controles de validación funcionan en el cliente y en el servidor. Valida primero en el cliente, Asp no permite que un formulario sea enviado si tiene información inválida. Valida de nuevo en el servidor respecto a los recursos no disponibles en el cliente, como ejemplo una B.D. Propiedades importantes: ControlToValidate: Control a validar. ErrorMessage: Mensaje de error que sacará. IsValid: indica si la validación es correcta, también se puede hacer a nivel de página. TIPOS DE CONTROLES DE VALIDACIÓN EN ASP.NET RequiredFieldValidator Se utiliza para verificar que se ha dado algún valor a un campo, es decir, valida que se ha asignado un valor a un campo requerido de un Web Form. CompareValidator Este control Web de validación lo utilizaremos para comparar el valor que contiene un control Web con un valor específico, que puede ser un valor determinado especificado como una constante o bien un valor de otro control Web. Este control Web se utilizará con un operador de comparación, y presenta las siguientes propiedades adicionales: ValueToCompare: esta propiedad se utilizará cuando deseemos comparar el valor de un control Web con un valor constante, esta propiedad es la que contendrá este valor constante. ControlToCompare: esta propiedad se utilizará cuando deseemos compara el valor de un control Web con otro, esta propiedad contendrá el identificador del otro control contra el que se quiere comparar el control Web en cuestión. Type: indica el tipo de dato de los valores que se van a comparar, esta propiedad puede presentar los siguientes valores, Currency, Date, Double, Integer y String, que se corresponden con los distintos tipos de datos que podemos indicar. Operator: esta última propiedad va a contener el tipo de operador que se va a utilizar en la comparación de los dos valores. Esta propiedad puede tener los siguientes valores,Equal(igual)GreaterThan(mayor), GreaterThanEqual (mayor o igual), LessThan (menor), LessThanEqual (menor o igual ), NotEqual (distinto) y DataTypeCheck (validación de tipo). El operador DataTypeCheck es utilizado para validar el tipo de datos del control Web, en este caso no se compara con otro control, sino que únicamente se comprueba el tipo del valor del control. RangeValidator Este control Web se utilizará cuando sea necesario comprobar si un valor de entrada de un control Web se 72 encuentra comprendido en un rango determinado. El control RangeValidator ofrece tres propiedades adicionales para llevar a cabo su labor de validación, las propiedades son las siguientes: MinimumControl: esta propiedad define el valor mínimo del rango permitido para el control. MaximumControl: esta propiedad define el valor máximo Type: indica el tipo de dato que se utiliza para comparar los valores dentro del rango especificado, esta propiedad puede tener los siguientes valores, Currency, Date, Double, Integer y String. RegularExpressionValidator Este otro control Web de validación es utilizado para comparar el valor del control correspondiente con una expresión regular. Este control debe hacer uso de la propiedad ValidationExpression para indicar la expresión regular con la que se va a comparar el valor indicado en el control Web que se desea validar. ValidationSummary Este control difiere del resto, ya que en realidad no va a realizar un tipo de validación determinada, sino que contiene todos los mensajes de error que se han producido y muestra una lista de ellos en la página, en el caso de que la página no sea válida, es decir, algunas de las validaciones han fallado. Este control mostrará todos los mensajes indicados en la propiedad ErrorMessage de cada uno de los controles de validación cuya validación ha fallado en la página. Así en este caso los controles de validación no mostrarán el mensaje de error de la propiedad ErrorMessage, sino que mostrarán si procede el texto incluido entre sus etiquetas de inicio y fin. Propiedades: HeaderText: esta propiedad contendrá el texto que va a mostrarse como cabecera a modo de descripción de los errores. ShowSummary: esta propiedad, que puede tener los valores True/False, indicará si deseamos mostrar o no el resumen de validación de la página ASP .NET. DisplayMode: en esta propiedad podemos indicar la forma en la que se mostrarán las distintas descripciones de cada uno de los errores de validación encontrados en la página, puede presentar los siguientes valores, BulletList (una lista con puntos), List (una lista) y SingleParagraph (en un único párrafo). CustomValidator Este último control Web de validación se utilizará para realizar una validación personalizada, este control llamará a una función definida por el usuario que será la que realice la validación. Esta función puede estar definida en el cliente o bien en el servidor. Propiedades destacadas: ClientValidationFunction: en esta propiedad indicaremos el nombre de la función del lado del cliente que realizará la validación deseada, en este caso la función será una función definida en un lenguaje de script de 73 cliente , como puede ser JavaScript, y que sea soportado por el navegador. OnServerValidate: en esta propiedad debemos indicar el nombre de la función de servidor que se va a encargar de realizar la validación correspondiente, esta función se ejecutará cuando se produzca el evento ServerValidate, es decir, esta propiedad va a ser el manejador del evento que se produce cuando se realiza la validación en el servidor. La función de validación va a recibir dos parámetros: Uno de la clase Object, que representa al control de la clase CustomValidator. Otro objeto de la clase ServerValidateEventArgs, que se va a utilizar para indicar si la validación ha sido correcta o no. El objeto de clase ServerValidateEventArgs posee la propiedad Value para obtener el valor del control que se desea validar y la propiedad IsValid, en la que se indicará el resultado de la validación. Los controles que se pueden validar son: HtmlInputText HtmlTextArea HtmlSelect HtmlInputFile TextBox ListBox DropDownList RadioButtonList COMO FUNCIONAN LOS CONTROLES DE VALIDACIÓN Para generar un control Validation en una página ASP.net hay que agregar la etiqueta adecuada de validación al formulario Web. Los controles de validación funcionan tanto en el cliente como en el servidor. Cuando un usuario teclea datos en un control Web que infrinjan la regla de validación que hayamos especificado, el usuario será alertado de inmediato. Asp.net no permite que un formulario sea enviado si la información no es válida. Esto significa que no hay que enviar el formulario al servidor para hacer la validación, y que ésta se realiza en el cliente automáticamente. (La validación en el cliente sólo es posible en exploradores web que soporten DHTML y JavaScript). Cuando el formulario se envía por fin al servidor, asp.net vuelve a validad las capturas. Esto permite volver a verificar los datos respecto a los recursos que no hayan estado disponibles en el cliente, como una base de datos. Ejemplo sencillo de validación: <%@ Page Language="VB" %> 74 <script runat="server"> Sub Enviar(obj as object, e as eventargs) If Page.IsValid then lblMensaje.Text = "¡Ha pasado la validación!" End If End Sub </script> <html><body> <form runat="server"> <asp:Label id="lblMensaje" runat="server" /><p> Teclee su nombre: <asp:TextBox id="tbNombre" runat="server" /><br> <asp:RequiredFieldValidator runat="server" ControlToValidate="tbNombre" ErrorMessage="Se necesita su nombre."/><p> <asp:Button id="tbEnviar" runat="server" Text="Enviar" OnClick="Enviar" /> </form> </body></html> Ver tema6−sencilloVB.aspx <%@ Page Language="C#" %> <script runat="server"> void Enviar(Object sender, EventArgs e) { if (Page.IsValid) 75 { lblMensaje.Text = "¡Ha pasado la validación!"; } } </script> <html><body> <form runat="server"> <asp:Label id="lblMensaje" runat="server" /><p> Teclee su nombre: <asp:TextBox id="tbNombre" runat="server" /><br> <asp:RequiredFieldValidator runat="server" ControlToValidate="tbNombre" ErrorMessage="Se necesita su nombre."/><p> <asp:Button id="tbEnviar" runat="server" Text="Enviar" OnClick="Enviar" /> </form> </body></html> La propiedad ControlToValidate establece a qué control debe vigilar este validador (a tbNombre en este caso). Si captura cualquier dato en el cuadro de tbNobmre, se cumple RequiredFieldValidator. Este control verifica si un campo contiene datos. Todo control de validación contiene una propiedad IsValid que indica si la validación es correcta. Cuando el formulario se envía se ejecuta el método Enviar. La propiedad Page.IsValid garantiza que se cumplan todos los controles de validación de la página. También se podría verificar la propiedad IsValid de cada control. Hacer la prueba haciendo saltar el mensaje de error y escribiendo algo en la caja de texto y pulsando fuera sin enviar. El mensaje de error desaparece porque se valida al perder el foco. USO DE LOS CONTROLES DE VALIDACIÓN 76 Todos los controles de validación comparten propiedades similares. Dos propiedades, (sin incluir a runat=server). ControlToValide: establece el nombre del control de servidor que deberá ser vigilado por este validador. ErrorMessage que indica a asp.net el mensaje por mostrar al usuario si falla la validación. Veamos que tipos de validación se necesitan aquí: <html><body> <form runat="server"> <asp:Label id="lblEncabezado" runat="server" Height="25px" Width="100%" BackColor="#ddaa66" ForeColor="white" Font−Bold="true" Text="Un ejemplo de validación" /> <asp:Label id="lblMensaje" runat="server" /><br> <asp:Panel id="Panel1" runat="server"> <table> <tr> <td width="100" valign="top"> Nombre y apellidos: </td> <td width="300" valign="top"> <asp:TextBox id="tbNombre" runat="server" /> <asp:TextBox id="tbApellidos" runat="server" /> </td> </tr> <tr> <td valign="top">Correo electrónico:</td> <td valign="top"> <asp:TextBox id="tbCorreoE" 77 runat="server" /> </td> </tr> <tr> <td valign="top">Domicilio:</td> <td valign="top"> <asp:TextBox id="tbDomicilio" runat="server" /> </td> </tr> <tr> <td valign="top">Ciudad, Estado y Código postal:</td> <td valign="top"> <asp:TextBox id="tbCiudad" runat="server" />, <asp:TextBox id="tbEstado" runat="server" size=2 />&nbsp; <asp:TextBox id="tbCodigoPostal" runat="server" size=5 /> </td> </tr> <tr> <td valign="top">Teléfono:</td> <td valign="top"> <asp:TextBox id="tbTelefono" runat="server" size=11 /><p> 78 </td> </tr> <tr> <td colspan="2" valign="top" align="right"> <asp:Button id="btEnviar" runat="server" text="Agregar" /> </td> </tr> </table> </asp:Panel> </form> </body></html> 79 Para sus cuadros de texto nombre y apellido que se teclee algo, siempre y cuando sea texto. Esta validación requiere el control RequiredFieldValidator. Para mayor seguridad también podemos comprobar que no sean iguales. Con CompareValidator. En el cuadro del correo electrónico nos tendremos que asegurar que la dirección tenga un formato adecuado, como [email protected]. El control RegularExpressionValidator realiza esta función. Demos por hecho que queremos permitir sólo usuarios de cierto lugar (un rango de códigos postales) para enviar su formulario. Este tipo de validación se hace con RangeValidator. El mismo código mejorado: <html><body> <form runat="server"> <asp:Label id="lblEncabezado" runat="server" 80 Height="25px" Width="100%" BackColor="#ddaa66" ForeColor="white" Font−Bold="true" Text="Un ejemplo de validación" /> <asp:Label id="lblMensaje" runat="server" /><br> <asp:Panel id="Panel1" runat="server"> <table> <tr> <td width="100" valign="top"> Nombre y apellidos: </td> <td width="300" valign="top"> <asp:TextBox id="tbNombre" runat="server" /> <asp:TextBox id="tbApellidos" runat="server" /> <br> <asp:RequiredFieldValidator runat="server" ControlToValidate="tbNombre" ErrorMessage="Se necesita el nombre"/> <asp:RequiredFieldValidator runat="server" ControlToValidate="tbApellidos" ErrorMessage="Se necesitan los apellidos"/> <asp:CompareValidator runat="server" ControlToValidate="tbNombre" ControlToCompare="tbApellidos" Type="String" Operator="NotEqual" ErrorMessage="El nombre y los apellidos no pueden ser iguales" /> 81 </td> </tr> <tr> <td valign="top">Correo electrónico (sólo .com):</td> <td valign="top"> <asp:TextBox id="tbCorreoE" runat="server" /><br> <asp:RegularExpressionValidator runat="server" ControlToValidate="tbCorreoE" ValidationExpression="\w+\@\w+\.com" ErrorMessage="No es un correo electrónico correcto"/> </td> </tr> <tr> <td valign="top">Domicilio:</td> <td valign="top"> <asp:TextBox id="tbDomicilio" runat="server" /> </td> </tr> <tr> <td valign="top">Ciudad, Estado y Código postal (5 cifras):</td> <td valign="top"> <asp:TextBox id="tbCiudad" runat="server" /> 82 <asp:TextBox id="tbEstado" runat="server" size=2 />&nbsp; <asp:TextBox id="tbZonaPostal" runat="server" size=5 /><br> <asp:RegularExpressionValidator runat="server" ControlToValidate="tbZonaPostal" ValidationExpression="[0−9]{5}" ErrorMessage="No es una zona postal correcta" /> <br> <asp:RangeValidator runat="server" ControlToValidate="tbZonaPostal" MinimumValue="00000" MaximumValue="22222" Type="String" ErrorMessage="No se encuentra en la región adecuada" /> </td> </tr> <tr> <td valign="top">Teléfono (<i>xxxxx−xxxx</i>):</td> <td valign="top"> <asp:TextBox id="tbTelefono" runat="server" size=11 /><br> <asp:RegularExpressionValidator runat="server" ControlToValidate="tbTelefono" ValidationExpression="[0−9]{5}−[0−9]{4}" 83 ErrorMessage="No es un número telefónico correcto"/> </td> </tr> <tr> <td colspan="2" valign="top" align="right"> <asp:Button id="btEnviar" runat="server" text="Agregar" /> </td> </tr> </table> </asp:Panel> </form> </body></html> Los controles de correo electrónico, ciudad, estado, código postal y teléfono NO tienen sus correspondientes RequiredFieldValidators, lo que los convierte en opcionales. Aún si el campo está vacío, la propiedad IsValid devolverá true. El formulario sólo acepta ciertos tipos de direcciones electrónicas (terminar en .com), códigos postales (5 números) y números de teléfono (9 números, con un guión entre el cuarto y el quinto). Dos instancias de RequiredFieldValidators, aseguran que el usuario haya capturado algo en el nombre y apellidos. Estos controles sólo tienen las dos propiedades necesarias, ControToValidate y ErrorMessage. CompareValidator puede comparar el valor de un control de servidor con una constante, o con otro control de servidor. La propiedad Type indica el tipo de valores que comparará, como String, Double. Para comparar con un valor constante, en vez de ControlToCompare hay que usar ValueToCompare. Si sólo se quiere verificar si lo capturado por el usuario es de un tipo de dato válido, se establece la propiedad Operato de CompareValidator a DataTypeCheck y olvidarse de la propiedad ControlToCompare. En un formulario Web todo lo capturado será una cadena, por lo que se podría no obtener una validación correcta. Cuando tengamos dos o más controles Validation basados en un control de servidor, todas las condiciones deberán cumplirse para dar por válida la captura. El control RequierdFieldValidator considera inválido un campo en blanco. Todos los demás controles aceptan campos vacíos. COMO HACER VALIDACIONES EN EL SERVIDOR 84 Hay que controlar la validación en el servidor. La forma más sencilla de verificar el formulario es a través de la propiedad IsValid del objeto Page. Si todos los datos verificados por los controles de validación son satisfactorios, la propiedad tendrá valor true. Si cualquiera de ellos no lo es, será False. <%@ Page Language="VB" %> <script runat="server"> Sub Enviar (obj as object, e as eventargs) If Page.IsValid then lblMensaje.Text = "¡Correcto!" Else lblMensaje.Text = "Alguno de los campos no es válido." End if End sub </script> <html><body> <form runat="server"> <asp:Label id="lblEncabezado" runat="server" Height="25px" Width="100%" BackColor="#ddaa66" ForeColor="white" Font−Bold="true" Text="Un ejemplo de validación" /> <asp:Label id="lblMensaje" runat="server" /><br> <asp:Panel id="Panel1" runat="server"> <table> <tr> <td width="100" valign="top"> Nombre y apellidos: </td> <td width="300" valign="top"> 85 <asp:TextBox id="tbNombre" runat="server" /> <asp:TextBox id="tbApellidos" runat="server" /> <br> <asp:RequiredFieldValidator runat="server" ControlToValidate="tbNombre" ErrorMessage="Se necesita el nombre"/><br> <asp:RequiredFieldValidator runat="server" ControlToValidate="tbApellidos" ErrorMessage="Se necesitan los apellidos"/><br> <asp:CompareValidator runat="server" ControlToValidate="tbNombre" ControlToCompare="tbApellidos" Type="String" Operator="NotEqual" ErrorMessage="El nombre y los apellidos no pueden ser iguales" /> </td> </tr> <tr> <td valign="top">Correo electrónico (sólo .com):</td> <td valign="top"> <asp:TextBox id="tbCorreoE" runat="server" /><br> <asp:RegularExpressionValidator runat="server" ControlToValidate="tbCorreoE" ValidationExpression="\w+\@\w+\.com" 86 ErrorMessage="No es un correo electrónico correcto" /> </td> </tr> <tr> <td valign="top">Domicilio:</td> <td valign="top"> <asp:TextBox id="tbDomicilio" runat="server" /> </td> </tr> <tr> <td valign="top">Ciudad, Estado y Zona postal (5−digit):</td> <td valign="top"> <asp:TextBox id="tbCiudad" runat="server" />, <asp:TextBox id="tbEstado" runat="server" size=2 />&nbsp; <asp:TextBox id="tbZonaPostal" runat="server" size=5 /><br> <asp:RegularExpressionValidator runat="server" ControlToValidate="tbZonaPostal" ValidationExpression="[0−9]{5}" ErrorMessage="No es una zona postal correcta" /> <br> 87 <asp:RangeValidator runat="server" ControlToValidate="tbZonaPostal" MinimumValue="00000" MaximumValue="22222" Type="String" ErrorMessage="No se encuentra en la región adecuada" /> </td> </tr> <tr> <td valign="top">Teléfono (<i>xxxx−xxxx</i>):</td> <td valign="top"> <asp:TextBox id="tbTelefono" runat="server" size=11 /><br> <asp:RegularExpressionValidator runat="server" ControlToValidate="tbTelefono" ValidationExpression="[0−9]{4}−[0−9]{4}" ErrorMessage="No es un número telefónico correcto" /> </td> </tr> <tr> <td colspan="2" valign="top" align="right"> <asp:Button id="btEnviar" runat="server" text="Agregar" OnClick="Enviar" /> </td> 88 </tr> </table> </asp:Panel> </form> </body></html> <%@ Page Language="c#" %> <script runat="server"> Verifica si todos los controles Validation son válidos. public void Enviar(Object obj , EventArgs e) { if (Page.IsValid) { lblMensaje.Text = "¡Correcto!"; } else { lblMensaje.Text = "Alguno de los campos no es válido."; } } </script> <html><body> <form runat="server"> <asp:Label id="lblEncabezado" runat="server" Height="25px" Width="100%" BackColor="#ddaa66" ForeColor="white" Font−Bold="true" Text="Un ejemplo de validación" /> 89 <asp:Label id="lblMensaje" runat="server" /><br> <asp:Panel id="Panel1" runat="server"> <table> <tr> <td width="100" valign="top"> Nombre y apellidos: </td> <td width="300" valign="top"> <asp:TextBox id="tbNombre" runat="server" /> <asp:TextBox id="tbApellidos" runat="server" /> <br> <asp:RequiredFieldValidator runat="server" ControlToValidate="tbNombre" ErrorMessage="Se necesita el nombre"/><br> <asp:RequiredFieldValidator runat="server" ControlToValidate="tbApellidos" ErrorMessage="Se necesitan los apellidos"/><br> <asp:CompareValidator runat="server" ControlToValidate="tbNombre" ControlToCompare="tbApellidos" Type="String" Operator="NotEqual" ErrorMessage="El nombre y los apellidos no pueden ser iguales" /> </td> </tr> <tr> 90 <td valign="top">Correo electrónico (sólo .com):</td> <td valign="top"> <asp:TextBox id="tbCorreoE" runat="server" /><br> <asp:RegularExpressionValidator runat="server" ControlToValidate="tbCorreoE" ValidationExpression="\w+\@\w+\.com" ErrorMessage="No es un correo electrónico correcto" /> </td> </tr> <tr> <td valign="top">Domicilio:</td> <td valign="top"> <asp:TextBox id="tbDomicilio" runat="server" /> </td> </tr> <tr> <td valign="top">Ciudad, Estado y Zona postal (5−digit):</td> <td valign="top"> <asp:TextBox id="tbCiudad" runat="server" />, <asp:TextBox id="tbEstado" runat="server" size=2 />&nbsp; 91 <asp:TextBox id="tbZonaPostal" runat="server" size=5 /><br> <asp:RegularExpressionValidator runat="server" ControlToValidate="tbZonaPostal" ValidationExpression="[0−9]{5}" ErrorMessage="No es una zona postal correcta" /> <br> <asp:RangeValidator runat="server" ControlToValidate="tbZonaPostal" MinimumValue="00000" MaximumValue="22222" Type="String" ErrorMessage="No se encuentra en la región adecuada" /> </td> </tr> <tr> <td valign="top">Teléfono (<i>xxxx−xxxx</i>):</td> <td valign="top"> <asp:TextBox id="tbTelefono" runat="server" size=11 /><br> <asp:RegularExpressionValidator runat="server" ControlToValidate="tbTelefono" ValidationExpression="[0−9]{4}−[0−9]{4}" ErrorMessage="No es un número telefónico correcto" /> 92 </td> </tr> <tr> <td colspan="2" valign="top" align="right"> <asp:Button id="btEnviar" runat="server" text="Agregar" OnClick="Enviar" /> </td> </tr> </table> </asp:Panel> </form> </body></html> Ver tema6/ listado0706.aspx La colección Validators contiene referencias a todos los controles. Puede iterar por esta colección para determinar la validez de un control en particular: public void Enviar(Object obj , EventArgs e) { if (Page.IsValid) { lblMensaje.Text = "¡Correcto!"; } else { Ivalidator objValidator; Foreach objValidator in Validators { 93 lblMensaje.Text += objValidator.ErrorMessage; } } } También se puede verificar la propiedad IsValid de cualquier control mediante su nombre. Para ello hay que asignar la propiedad id de cada control de validación. Por ejemplo, si el RegularExpressionValidator del cuadro de texto del correo electrónico tuviera el id valCorreoE: If (!valCorreoE.IsValid) { lblMensaje.Text+=valCorreoE.Message; } COMO INHABILITAR LA VALIDACIÓN Con la propiedad Enabled a False: <asp:RegularExpressionValidator runat=server ControlToValidate=tbCodigoPostal Enabled=False/> También se puede inhabilitar toda la validación en el cliente estableciendo la propiedad clienttarget de la directiva <% @ Page %> con un valor de downlevel: <%@ Page Language=C# clienttarget=downlevel %> Este comando hace que asp.net piense que está tratando con un explorador que no soporta DHTML, por lo que no reconoce estos controles. COMO PERSONALIZAR LA VALIDACIÓN MENSAJES DE ERROR Los controles de validación pueden colocarse en cualquier parte de la página. Por ejemplo, se pueden colocar al principio de la página si se quiere agrupar los mensajes de error. Con la propiedad Display en Dynamic el siguiente código muestra los RequiredFieldValidator de los campos nombre y apellido como objetos desplegados de forma dinámica: Se agrupan los controles y se separan cuando aparece un mensaje de error. <asp: RequiredFieldValidator runat=server ControToValidate=tbNombre ErrorMessage=Se necesita un nombre Display=dynamic/> <asp: RequiredFieldValidator runat=server ControToValidate=tbApellidos ErrorMessage=Se necesita un apellido Display=dynamic/> <asp:CompareValidator runat=server ControlToValidate=tbNombre ControlToCompare=tbApellidos 94 Type=String Operator=NotEqual ErrorMessage=El nombre y los apellidos no pueden ser iguales Display=dinamic/> COMO MOSTRAR RESÚMENES DE VALIDACIÓN Técnicamente, los mensajes de error se colocan donde se encuentre el control Validation en la página. Podemos elegir dónde colocarlos: Directo: en el mismo lugar donde se encuentre el control de validación de la página. Resumen: en un resumen por separado (podría ser una ventana de aparición súbita en exploradores web que usasn DHTML). Tanto en directo como en resumen: los mensajes de error respectivos pueden ser distintos. Donde se quiera. El método es útil cuando queremos listar todos los mensajes de error en un lugar, como al principìo de la página. En lugar de colocar todos sus controles de validación en un lugar, podemos dejarlos donde estásn y valernos del control ValidationSummary. Este control despliega los mensajes de error en un lugar de la página con un formato especificado. <asp:ValidationSummary runat=server DisplayMode=BulletList/> Con la adición de la propiedad ShowMessageBox, puede generar un mensaje de aparición súbita con el control VatidationSummary. <asp:ValidationSummary runat=server ShowMessageBox=True DisplayMode=BulletList/> Se puede establecer la propiedad Text de los controles de validación con cualquier etiqueta HTML válida. Por lo que podemos mostrar imágenes en los mensajes de error. CONTROLES DE VALIDACIÓN PERSONALIZADOS Si ninguno de los controles de validación satisface nuestras necesidades con el control CustomValidator podemos definir cualquier tipo de validación que se necesite. Hay que crear un procedimiento. Cuando el usuario teclee datos el CustomValidator ejecutará el método que hayamos generado. <%@ Page Language="VB" %> <script runat="server"> Sub Enviar(obj as object, e as eventargs) ' Hacer algo End Sub Sub ValideEsto(obj as Object, args as _ 95 ServerValidateEventArgs) If Len(args.Value) < 8 Then args.IsValid = False Else args.IsValid = True End If End Sub </script> <html><body> <form runat="server"> <asp:Label id="lblMensaje" runat="server" /> <table> <tr> <td valign="top">Nombre de usuario:</td> <td valign="top"> <asp:Textbox id="tbNombreUsuario" runat="server" /> <br> <asp:CustomValidator runat="server" OnServerValidate="ValideEsto" Display="Dynamic" ControlToValidate="tbNombreUsuario" ErrorMessage="El nombre del usuario debe tener 8 o más caracteres."/> </td> </tr> <tr> <td valign="top">Contraseña:</td> 96 <td valign="top"> <asp:Textbox id="tbContrasenia" runat="server" TextMode="password" /> </td> </tr> <tr> <td align="right" colspan="2"> <ASP:Button id="tbEnviar" runat="server" OnClick="Enviar" Text="Enviar" /> </td> </tr> </table> </form> </body></html> <%@ Page Language="c#" %> <script runat="server"> public void (Object obj, EventArgs e) { // Hacer algo; } args contiene todo lo capturado por el usuario. Uliliza la propiedad value para recuperar el texto contenido en este objeto y la propiedad IsValid para establecer la validez del control. public void ValideEsto(Object obj, ServerValidateEventArgs args) { if(Len(args.Value) < 8) args.IsValid = False; 97 else args.IsValid = True; } </script> <html><body> <form runat="server"> <asp:Label id="lblMensaje" runat="server" /> <table> <tr> <td valign="top">Nombre de usuario:</td> <td valign="top"> <asp:Textbox id="tbNombreUsuario" runat="server" /> <br> OnServerValidate se procesa el primero. <asp:CustomValidator runat="server" OnServerValidate="ValideEsto" Display="Dynamic" ControlToValidate="tbNombreUsuario" ErrorMessage="El nombre del usuario debe tener 8 o más caracteres."/> </td> </tr> <tr> <td valign="top">Contraseña:</td> <td valign="top"> <asp:Textbox id="tbContrasenia" runat="server" TextMode="password" /> 98 </td> </tr> <tr> <td align="right" colspan="2"> <ASP:Button id="tbEnviar" runat="server" OnClick="Enviar" Text="Enviar" /> </td> </tr> </table> </form> </body></html> CustomValidator también permite validar en el cliente. Hay que generar un controlador de eventos en JavaScrip: <script language=JavaScript> function validarLongitud (oSrc,txtValue) { var retValot=true; //asume que todo está bien if(txtValor.length<8) { retValor=false; } return retValor; } </script> Luego el control CustomValidator deberá establecer la propiedad OnClientSideValidate hacia el método de JavaScript. 99 <asp:CustomValidator runat="server" OnServerValidate="ValideEsto" OnClientSideValidate=validarLongitud Display="Dynamic" ControlToValidate="tbNombreUsuario" ErrorMessage="El nombre del usuario debe tener 8 o más caracteres."/> EJERCICIOS Generar dos cuadros de lista con elementos idénticos. Luego generar un control de validación que compare los valores seleccionados y muestre un mensaje de error si no son iguales. PREGUNTAS PARA ENTREGAR • ¿Cuáles son los 5 controles de validación? • Verdadero o falso: Los controles de validación validan en el cliente. • ¿Cuáles son las propiedades que todo control de validación debería tener. • ¿Qué hace el parámetro clienttarget=downlevel? • ¿Qué propiedad del control CustomValidator necesita para establecer el controlador de evento? • Si tuviera dos controles de servidor, tbNombre y tbEdad, ¿funcionaría el siguiente validador? <asp:CompareValidator runat=server ControlToValidate=tbNombre ValueToCompare=tbEdad ErrorMessage=¡Error!/> TEMA 7: INTRODUCCIÓN A LAS BASES DE DATOS COMO ACCEDER A DATOS CON ASP.NET Cinco pasos: • Configurar la conexión a la base de datos. • Abrir la conexión. • Llenar un conjunto de datos (DataSet) con los datos deseados. • Establecer una vía de datos (DataView) para mostrar los datos. • Establecer un control de servidor a una vista de datos mediante enlace de datos. <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.OleDb" %> Hay que importar los espacios de nombres de datos <script language="c#" runat="server"> public void Page_Load(Object obj, EventArgs e) { //Configurar conexión OleDbConnection objConn= New OleDbConnection ("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\ASPNET\datos\bancario.mdb") // Abrir conexión 100 OleDbDataAdapter objCmd = New OleDbDataAdapter("SELECT * FROM tblUsuarios;", objConn) // Llenar conjunto de datos DataSet ds = New DataSet() objCmd.Fill(ds, "tblUsuarios") //Seleccionar la vista de datos y vincularla con un control del servidor Enlaza los datos a un control web DataList que despliega automáticamente los datos. Este control utiliza plantillas para dar formato a los datos e itera automáticamente por los registros de la BBDD. MiListaDeDatos.DataSource = ds.Tables("tblUsuarios").DefaultView MiListaDeDatos.DataBind() } </script> <html><body> <ASP:DataList id="MiListaDeDatos" RepeatColumns="2" RepeatDirection="Vertical" runat="server"> <ItemTemplate> <div style="padding:15,15,15,15;font−size:10pt; font−family:Verdana"> <div style="font:12pt verdana;color:darkred"> <i><b> Las etiquetas <%# %> son expresiones de enlace de datos, que permite vincular explícitamente un origen de datos a un control de servidor. Lo que ocurra en el origen de datos también ocurrirá en el control. <%# DataBinder.Eval(Container.DataItem, "Nombre")%>&nbsp; <%# DataBinder.Eval(Container.DataItem, "Apellidos")%> </i></b> </div> <br> <b>Domicilio:</b> <%#DataBinder.Eval(Container.DataItem, "Domicilio")%><br> <b>Ciudad:</b> 101 <%#DataBinder.Eval(Container.DataItem,Ciudad")%><br> <b>Estado: </b> <%# DataBinder.Eval (Container.DataItem, "Estado") %><br> <b>CodPostal: </b> <%# DataBinder.Eval (Container.DataItem, "CodPostal") %><br> <b>Telefono: </b> <%# DataBinder.Eval (Container.DataItem, "Telefono") %><br> </div> </ItemTemplate> </ASP:DataList> </body></html> TEMA 8: USO DE LAS BASES DE DATOS CON ASP.NET EL OBJETO DATASET Ado.Net gira entorno a este objeto. Reemplaza al RecordSet tradicional de ADO. El DataSet es un sencillo almacén de datos residente en memoria qu ofrece un modelo de programación consistente para acceder a datos, sin importar el tipo de éstos. El DataSet contiene conjuntos completos de datos, como restricciones, relaciones e incluso varias tablas a la vez. Imagina una caja con varios compartimentos. En cada uno puedes colocar el objeto que quieras siempre y cuando quepa en la caja. Cuando estableces una conexión a la base de datos, le proporcionas a ésta una caja y le indicas que la llene con algo. Un objeto DataTable representa a una tabla de datos. El DataSet tiene una colección de estas tablas en el objeto TablesCollection. El DataTable tiene otras dos colecciones Rows y Columns. Imagina otra vez la caja. Cada compartimento es un DataTable. COMO LLENAR UN DATASET <%@ Page Language=c#%> <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.OleDb" %> <script runat="server"> public void Page_Load(Object obj, EventArgs e) 102 { //Configurar conexión OleDbConnection miConexion= New OleDbConnection ("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\ASPNET\\datos\\bancario.mdb"); // Abrir conexión OleDbDataAdapter miComando = New OleDbDataAdapter("SELECT * FROM tblUsuarios;", miConexion); // Llenar conjunto de datos DataSet ds = New DataSet(); miComando.Fill(ds, "tblUsuarios"); } </script> <html><body> </body></html> No es necesario crearse la tabla tblUsuarios. El DataSet lo hace por nosotros. ENLACE DE DATOS Se puede enlazar casi cualquier tipo de dato a cualquier control o a la propiedad de un control de una página. Esto da un control total del modo en que los datos van del almacén de datos a la página y viceversa. Puedes tan sólo mostrar datos al usuario, usarlos para establecer las propiedades de estilo de un control, o incluso permitir que el usuario modifique los datos y que actualice en almacén de datos. Dos formas de enlazar datos a una página asp.net: con la propiedad DataSource de un control o con una expresión de enlace de datos. La primera es la más usada para controles más complejos de servidor. La segunda se puede utilizar en cualquier parte. La sintaxis de una expresión de enlace de datos es la siguiente: <%# propiedad o colección %> Las expresiones para el enlace de datos sólo se evalúan con el método DataBind(). <script runat="server"> string strNombre=David; string [] miMatriz={Hola, Mundo}; string micadena=David; public void Page_Load(Object obj, EventArgs e) 103 { Page.DataBind(); } </script> <html> .. Mi nombre es <%# strNombre %> <asp:ListBox DataSource='<%# miMatriz %>' runat=server/> <asp:TextBox text='<%# miCadena %>' runat=server/> .. </html> Hay que tener cuidado de que las expresiones de datos devuelvan los tipos de datos que esperan los controles. Por ejemplo, un cuadro de texto espera un valor de cadena. Si la expresión no devuelve una obtendremos un error. <asp:TextBox text='<%# miCadena.ToString() %>' runat=server/> Si ejecutamos DataBind en la página evaluará toda expresión de enlace de datos en al página. Por lo general, esto se hace en el Page_Load: public void Page_Load(Object obj, EventArgs e) { DataBind(); } USO DEL ENLACE DE DATOS El verdadero potencial del enlace de datos proviene del uso de valores dinámicos en controles de servidor. <script language="c#" runat="server"> public void Indice_Changed(Object obj, EventArgs e) { DataBind(); } 104 </script> <html><body> <form runat="server"> <asp:Listbox runat="server" id="lbColores" width="150" AutoPostBack=true rows="1" SelectionMode="Single" OnSelectedIndexChanged="Indice_Changed" > <asp:Listitem value="1">Rojo</asp:Listitem> <asp:Listitem value=" 2">Azul</asp:Listitem> <asp:Listitem value=" 3">Verde</asp:Listitem> <asp:Listitem value=" 4">Amarillo</asp:Listitem> </asp:Listbox><p> Usamos una expresión para enlazar la propiedad SelectedItem del ListBox. Cuando cambia el índice seleccionado ejecuta de nuevo DataBind para enlazar el nuevo valor al label. <asp:Label id="lblMensaje" runat="server" Text='<%# lbColores.SelectedItem.Text %>' /> </form> </body></html> Ver tema8/aa.aspx Algunos controles de servidor también pueden enlazarse a clases de datos. Esto se hace con la propiedad DataSource a la que sólo se accede en tiempo de diseño. Tan sólo hay que establecer esta propiedad a una clase de datos (una matriz, por ejemplo) y ejecutar el DataBind. <script language="vb" runat="server"> Sub Page_Load(obj as Object, e as EventArgs) If Not Page.IsPostBack Then ' Genere una matriz de colores 105 dim arrColores() as string = _ {"rojo", "naranja", "amarillo", "verde", _ "azul", "añil", "violeta"} lbColores.DataSource = arrColores lbColores.SelectedIndex = 0 End If DataBind() End Sub </script> <html><body> <form runat="server"> <asp:Listbox runat="server" id="lbColores" width="150" AutoPostBack="true" SelectionMode="Single" > </asp:Listbox><p> <asp:Label id="lblMensaje" runat="server" Text='<%# lbColores.selectedItem.Text %>' /> </form> </body></html> <script language="c#" runat="server"> public void Page_Load(Object obj, EventArgs e) { Al usar PostBack sólo generamos la matriz la primera vez que se vea la página. if (!Page.IsPostBack) { 106 //Genere una matriz de colores string [] arrColores = {"rojo", "naranja", "amarillo", "verde","azul", "añil", "violeta"}; lbColores.DataSource = arrColores; lbColores.SelectedIndex = 0; } DataBind(); } </script> <html><body> <form runat="server"> <asp:Listbox runat="server" id="lbColores" width="150" AutoPostBack="true" SelectionMode="Single" > </asp:Listbox><p> <asp:Label id="lblMensaje" runat="server" Text='<%# lbColores.SelectedItem.Text %>' /> </form> </body></html> 107 Ver tema8/9.7.aspx Al usar PostBack sólo generamos la matriz la primera vez que se vea la página. Esta verificación también tiene otro propósito, si la omitimos recibiremos un error de se encontró el valor null donde se requería una instancia de un objeto de la etiqueta. SIN POSTBACK CON POSTBACK 108 Evento Page−Load Evento Page−Load Inicializar ListBox ¿Se envió el formulario? (DataBind) SI NO(Primera vista) Controlar Cambio (DataBind) Controlar Cambio Inicializar ListBox (DataBind) (DataBind) Interpretar página Interpretar página Interpretar página CONTROLES ENLAZADOS A DATOS Son los controles de lista: Repeater, DataList y DataGrid. Toman colecciones de datos e iteran por ellos automáticamente. Similares a los demás controles, como DropDownList y ListBox, pero con funcionalidad más compleja. Funcionan como contenedores de otros controles que realmente muestran los datos, como las etiquetas. EL CONTROL DE SERVIDOR REPEATER Es contenedor que itera por los datos. No tiene un despliegue predeterminado. Hay que establecer su disposición con controles de plantilla. Tiene una interfaz muy flexible. Si no se establece una disposición, el control no será interpretado. Las plantillas son controles que permiten usar etiquetas y texto HTML, así como otros controles para controlasr el despliegue de datos en controles Web enriquecidos. El control Repeater permite los siguientes tipos de plantillas: ItemTemplate: Es necesaria para este control. Produce una fila de resultados para cada registro de datos. Usa otros controles de servidor para mostrar los datos reales enlazándolos a los campos adecuados. AlternatingItemTemplate: Igual que ItemTemplate, pero se interpreta para mostrar cada fila alternativa de datos. Esto permite especificar diferentes configuraciones de estilo, como alternar colores de las filas. HeaderTemplate y FooterTemplate: Generan directamente HTML antes y después de las filas de datos que serán interpretadas. Un uso típico sería abrir y cerrar tablas con las etiquetas <table> y </table>. SeparatorTemplate: Estas plantillas generan elementos entre cada fila de datos, como las etiquetas HTML <br>,<p> o <HR>. Estas plantillsa sólo se usan como contenedores para el despliegue de datos. <%@ Page Language="VB" %> 109 <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.OleDb" %> <script runat="server"> Sub Page_Load(obj As Object, e As EventArgs) ' Establezca la conexión Dim miConexion As New OleDbConnection _ ("Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=C:\ASPNET\datos\bancario.mdb") ' Abra la conexión Dim miComando As New OleDbDataAdapter _ ("SELECT * FROM tblUsuarios;", miConexion) ' Llene el conjunto de datos Dim ds As DataSet = New DataSet() miComando.Fill(ds, "tblUsuarios") ' Seleccione la vista de datos y vincúlela al control del servidor Repeater1.DataSource = ds.Tables("tblUsuarios"). _ DefaultView DataBind() end sub </script> <html><body> <ASP:Repeater id="Repeater1" runat="server" > <HeaderTemplate> <table> <tr> <td bgcolor="#cccc99" width=200><b>Nombre</b></td> 110 <td bgcolor="#cccc99" width=200><b>Teléfono</b></td> </tr> </HeaderTemplate> <ItemTemplate> <tr> <td> <%# Container.DataItem("Nombre") %>&nbsp; <%# Container.DataItem("Apellidos") %> </td> <td> <%# Container.DataItem("Telefono") %> </td> </tr> </ItemTemplate> <AlternatingItemTemplate> <tr> <td bgcolor="#cccc99""> <%# Container.DataItem("Nombre") %>&nbsp; <%# Container.DataItem("Apellidos") %> </td> <td bgcolor="#cccc99"> <%# Container.DataItem("Telefono") %> </td> </tr> </AlternatingItemtemplate> <SeparatorTemplate> <tr> <td colspan="2" align="center"> −−− 111 </td> </tr> </SeparatorTemplate> <FooterTemplate> </table> </FooterTemplate> </ASP:Repeater> </body></html> ver tema8/9.8VB <%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="_9._8C.WebForm1" %> <!DOCTYPE HTML PUBLIC "−//W3C//DTD HTML 4.0 Transitional//EN" > <HTML> <body> Declaro el control Repeater <asp:Repeater id="Repeater1" runat="server"> El encabezado sólo genera una tabla HTML y despliega los encabezados de las columnas nombre y teléfono <HeaderTemplate> <table> <tr> <td bgcolor="#cccc99" width=200><b>Nombre</b></td> <td bgcolor="#cccc99" width=200><b>Teléfono</b></td> </tr> </HeaderTemplate> Enlazamos tres controles de datos a la página en esta plantilla y el Repeater itera por por resultados. <ItemTemplate> <tr> 112 <td> <%# DataBinder.Eval(Container,"DataItem.Nombre") %>&nbsp; <%# DataBinder.Eval(Container,"DataItem.Apellidos") %> </td> <td> <%# DataBinder.Eval(Container,"DataItem.Telefono")%> </td> </tr> </ItemTemplate> La plantilla alternativa muestra un color de fondo diferente para las distintas filas, por lo demás hace lo mismo que el ItemTemplate. <AlternatingItemTemplate> <tr> <td bgcolor="#cccc99""> <%# DataBinder.Eval(Container,"DataItem.Nombre") %>&nbsp; <%# DataBinder.Eval(Container,"DataItem.Apellidos") %> </td> <td bgcolor="#cccc99"> <%# DataBinder.Eval(Container,"DataItem.Telefono") %> </td> </tr> </AlternatingItemtemplate> La plantilla separadora sólo añade un separador entre filas. <SeparatorTemplate> <tr> <td colspan="2" align="center"> −−− </td> </tr> </SeparatorTemplate> 113 La plantilla de pie cierra la tabla. <FooterTemplate> </table> </FooterTemplate> </asp:Repeater> </body> </HTML> ASPX.CS private void Page_Load(object sender, System.EventArgs e) { OleDbConnection miConexion = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Documents and Settings\\mvaldericeda\\Escritorio\\asp.net\\Ejercicios\\bancario.mdb"); // Abre la conexión OleDbDataAdapter miComando =new OleDbDataAdapter("SELECT * FROM tblUsuarios;", miConexion); // Llena el conjunto de datos DataSet ds = new DataSet(); miComando.Fill(ds, "tblUsuarios"); // Selecciona la vista de datos y la vinculas al control del servidor Repeater1.DataSource = ds.Tables[0]; DataBind(); } ver tema8/9.8C El control Repeater tiene un evento:ItemCreated. ItemCreated: Se desencadena siempre antes de que se genere un elemento o plantilla. Se puede usar para establecer propiedades a través de código en tiempo de ejecución. Su sintaxis es: Public void Nombre_ItemCreated (Object obj, RepeaterItemEventArgs e) RepeaterItemEventArgs tiene la propiedad Item, que es el elemento que ha generado. 114 public void Repeater1_ItemCreated (object obj, RepeaterItemEventArgs e) { string tipo=""; switch (e.Item.ItemType) { case ListItemType.Item: tipo="Item"; break; case ListItemType.AlternatingItem: tipo="AlternatingItem"; break; case ListItemType.Header: tipo="Header"; break; case ListItemType.Footer: tipo="Footer"; break; case ListItemType.Separator: tipo="Separator"; break; } Label1.Text=Label1.Text + "Se ha generado un " + tipo + " del repetidor <br>"; } ver tema8/Rep1 El control Repeater sólo presenta datos, no permite que los usuarios modifiquen el origen de datos. Si quieres permitirlo tendrás que usar los controles DataList o DataGrid. EL CONTROL DE SERVIDOR DATALIST 115 Similar al Repeater, excepto que permite la comunicación con el usuario y la modificación de los datos. Este control se puede usar con plantillas para listar elementos como lo haría el Repeater. Pero el DataList sólo admite dos tipos de plantillas adicionales: SelectedItemTemplate: Contiene elementos adicionales que serán interpretados sólo cuando el usuario elija un elemento en el control DataList. Usos típicos:modificar las propiedades de estilo para reflejar la selección de una fila, o expandir el elemento como en un listado jerárquico (principal y secundario). EditItemTemplate: Especifica la disposición de un elemento cuando se encuetre en modo edición. Trabajar con DataList El control DataList muestra los elementos de datos en una lista de repeticiones y admite opcionalmente la selección y edición de elementos. El contenido y diseño de los elementos de la lista de DataList se define utilizando plantillas. Como mínimo, todos los controles DataList deben definir un ItemTemplate; sin embargo, algunas plantillas opcionales se pueden utilizar para personalizar el aspecto de la lista. La siguiente tabla enumera las plantillas. Nombre de la plantilla ItemTemplate AlternatingItemTemplate Plantilla del separador SelectedItemTemplate EditItemTemplate Plantilla de encabezado Plantilla de pie de página Descripción Define el contenido y diseño de los elementos de la lista. Requerido. Si se define, determina el contenido y diseño de elementos alternos. Si no se define, se utiliza ItemTemplate. Si se define, se procesa entre elementos (y elementos alternos). Si no se define, no se procesa el separador. Si se define, determina el contenido y diseño del elemento seleccionado. Si no se define, se utiliza ItemTemplate (AlternatingItemTemplate). Si se define, determina el contenido y diseño del elemento que se edita. Si no se define, se utiliza ItemTemplate (AlternatingItemTemplate, SelectedItemTemplate). Si se define, determina el contenido y diseño del encabezado de la lista. Si no se define, no se procesa el encabezado. Si se define, determina el contenido y diseño del pie de página de la lista. Si no se define, no se procesa el pie de página. Las plantillas definen los elementos y controles HTML que se deben mostrar para un elemento, así como el diseño de estos elementos. El formato de estilo: fuente, color y atributos de bordes, se establece a través de los estilos. Cada plantilla tiene su propiedad de estilo. Por ejemplo, los estilos de EditItemTemplate se establecen mediante la propiedad EditItemStyle. Un tercer conjunto de propiedades afectan al procesamiento general de DataList. De forma predeterminada, los elementos de DataList se procesan en una tabla como una columna individual vertical. Al establecer la propiedad RepeatLayout en Flow se quita la estructura de tabla HTML del procesamiento de la lista. DataList admite procesamiento direccional mediante la propiedad RepeatDirection, es decir, que puede procesar los elementos horizontal o verticalmente. Dado que el ancho de página es la dimensión que el desarrollador debe controlar en la interfaz de usuario Web, el control DataList permite que el desarrollador controle el número de columnas que se procesan (RepeatColumns), independientemente de si se procesan horizontal o verticalmente los elementos. 116 Si RepeatDirection es igual a Horizontal y RepeatColumns es cinco, los elementos se procesan en filas que contienen cinco columnas. 1 6 11 2 7 12 3 8 13 4 9 5 10 Si RepeatDirection es igual a Vertical y RepeatColumns está establecido en cinco, los elementos se procesan en cinco columnas, cada una igual en longitud al número total de elementos dividido por cinco. 1 2 3 4 5 6 7 8 9 10 11 12 13 <%@ Page Language="VB" Debug="true"%> <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.OleDb" %> <script runat="server"> Sub Page_Load(obj As Object, e As EventArgs) ' Establezca la conexión Dim miConexion As New OleDbConnection _ ("Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=C:\Inetpub\wwwroot\bancario.mdb") ' Abra la conexión Dim miComando As New OleDbDataAdapter _ ("SELECT * FROM tblUsuarios;", miConexion) ' Llene el conjunto de datos Dim ds As DataSet = New DataSet() miComando.Fill(ds, "tblUsuarios") ' Seleccione la vista de datos y vincúlela al control del servidor DataList1.DataSource = ds.Tables("tblUsuarios"). _ DefaultView DataBind() 117 end sub sub DataList1_ItemCommand(obj As object, e As _ DataListCommandEventArgs) DataList1.SelectedIndex = e.Item.ItemIndex DataList1.DataBind() end sub </script> <html><body><Form runat="server"> <asp:DataList id="DataList1" runat="server" SelectedItemStyle−BackColor="#cccc99" repeatlayout="table" repeatdirection="horizontal" DataKeyField="IDUsuario" OnItemCommand="DataList1_ItemCommand"> <ItemTemplate> <asp:LinkButton id="button1" runat="server" Text='<%# Container.DataItem("Nombre") & " " & _ Container.DataItem("Apellidos") %>' CommandName="Select" /> <p> </ItemTemplate> <SelectedItemTemplate> <%# Container.DataItem("Nombre") & " " & _ Container.DataItem("Apellidos") %><br> Teléfono: <%# Container.DataItem("Telefono") %> 118 <br> Domicilio: <%# Container.DataItem("Domicilio") %> <br> <%# Container.DataItem("Ciudad") %>, <%# Container.DataItem("Estado") %> &nbsp;<%# Container.DataItem("codpostal") %> <br> </SelectedItemTemplate> </asp:DataList> </form> </body></html> Ver tema8/dataListVB.aspx <%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="DataList1.WebForm1" %> <!DOCTYPE HTML PUBLIC "−//W3C//DTD HTML 4.0 Transitional//EN" > <HTML> <HEAD> <title>WebForm1</title> <meta name="GENERATOR" Content="Microsoft Visual Studio 7.0"> <meta name="CODE_LANGUAGE" Content="C#"> <meta name="vs_defaultClientScript" content="JavaScript"> <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5"> </HEAD> <body MS_POSITIONING="GridLayout"> <form id="Form1" method="post" runat="server"> Declaro un control DataList 119 SelectedItemStyle−BackColor define el color de fondo de SelectedItemTemplate cuando está visible. DataKeyField es el nombre del campo que se usará como clave principal de los datos. <asp:DataList id="DataList1" runat="server" SelectedItemStyle−BackColor="#cccc99" repeatlayout="table" repeatdirection="horizontal" DataKeyField="IDUsuario" OnItemCommand="DataList1_ItemCommand"> <ItemTemplate> Genero un control LinkButton que está enlazado a las columnas Nombre y Apellidos. Cuando se haga clic en el vínculo, generará y pasará el comando Select al DataList. <asp:LinkButton id="button1" runat="server" CommandName="Select" > <%# DataBinder.Eval(Container,"DataItem.Nombre")%> <%#DataBinder.Eval(Container,"DataItem.Apellidos") %> </asp:LinkButton> <p> </ItemTemplate> Esta plantilla muestra información enlazada a los datos. <SelectedItemTemplate> <%# DataBinder.Eval(Container,"DataItem.Nombre")%> <%# DataBinder.Eval(Container,"DataItem.Apellidos")%><br> Teléfono: <%# DataBinder.Eval(Container,"DataItem.Telefono") %> <br> Domicilio: <%# DataBinder.Eval(Container,"DataItem.Domicilio") %> <br> 120 <%# DataBinder.Eval(Container,"DataItem.Ciudad") %>, <%# DataBinder.Eval(Container,"DataItem.Provincia") %> &nbsp;<%# DataBinder.Eval(Container,"DataItem.codpostal") %> <br> </SelectedItemTemplate> </asp:DataList> </form> </body> </HTML> .ASPX.CS private void Page_Load(object sender, System.EventArgs e) { OleDbConnection miConexion = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Inetpub\\wwwroot\\bancario.mdb"); // Abre la conexión OleDbDataAdapter miComando =new OleDbDataAdapter("SELECT * FROM tblUsuarios;", miConexion); // Llena el conjunto de datos DataSet ds = new DataSet(); miComando.Fill(ds, "tblUsuarios"); // Selecciona la vista de datos y vincúlela al control del servidor DataList1.DataSource = ds.Tables[0]; DataBind(); } public void DataList1_ItemCommand(object obj,DataListCommandEventArgs e) { DataList1.SelectedIndex = e.Item.ItemIndex; DataList1.DataBind(); 121 } Ver tema8/DataList1 Ejercicio: Tenemos un DataList, tres DropDown y un CheckBox. El DataList debe cambiar el aspecto según seleccionemos. Dirección: Horizontal o Vertical. Layout: Tabla o Flor. Columnas de 1 a 5. 122 123 124 Solución tema8/ejercicio1 MODIFICACIÓN DE ELEMENTOS El control DataList admite la edición directa de los datos de un elemento mediante la propiedad EditItemTemplate . EditItemTemplate define el contenido y el aspecto del elemento cuando se está editando. Por ejemplo, la siguiente plantilla incluye un cuadro de texto, un botón "Actualizar" y un botón "Cancelar". <EditItemTemplate> Item: <asp:TextBox id="Text1" runat="server" Text='<%# ((DataRowView)Container.DataItem)["Item"] %>' /> <br> <asp:LinkButton id="button1" runat="server" Text="Update" CommandName="update" /> <asp:LinkButton id="button2" runat="server"Text="Cancel" 125 CommandName="cancel"/> </EditItemTemplate> EditItemTemplate interactúa con otra propiedad: EditItemIndex. De forma predeterminada, el valor de EditItemIndex es igual a −1, es decir, no se está editando ninguno de los elementos de la lista. Cuando EditItemIndex se establece en un elemento determinado, ese elemento se muestra utilizando EditItemTemplate. DataList también proporciona tres eventos que se pueden utilizar por compatibilidad con la edición. Se inicia EditCommand cuando se hace clic en el control del botón de comando "Editar" en ItemTemplatede la lista. El control de este evento en el código depende del usuario. La lógica típica establece EditItemIndex en el elemento seleccionado y, a continuación, vuelve a enlazar los datos de DataList como se muestra en el siguiente ejemplo: protected void DataList_EditCommand(object Source,DataListCommandEventArgs e) { DataList1.EditItemIndex = (int)e.Item.ItemIndex; BindList(); } EditItemTemplate contiene normalmente botones de comando "Actualizar" y "Cancelar". Estos botones provocan que se inicien los eventos UpdateCommand y CancelCommand, respectivamente. Controlar estos eventos en el código depende del usuario. La lógica típica de "Cancelar" establece EditItemIndex en −1 y, a continuación, vuelve a enlazar los datos de DataList como muestra el siguiente ejemplo: protected void DataList_CancelCommand(object Source, DataListCommandEventArgs e) { DataList1.EditItemIndex = −1; BindList(); } Protected Sub DataList_CancelCommand(Source As Object, e As DataListCommandEventArgs) DataList1.EditItemIndex = −1 BindList() End Sub protected function DataList_CancelCommand(Source:Object, e:DataListCommandEventArgs) : void { DataList1.EditItemIndex = −1; BindList(); 126 } <%@ Page Language="VB" %> <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.OleDb" %> <script runat="server"> Sub Page_Load(obj As Object, e As EventArgs) ' Establezca la conexión Dim miConexion As New OleDbConnection _ ("Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=C:\ASPNET\datos\bancario.mdb") ' Abra la conexión Dim miComando As New OleDbDataAdapter _ ("SELECT * FROM tblUsuarios;", miConexion) ' Llene el conjunto de datos Dim ds As DataSet = New DataSet() miComando.Fill(ds, "tblUsuarios") ' Seleccione la vista de datos y vincúlela al control del servidor DataList1.DataSource = ds.Tables("tblUsuarios"). _ DefaultView DataBind() end sub Sub DataList1_ItemCommand(obj As object, e As _ DataListCommandEventArgs) DataList1.SelectedIndex = e.Item.ItemIndex DataList1.DataBind() End Sub 127 sub DataList1_EditCommand(obj As object, e As _ DataListCommandEventArgs) DataList1.EditItemIndex = e.Item.ItemIndex DataList1.DataBind() end sub Sub DataList1_CancelCommand(obj As object, e As _ DataListCommandEventArgs) DataList1.EditItemIndex = −1 DataList1.DataBind() End Sub Sub DataList1_UpdateCommand(obj As object, e As _ DataListCommandEventArgs) ' Actualizar el almacén de datos DataList1.DataBind() End Sub Sub DataList1_DeleteCommand(obj As object, e As _ DataListCommandEventArgs) ' Suprimir del almacén de datos DataList1.DataBind() End Sub </script> <html><body><Form runat="server"> <asp:DataList id="DataList1" runat="server" SelectedItemStyle−BackColor="#cccc99" repeatlayout="table" repeatdirection="horizontal" 128 OnItemCommand="DataList1_ItemCommand" OnEditCommand="DataList1_EditCommand" OnCancelCommand="DataList1_CancelCommand" OnUpdateCommand="DataList1_UpdateCommand" OnDeleteCommand="DataList1_DeleteCommand" DataKeyField="IDUsuario"> <ItemTemplate> <asp:LinkButton id="button1" runat="server" Text='<%# Container.DataItem("Nombre") & _ " " & Container.DataItem("Apellidos") %>' CommandName="Edit" /> <p> </ItemTemplate> <EditItemTemplate> <asp:LinkButton id="lbtCancel" runat="server" CommandName="Cancel" Text="Cancelar" /> <asp:LinkButton id="lbtUpdate" runat="server" CommandName="Update" Text="Actualizar" /> <asp:LinkButton id="lbtDelete" runat="server" CommandName="Delete" Text="Suprimir" /> </EditItemTemplate> </asp:DataList> </form> 129 </body></html> Ver tema8/DataListVB2 <%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="DataList1.WebForm1" %> <!DOCTYPE HTML PUBLIC "−//W3C//DTD HTML 4.0 Transitional//EN" > <HTML> <HEAD> <title>WebForm1</title> <meta name="GENERATOR" Content="Microsoft Visual Studio 7.0"> <meta name="CODE_LANGUAGE" Content="C#"> <meta name="vs_defaultClientScript" content="JavaScript"> <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5"> </HEAD> <body MS_POSITIONING="GridLayout"> <form id="Form1" method="post" runat="server"> <asp:DataList id="DataList1" runat="server" SelectedItemStyle−BackColor="#cccc99" repeatlayout="table" repeatdirection="horizontal" DataKeyField="IDUsuario" OnItemCommand="DataList1_ItemCommand"> <ItemTemplate> <asp:LinkButton id="button1" runat="server" CommandName="Edit" > <%# DataBinder.Eval(Container,"DataItem.Nombre")%> <%#DataBinder.Eval(Container,"DataItem.Apellidos") %> </asp:LinkButton> <p> 130 </ItemTemplate> <SelectedItemTemplate> <%# DataBinder.Eval(Container,"DataItem.Nombre")%> <%# DataBinder.Eval(Container,"DataItem.Apellidos")%><br> Teléfono: <%# DataBinder.Eval(Container,"DataItem.Telefono") %> <br> Domicilio: <%# DataBinder.Eval(Container,"DataItem.Domicilio") %> <br> <%# DataBinder.Eval(Container,"DataItem.Ciudad") %>, <%# DataBinder.Eval(Container,"DataItem.Provincia") %>&nbsp; <%# DataBinder.Eval(Container,"DataItem.codpostal") %> <br> </SelectedItemTemplate> <EditItemTemplate> <asp:LinkButton id="lbtCancel" runat="server" CommandName="Cancel" Text="Cancelar" /> <asp:LinkButton id="lbtUpdate" runat="server" CommandName="Update" Text="Actualizar" /> <asp:LinkButton id="lbtDelete" runat="server" CommandName="Delete" Text="Suprimir" /> </EditItemTemplate> 131 </asp:DataList> </form> </body> </HTML> Este listado aún no funcionará. Primero hay que definir los métodos para controlar sus eventos. Cuando los usuarios hagan clic en cada elemento, parecerá un menú de opciones, gracias al EditItemTemplate. También se ha modificado el comando Select del LinkButton a Edit. Este es un comando que desencadena automáticamente el evento EditCommand del DataList. Tendremos que declarar un controlador de evento. public void DataList1_EditCommand(object obj,DataListCommandEventArgs e) { DataList1.EditItemIndex=e.Item.ItemIndex; DataList1.DataBind(); } Establecemos la propiedad EditItemIndex al elemento seleccionado, y cambia a modo de edición para ese elemento para que el usuario modifique los campos, lo que a la vez acrualizará el almacén de datos. public void DataList1_CancelCommand(object obj,DataListCommandEventArgs e) { DataList1.EditItemIndex=−1; DataList1.DataBind(); } public void DataList1_UpdateCommand(object obj,DataListCommandEventArgs e) { DataList1.DataBind(); } public void DataList1_DeleteCommand(object obj,DataListCommandEventArgs e) { DataList1.DataBind(); } 132 Ver tema8/DataList2 EL CONTROL DE SERVIDOR DATAGRID Similar a los controles DataList y Repeater, excepto porque ofrece más funcionalidad. Utiliza columnas para mostrar los datos en un diseño de cuadrícula. De forma predeterminada genera una columna para cada campo del almacén de datos. Se puede especificar manualmente qué campos desplegar y cómo desplegarlos. Tipos de columnas: Columnas Enlazadas: Permiten especificar cuáles columnas mostrar y en qué orden, y dar formato a los atributos de estilo. Son las que usa de forma predeterminada. Columnas de Botón: Muestran botones para todos los elementos de la cuadrícula, par los cuales definirá una funcionalidad propia. Columnas del comando Edit: Permite modificar elementos. Columnas de hipervínculo: Muestra los datos como hipervínculos. Columnas por plantillas: Se pueden usar plantillas, como con los controles Repeater y DataList, para definir formatos propios para las columnas. El control DataGrid elige automáticamente un tipo de columna de acuerdo con los datos que se mostrarán. Ejemplo de DataGrid <%@ Page Language="VB" Debug="true"%> <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.OleDb" %> <script runat="server"> Sub Page_Load(obj As Object, e As EventArgs) try ' Establezca la conexión Dim miConexion As New OleDbConnection _ ("Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=C:\Inetpub\wwwroot\bancario.mdb") ' Abra la conexión Dim miComando As New OleDbDataAdapter _ ("SELECT * FROM tblUsuarios;", miConexion) 133 ' Llene el conjunto de datos Dim ds As DataSet = New DataSet() miComando.Fill(ds, "tblUsuarios") ' Seleccione la vista de datos y vincúlela al control del servidor DataGrid1.DataSource = ds.Tables("tblUsuarios").DefaultView DataBind() catch ex as Exception Response.Write (ex.Message) end try end sub </script> <html><body><Form runat="server"> <asp:DataGrid id="DataGrid1" runat="server" BorderColor="black" GridLines="Vertical" cellpadding="4" cellspacing="0" width="450" Font−Names="Arial" Font−Size="8pt" ShowFooter="True" HeaderStyle−BackColor="#cccc99" FooterStyle−BackColor="#cccc99" ItemStyle−BackColor="#ffffff" AlternatingItemStyle−Backcolor="#cccccc" AutoGenerateColumns="True"> 134 <Columns> <asp:TemplateColumn HeaderText="Nombre"> <ItemTemplate> <asp:Label id="Nombre" runat="server" Text='<%# Container.DataItem("Nombre")& _ " " & Container.DataItem("Apellidos") %>'/> </ItemTemplate> </asp:TemplateColumn> <asp:BoundColumn HeaderText="Domicilio" DataField="Domicilio"/> <asp:BoundColumn HeaderText="Ciudad" DataField="Ciudad"/> <asp:BoundColumn HeaderText="Provincia" DataField="Provincia" /> <asp:BoundColumn HeaderText="Código postal" DataField="codPostal" /> <asp:HyperlinkColumn HeaderText="Modificar" text="Modificar" NavigateURL="edit.aspx"/> <asp:ButtonColumn HeaderText="¿Suprimir?" text="X" CommandName="delete" ButtonType="PushButton"/> </Columns> </asp:DataGrid> </form> </body></html> Ver tema8/dg1VB.aspx <%@ Page Language="C#" Debug="true"%> <%@ Import Namespace="System.Data" %> 135 <%@ Import Namespace="System.Data.OleDb" %> <script runat="server"> private void Page_Load(object sender, System.EventArgs e) { try { // Establezco la conexión OleDbConnection miConexion= new OleDbConnection ("Provider= Microsoft.Jet.OLEDB.4.0;" + "Data Source=C:\\Inetpub\\wwwroot\\bancario.mdb"); // Abro la conexión OleDbDataAdapter miComando = new OleDbDataAdapter("SELECT * FROM tblUsuarios;", miConexion); // Lleno el conjunto de datos DataSet ds= new DataSet(); miComando.Fill(ds, "tblUsuarios"); // Selecciono la vista de datos y la vinculo al control del servidor DataGrid1.DataSource = ds.Tables["tblUsuarios"].DefaultView; DataGrid1.DataBind(); } catch (Exception ex) { Response.Write (ex.Message); } } </script> <html> <body> 136 <Form runat="server"> Establezco las propiedades del DataGrid <asp:DataGrid id="DataGrid1" runat="server" BorderColor="black" GridLines="Vertical" cellpadding="4" cellspacing="0" width="450" Font−Names="Arial" Font−Size="8pt" ShowFooter="True" HeaderStyle−BackColor="#cccc99" FooterStyle−BackColor="#cccc99" ItemStyle−BackColor="#ffffff" AlternatingItemStyle−Backcolor="#cccccc" En esta línea le indico al DataGrid que quiero configurar mis propias columnas AutoGenerateColumns="True"> Para definir las columnas personalizadas tendré que agregarlas a la colección Columns del DataGrid. TemplateColumn, HyperlinkColumn, BoundColumn y ButtonColumn son controles utilizados específicamente para el control DataGrid. <Columns> <asp:TemplateColumn HeaderText="Nombre"> <ItemTemplate> <asp:Label id="Nombre" runat="server" Text='<%# DataBinder.Eval(Container.DataItem,"Nombre") + " " + DataBinder.Eval(Container.DataItem,"Apellidos") %>'/> </ItemTemplate> 137 </asp:TemplateColumn> BoundColumn utiliza la propiedad DataField para para enlazarse al almacén de datos. <asp:BoundColumn HeaderText="Domicilio" DataField="Domicilio"/> <asp:BoundColumn HeaderText="Ciudad" DataField="Ciudad"/> <asp:BoundColumn HeaderText="Provincia" DataField="Provincia" /> <asp:BoundColumn HeaderText="Código postal" DataField="codPostal" /> <asp:HyperlinkColumn HeaderText="Modificar" text="Modificar" NavigateURL="edit.aspx"/> ButtonColumn muestra de forma predeterminada un control LinkButton, pero puede usar la propiedad ButtonType para establecer un tipo distinto. <asp:ButtonColumn HeaderText="¿Suprimir?" text="X" CommandName="delete" ButtonType="PushButton"/> </Columns> </asp:DataGrid> </form> </body></html> Ver tema8/dg1C.aspx DataBinder.Eval El marco de trabajo ASP.NET proporciona un método estático que evalúa expresiones de enlace de datos enlazadas en tiempo de ejecución y, de forma opcional, aplica un formato de cadena al resultado. DataBinder.Eval resulta práctico en cuanto a que elimina gran parte de la conversión de tipos explícita que debe realizar el programador para convertir valores en el tipo de datos deseado. Resulta especialmente útil al enlazar datos con controles en una lista con plantillas, ya que con frecuencia la fila de datos y el campo de datos deben estar convertidos. Considérese el siguiente ejemplo, en el que un entero se visualiza como una cadena de moneda. Con la sintaxis de enlace de datos estándar de ASP.NET, se debe realizar primero la conversión del tipo de la fila de datos para recuperar el campo de datos, IntegerValue. A continuación, se pasa como argumento al método String.Format. 138 <%# String.Format("{0:c}", ((DataRowView)Container.DataItem)["IntegerValue"]) %> Esta sintaxis puede resultar compleja y difícil de recordar. En contraste, DataBinder.Eval es simplemente un método con tres argumentos: el contenedor que da nombre al elemento de datos, el nombre del campo de datos y una cadena de formato. En una lista con plantillas, como DataList, DataGrid o Repeater, el contenedor que da nombre es siempre Container.DataItem. Page es otro contenedor de nombres que se puede utilizar con DataBinder.Eval. <%# DataBinder.Eval(Container.DataItem, "IntegerValue", "{0:c}") %> MODIFICACIÓN DE ELEMENTOS Simplemente hay que generar un EditCommandColumn. <asp:DataGrid id="DataGrid1" runat="server" BorderColor="black" GridLines="Vertical" cellpadding="4" cellspacing="0" width="450" Font−Names="Arial" Font−Size="8pt" ShowFooter="True" HeaderStyle−BackColor="#cccc99" FooterStyle−BackColor="#cccc99" ItemStyle−BackColor="#ffffff" AlternatingItemStyle−Backcolor="#cccccc" AllowSorting="False" AutoGenerateColumns="False" AllowPaging="True" PageSize=2 PagerStyle−Mode=NumericPages PagerStyle−PageButtonCount=2 139 OnPageIndexChanged="DataGrid1_PageIndexChanged" OnEditCommand="DataGrid1_Edit" OnCancelCommand="DataGrid1_Cancel" OnUpdateCommand="DataGrid1_Update"> <Columns> <asp:TemplateColumn HeaderText="Nombre"> <ItemTemplate> <asp:Label id="Nombre" runat="server" Text='<%# Container.DataItem("Nombre")& _ " " & Container.DataItem("Apellidos") %>'/> </ItemTemplate> </asp:TemplateColumn> <asp:BoundColumn HeaderText="Domicilio" DataField="Domicilio"/> <asp:BoundColumn HeaderText="Ciudad" DataField="Ciudad"/> <asp:BoundColumn HeaderText="Estado" DataField="Estado" /> <asp:BoundColumn HeaderText="Código postal" DataField="codPostal" /> <asp:EditCommandColumn EditText="Modificar" CancelText="Cancelar" UpdateText="Actualizar" ItemStyle−Wrap="false" Muestra un LinkButton con el texto Modificar. Cuando el usuario haga clic, el elemento seleccionado entrará a modo edición y cada columna cambiará a cuadro de texto. También muestra los vínculos Actualizar y Cancelar. Hay que definir métodos para controlar estos eventos. HeaderText="Modificar" /> 140 </Columns> </asp:DataGrid> Puesto que se ha generado un EditCommandColumn se puede suprimir el HyperLinkColumn: <asp:HyperlinkColumn HeaderText="Modificar" text="Modificar" NavigateURL="edit.aspx"/> Y también el ButtonColumn: <asp:ButtonColumn HeaderText="¿Suprimir?" text="X" CommandName="delete" ButtonType="PushButton"/> Porque EditCommandColumn agregará uno automáticamente. Sólo BoundColumns cambiará a campos modificables. El resto, como TemplateColumns, mantendrá su interfaz original. Hay que asegurarse de que las columnas que va a modificar el usuario sean BoundColumns. Métodos para controlar Actualizar y Cancelar: public void DataGrid1_Editar(object obj, DataGridCommandEventArgs e) { DataGrid1.EditItemIndex = (int)e.Item.ItemIndex; DataGrid1.DataBind(); } public void DataGrid1_Update(object obj, DataGridCommandEventArgs e) { //Realizar actualizaciones DataGrid1.DataBind(); } public void DataGrid1_Cancel(object obj, DataGridCommandEventArgs e) { DataGrid1.EditItemIndex = −1; DataGrid1.DataBind(); 141 } Ver tema8/dataG.aspx ORDENAMIENTO Cuando activas el ordenamiento, de forma predeterminada el DataGrid convierte todos los encabezados en un LinkButton en el que los usuarios pueden hacer clic para ordenar en base a esa columna. Hay que generar un mecanismo de ordenamiento, pero asp.net da los fundamentos. También se puede especificar un ordenamiento personalizado, en el que se defina las columnas por las que el usuario puede ordenar. Cuando la propiedad AllowSorting de DataGrid se establece en true, procesa hipervínculos para los encabezados de columna que desencadenan un comando Sort de nuevo en la cuadrícula. La propiedad OnSortCommand de DataGrid se establece en el controlador al que se desea llamar cuando el usuario hace clic en un vínculo de columna. El nombre de la columna se pasa como una propiedad SortExpression en el argumento DataGridSortCommandEventArgs, que se puede utilizar para establecer la propiedad Sort del enlace DataView en la cuadrícula. Ejemplo: <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.OleDb" %> <%@ Page Language="C#" Debug="true" %> <html> <script runat="server"> OleDbConnection myConnection; protected void Page_Load(Object sender, EventArgs e) { myConnection = new OleDbConnection("Provider= Microsoft.Jet.OLEDB.4.0;" + "Data Source=C:\\Inetpub\\wwwroot\\bancario.mdb"); if (!IsPostBack) BindGrid("IDUsuario"); // La primera vez aparece ordenado por IDUsuario } protected void MyDataGrid_Sort(Object sender, DataGridSortCommandEventArgs e) { BindGrid(e.SortExpression); 142 //Llama al método BindGrid y le dice por que columna ordenamos } public void BindGrid(String sortfield) //recibe la columna por la que ordenar { OleDbDataAdapter myCommand = new OleDbDataAdapter("SELECT * FROM tblUsuarios;", myConnection); DataSet ds = new DataSet(); myCommand.Fill(ds, "tblUsuarios"); DataView Source = ds.Tables["tblUsuarios"].DefaultView; //genera una vista de datos Source.Sort = sortfield; //establece la propiedad Sort a sortfield (ordena por campo) MyDataGrid.DataSource=Source; MyDataGrid.DataBind(); } </script> <body> <h3><font face="Verdana">Ordenar datos en un control DataGrid</font></h3> <form runat="server"> <ASP:DataGrid id="MyDataGrid" runat="server" OnSortCommand="MyDataGrid_Sort" Width="700" BackColor="#ccccff" BorderColor="black" ShowFooter="false" CellPadding=3 CellSpacing="0" Font−Name="Verdana" 143 Font−Size="8pt" HeaderStyle−BackColor="#aaaadd" AllowSorting="true" /> </form> </body> </html> Ver tema8/OrdenDataGrid.aspx PAGINACIÓN El DataGrid puede dividir los datos en varias páginas si hay demasiados registros para mostrarlos en una sola. Asp.net dividirá los datos en las páginas que le indiquemos y creará botones para pasar de una a otra. Usaremos la propiedad CurrentPageIndex del DataGrid para determinar cuál página deberá mostrarse. Cuando el usuario haga clic en un botón para ir a la siguiente página, todos los datos serán generados y el proceso se repetirá. Para activar la paginación hay que establecer AllowPaging=True (esto es verdadero de forma predeterminada), y la propiedad PageSize en la cantidad de registros que queremos mostrar a la vez. El estilo de los botones de paginación se obtiene mediante la propiedad PagerStyle. Los dos estilos integrados son los botones Siguiente y Anterior, y los números de página. <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.OleDb" %> <%@ Page Language="C#" Debug="true" %> <html> <script runat="server"> OleDbConnection myConnection; protected void Page_Load(Object sender, EventArgs e) { myConnection = new OleDbConnection("Provider= Microsoft.Jet.OLEDB.4.0;" + "Data Source=C:\\Inetpub\\wwwroot\\bancario.mdb"); if (!IsPostBack) BindGrid("IDUsuario"); 144 } protected void MyDataGrid_Sort(Object sender, DataGridSortCommandEventArgs e) { BindGrid(e.SortExpression); } public void BindGrid(String sortfield) { OleDbDataAdapter myCommand = new OleDbDataAdapter("SELECT * FROM tblUsuarios;", myConnection); DataSet ds = new DataSet(); myCommand.Fill(ds, "tblUsuarios"); DataView Source = ds.Tables["tblUsuarios"].DefaultView; Source.Sort = sortfield; MyDataGrid.DataSource=Source; MyDataGrid.DataBind(); } public void MyDataGrid_PageIndexChanged(Object obj,DataGridPageChangedEventArgs e) { MyDataGrid.CurrentPageIndex = e.NewPageIndex; //MyDataGrid.DataBind(); BindGrid("IDUsuario"); } </script> <body> <h3><font face="Verdana">Ordenar datos en un control DataGrid</font></h3> <form runat="server"> <ASP:DataGrid id="MyDataGrid" runat="server" OnSortCommand="MyDataGrid_Sort" 145 Width="700" BackColor="#ccccff" BorderColor="black" ShowFooter="false" CellPadding=3 CellSpacing="0" Font−Name="Verdana" Font−Size="8pt" HeaderStyle−BackColor="#aaaadd" AllowSorting="true" AllowPaging="true" PageSize=3 PagerStyle−Mode=NumericPages //NextPrev PagerStyle−PageButtonCount = 2 OnPageIndexChanged="MyDataGrid_PageIndexChanged"/> </form> </body> </html> Ver tema8/OrdenDataGrid1.aspx PREGUNTAS PARA ENTREGAR EN PAPEL • ¿Qué espacios de nombres deberás importar para usar los mecanismos de datos en las páginas asp.net? • Verdadero o falso: El DataSet puede contener varias tablass. • ¿Cuáles son las tres colecciones del DataSet y qué hacen? • ¿Cuál es la sintaxis para expresiones enlazadas a datos? • ¿El control DataList admite paginación? • ¿Cuáles son las dos propiedades de un DataGrid que debes especificar para activar la ordenación y la paginación, respectivamente? TEMA 9: COMUNICACIÓN CON ADO.NET ADO.NET Y XML 146 XML es una herramienta muy útil para la distribución de datos. Está totalmente basado en texto, lo que significa que las personas lo pueden escribir y leer fácilmente y puede transportarse según las medidas de seguridad establecidas en internet. XML almacena los datos proporcionando una representación jerárquica de campos y sus datos. ADO.Net utliza XML en todos los intercambios de datos y para la representación interna de los datos. Tan pronto como salen los datos de una base de datos, se representan en XML y se envían a donde los necesite. EL MODELO DE OBJETOS ADO.NET ADO.Net consta de dos partes clave: el DataSet y los proveedores administrados. Los proveedores administrados fungen como una capa de comunicación entre un DataSet y un almacén de datos. Proporcionan los mecanismos de conexión, acceso, manejo y recuperación de información de cualquier almacén de datos compatible con OLEDB. OLE DB y SQL. UNA REVISIÓN DEL DATASET El DataSet está desconectado. Cada usuario recibe su propia copia de los datos para hacer con ellos lo que quiera. Las modificaciones hechas al DataSet NO se reflejan en el origen de datos. Cualquier modificación deberá ser enviada explícitamente al origen de datos. MODIFICACIÓN DE DATOS EN UN DATAROW El DataSet almacena los datos de forma similar a una base de datos, contiene tablass, columnas y filas. Se manipularán los datos con instrucciones sql que modifican más de un registro a la vez, pero habrá ocasiones en que tendremos que tener un control más directo de cada fila. El objeto DataRow representa una fila de datos del DataTable. Se puede modificar directamente el contenido de cada DataRow. La propiedad RowState indica la condición de la fila: Detached, Unchanged, New, Deleted y Modified. El primero significa que la fila se ha generado, pero que no es parte de ningún RowsCollection en un DataSet. Los últimos cuatro indican que la fila no ha sido modificada, que es nueva, que se ha eliminado y que se ha modificado, respectivamente. Como parte del RowState, un DataTable conserva tres versiones de cada fila: original, actual y propuesta. El DataTable utiliza estas versiones para determinar el RowState. La versión original es la fila cuando se agregó al DataTable. La versión actual es la fila modificada. La versión propuesta existe bajo una condición especial: cuando se ejecuta el método BeginEdit en la fila. El método BeginEdit se utiliza para realizar varias modificaciones a las filas sin tener que aplicar reglas de validación. Por ejemplo, si tiene un grupo de filas que deberán sumar el total de algún valor, se pueden poner en modo de edición y manejar los valores sin tenter que preocuparse por lo que tendrán que sumar. La fila se quita del modo de edición y se aplican las reglas de validación cuando se ejecuta el método EndEdit o AcceptChanges. El valor original (del origen de datos) se va al DataSet cuando se ejecuta el método Fill. Si haces cualquier modificación al valor, se convierte en el actual. Entonces se puede regresar al valor original, actualizar el almacén de datos con el valor actual, o ir al modo edición. En este modo se pueden aceptar las modificaciones y actualizar el almacén de datos, o cancelar las modificaciones y regresar al valor original o a las versiones 147 actuales. Pueden ocurrir errores, cada error se almacena en la propiedad RowError del DataRow como una cadena. Se pueden obtener todos los errores ejecutando el método GetErrors, que devuelve una matriz de DataRows. Si hay algún error, no se realizarán las actualizaciones al origen de datos. El DataRow tiene dos métodos: Delete y Remove. Delete destruye totalmente la fila y sus datos y ya no se puede acceder a ellos. Remove suprime la fila del DataTable para que los datos no puedan ser accedidos por el programa. El origen de datos real no se modifica. RejectChanges deshace las modificaciones realizadas desde que se cargó la fila o desde la última vez que ejecutó AcceptChanges. Ejemplo: myConnection = new OleDbConnection("Provider= Microsoft.Jet.OLEDB.4.0;" + "Data Source=C:\\Inetpub\\wwwroot\\bancario.mdb"); OleDbDataAdapter myCommand = new OleDbDataAdapter("SELECT * FROM tblUsuarios;", myConnection); DataSet ds = new DataSet(); myCommand.Fill(ds, "tblUsuarios"); ds.Tables[tblUsuarios2].Rows[0][Nombre]=David; //hacemos otras cosas ds.Tables[tblUsuarios2].Rows[0].RejectChanges; TEMA 10: USO DE XML EN ASP.NET INTRODUCCIÓN A XML XML (Lenguaje de Marcado Extensible) es un formato basado en texto para describir datos. Incluye nuevas formas de distribuir datos a aplicaciones propias de Web, lo que permite que casi cualquier tipo de dato se envíe a cualquier lugar. ?xml version="1.0" encoding="ISO−8859−1" ?> <libreria> <libro genero="novela" estilo="cubierta dura"> <titulo>El cuento de la sirvienta</titulo> <precio>19.95</precio> <autor> <nombre>Margaret</nombre> 148 <apellidos>Atwood</apellidos> </autor> </libro> <libro genero="novela" estilo="rústico"> <titulo>La biblia del bosque de los venenos</titulo> <precio>11.99</precio> <autor> <nombre>Bárbara</nombre> <apellidos>Kingsolver</apellidos> </autor> </libro> <libro genero="novela" estilo="tapas duras"> <titulo>Aníbal</titulo> <precio>27.95</precio> <autor> <nombre>Richard</nombre> <apellidos>Harris</apellidos> </autor> </libro> <libro genero="novela" estilo="tapas duras"> <titulo>El péndulo de Focault</titulo> <precio>22.95</precio> <autor> <nombre>Umberto</nombre> <apellidos>Eco</apellidos> </autor> 149 </libro> </libreria> Esquema: <Schema xmlns="urn:schemas−microsoft−com:xml−data" xmlns:dt="urn:schemas−microsoft−com:datatypes"> <ElementType name="nombre" content="textOnly"/> <ElementType name="apellido" content="textOnly"/> <ElementType name="nombrecompleto" content="textOnly"/> <ElementType name="precio" content="textOnly" dt:type="fixed.14.4"/> <ElementType name="autor" content="eltOnly" order="one"> <group order="seq"> <element type="nombrecompleto"/> </group> <group order="seq"> <element type="nombre"/> <element type="apellido"/> </group> </ElementType> <ElementType name="titulo" content="textOnly"/> <AttributeType name="genero" dt:type="string"/> <AttributeType name="estilo" dt:type="enumeration" dt:values="rustico cubiertadura"/> <ElementType name="libro" content="eltOnly"> <attribute type="genero" required="yes"/> 150 <attribute type="estilo" required="yes"/> <element type="titulo"/> <element type="autor"/> <element type="precio"/> </ElementType> <ElementType name="libreria" content="eltOnly"> <element type="libro"/> </ElementType> </Schema> ACCESO A XML MEDIANTE ASP.NET El acceso a XML es muy similar al acceso a una base de datos mediante ADO.NET. Dos de los objetos más sencillos XMLTextReader y XMLTextWriter en el espacio de nombres System.XML. COMO LEER XML El XMLTextReader es similar a un OleDBDataReader en el sentido que provee un acceso sólo hacia delante. Para abrir un archivo XML, simplemente hay que generar un XMLTextReader y pasarle el nombre del archivo XML. Si generamos un archivo LectorXML.aspx y lo colocamos en la misma carpeta que el archivo XML: Dim lector as New XMLTextReader (nombreDelArchivoYSuRutaDeAcceso) XMLTextReader lector = new XMLTextReader (C:\miCarpeta\archivo.xml) Para acceder a los datos: Do While (lector.Read()) Hacer algo con los datos Loop El método Read avanza automáticamente por el archivo XML siempre que se ejecuta. Hay que cerrar el lector cuando se termina. <%@ Page Language="VB" %> <%@ Import Namespace="System.Xml" %> <script runat=server> 151 Sub Page_Load(obj As object, e As eventargs) Dim lector As XmlTextReader Dim i As integer Try lector = new XmlTextReader(Server.MapPath ("libros.xml")) While lector.Read() Select Case lector.NodeType Case XMLNodeType.Element If lector.HasAttributes Then For i = 0 To lector.AttributeCount − 1 Response.Write(lector.GetAttribute(i) & " ") Next Response.Write("<br>") End if Case XMLNodeType.Text Response.Write(lector.Value & "<br>") End Select End While Catch ex As Exception Response.Write("Error al acceder el archivo XML.") Finally lector.Close End Try End Sub </script> <html><body> 152 </body></html> <%@ Page Language="VB" %> <%@ Import Namespace="System.Xml" %> <script runat=server> Sub Page_Load(obj As object, e As eventargs) Dim lector As XmlTextReader Try lector = new XmlTextReader(Server.MapPath ("libros.xml")) While lector.Read() Response.Write("<b>" & lector.Name & "</b> " & lector.Value & "<br>") End While Catch ex As Exception Response.Write("Error al acceder el archivo XML.") Finally lector.Close End Try End Sub </script> <html><body> </body></html> XMLTextReader tiene la propiedad NodeTyper que indica el tipo de dato que se está buscando: XMLNodeType.All = todos los nodos XMLNodeType.Element= Un elemento XMLNodeType.Document= El nodo principal ESCRITURA DE XML El objeto XmlTextWriter ofrece el método Write. 153 <%@ Page Language="VB" %> <%@ Import Namespace="System.Xml" %> <script runat=server> Sub Page_Load(obj As object, e As eventargs) Dim escritor As XMLTextWriter Se declara un escritor Try escritor = new XMLTextWriter(Server.MapPath ("libros2.xml"), Nothing) Se instancia el escritor, el segundo parámetro es la codificación (predeterminada UTF−8). Si hay un archivo con el mismo nombre lo sobrescribe. escritor.WriteStartDocument escritor.Formatting = Formatting.Indented Indica que sangre el archivo escritor.Indentation = 3 Que use 3 espacios para el sangrado escritor.WriteStartElement("libreria") Empieza la generación de datos.Abre la etiqueta de elemento escritor.WriteStartElement("libro") escritor.WriteAttributeString("genero", "historia") Genera atributo escritor.WriteAttributeString("estilo", "cubierta dura") escritor.WriteElementString("titulo", "Vietnam") Encapsula la funcionalidad de inicio y fin de los elementos simples.Produce el resultado: <titulo>Vietnam</titulo> escritor.WriteStartElement("autor") escritor.WriteElementString("nombre", "Michael") escritor.WriteElementString("apellido", "Avery") escritor.WriteEndElement() escritor.WriteElementString("precio", "6.99") escritor.WriteEndElement() Cierra la etiqueta de elementos escritor.WriteEndElement() escritor.Flush Vacía el contenido Catch ex As Exception 154 Response.Write("Error al acceder el archivo XML.") Finally escritor.Close Response.Write("Proceso finalizado.") End Try End Sub </script> <html><body> </body></html> Apertura de un archivo XML con XMLDocument e iteración a través del archivo con XMLNodes <%@ Page Language="VB" %> <%@ Import Namespace="System.Xml" %> <script runat=server> private i As integer private strResultado As string = "" Sub Page_Load(obj As object, e As eventargs) Dim xmldoc As new XMLDocument() Genera un XMLDocument Try xmldoc.Load(Server.MapPath("libros.xml")) Carga los datos del archivo XML MostrarJerarquia(xmldoc.DocumentElement) Itera por los nodos y muestra los datos. DocumentElement devuelve el primer elemento. Es el punto de inicio para que itere por el archivo. Catch ex As Exception strResultado = "Error al acceder el archivo XML." End Try resultado.Text = strResultado End Sub Sub MostrarJerarquia(nodo As XMLNode) 155 Dim atribnodo As XmlNode Dim acot As XmlNamedNodeMap Representa colección de atributos de cada nodo If Not(nodo.HasChildNodes) strResultado += "&nbsp;&nbsp;<b>" & nodo.Name & "</b> &lt;" & _ nodo.Value & "&gt;<br>" & vbcrlf Else strResultado += "<b>" & nodo.Name & "</b>" If nodo.NodeType = XmlNodeType.Element Then acot = nodo.Attributes For Each atribnodo In acot strResultado += " <b>" & atribnodo.Name & "</b> &lt;" & _ atribnodo.Value & "&gt; " & vbcrlf Next End If strResultado +="<br>" End If If nodo.HasChildNodes then nodo = nodo.FirstChild While Not IsNothing(nodo) MostrarJerarquia(nodo) nodo = nodo.NextSibling Itera por los nodos secundarios de cada nodo End while End if End Sub </script> <html><body> <asp:Label id="resultado" runat="server" /> </body></html> 156 MODIFICACIÓN DE DATOS XML Para agregar elementos: CreateComment, CreateAttribute, CreateNode, etc. Cargamos un archivo XML y adjuntamos un nuevo nodo libro. <%@ Page Language="VB" %> <%@ Import Namespace="System.Xml" %> <script runat=server> Sub Page_Load(obj As object, e As eventargs) Dim xmldoc As new XMLDocument() Dim strResultado As String = "" Try xmldoc.Load(Server.MapPath("libros.xml")) Dim eleLibro As XmlElement = xmldoc.CreateElement ("libro") Dim attEstilo As XmlAttribute = xmldoc.CreateAttribute ("estilo") eleLibro.SetAttributeNode(attEstilo) eleLibro.SetAttribute("estilo", "cubierta dura") Dim root As XmlElement = xmldoc.Item("librería") root.AppendChild(eleLibro) Obtiene el elemento principal, librería, para que pueda agregarse el nuevo elemento libro. xmldoc.Save(Server.MapPath("libros.xml")) Para guardar los cambios Catch ex As Exception strResultado = "Error al acceder el archivo XML." End Try resultado.Text = "Se terminó adecuadamente la operación de adición." End Sub </script> <html><body> <asp:Label id="resultado" runat="server" /> 157 </body></html> TEMA 11: LECTURA Y ESCRITURA DE ARCHIVOS EN EL SERVIDOR WEB USO DE ARCHIVOS CON ASP.NET Asp.net permite acceder a todo el sistema de archivos del servidor. INCLUSIÓN DE ARCHIVOS EXTERNOS DESDE EL SERVIDOR Un archivo incluído desde el servidor es una forma de separar código de una página. <!−−#include file=../../includes/archivo1.aspx−−> <!−−#include virtual=/includes/archivo1.aspx−−> Ejemplo: Encabezado.aspx <a href=indice.aspx><img src=encabezado.gif alt=Principal></a><hr> <a href=indice.aspx>Principal </a> <a href=finSesion.aspx>Finalizar sesión </a> Página: <script lenguaje=c# runat=server> public void Page_Load(object obj, EventArgs e) { //hacemos algo } </script> <html><body> <!−−#include file=Encabezado.aspx−−> ¡Hola a todos! </body></html> Asp.net inserta el contenido de Encabezado.aspx antes de procesar cualquier comando. OLEDB sources (SQL Server 6.5) OLE DB .NET 158 Data Provider DataSet SQL Server .NET Data Provider SQL Server 7.0 (y posterior) 159