Herramientas de usuario

Herramientas del sitio


sp:aspnet

¡Esta es una revisión vieja del documento!


ASP.NET

Básico

Código ASP.NET

Las páginas aspnet son páginas con extensión .aspx donde podemos agregar código aspnet entre código HTML introduciendolo entre <% %>.

<% for (int i=0; i <8; i++) { %>
    <font size="<%=i%>"> Welcome to ASP.NET </font> <br>
<% }%>

En este código podemos acceder a las clases que pone .NET nuestra disposición. Por ejemplo, en el siguiente código se recoge el valor de las variables en la QueryString (la URI de llamada a la página) Name y Category:

<% if (Request.QueryString["Lookup"] != null) { %>
Hi <%=HttpUtility.HtmlEncode(Request.QueryString["Name"]) %>, you selected: <%=HttpUtility.HtmlEncode(Request.QueryString["Category"]) %>
<% } %>
...
<%=String.Format("({0}) {1}", DropDownList1.SelectedValue, DropDownList1.SelectedItem.ToString())%>

Con esta sintaxis también podemos mostrar texto directamente utilizando <%= %>:

<%="Hello World" %>

Para incluir código “a saco” utilizaremos <!– #Include File=“nombre” –>:

<!-- #Include File="Header.inc" -->

Para insertar datos incluidos en recursos, archivos de configuración (web.config)… Utilizamos la nomenclatura: <%$ … %>:

<asp:Label ID="Label1" Text='<%$ Resources: ExchRate, ConvertLabel %>' runat="server"/>
<asp:SqlDataSource ConnectionString="<%$ ConnectionStrings:Northwind %>" ... />

Este sólo puede utilizarse dentro de propiedades de controles, si quisiesemos utilizarlo para mostrar un valor necesitaríamos utilizar el control Literal:

<asp:Literal Runat="server" Text="<%$ AppSettings:appName %>" />

Tipos de archivo

  • Extensión .aspx: páginas web de ASP.NET, contienen el código de la interface de usuario.
  • Extensión .ascx: controles de usuario de ASP.NET, similares a páginas web pero que no pueden ser accedidas directamente. Se utilizan dentro de otras para la reutilización de código.
  • Extensión .asmx: ASP.NET web services.
  • Extensión .svc: ASP.NET web services que utilizan WCF.
  • web.config: Configuración de la aplicación ASP.NET.
  • global.asax: Fichero donde se definen variables globales y reacciones a eventos.
  • Extensión .cs: Código en C#.

Elementos de ASP.NET

  • Una directiva es un código que se encuentra en los archivos .aspx y se coloca entre los signos <%@ y %>. Pueden contener atributos que definen sus propiedades siguiendo la siguiente sintaxis:
<%@ Nombre atributo="valor" [atributo="valor"...] %>

Server Controls y Html Server Controls

Los Html Server Controls son tags html que se diferencian de las estandard debido a la clausula runat=“server”, esto hace que dicho tag se enlace con un objeto en el propio servidor al cual podrá accederse a partir de la id de la tag, el objeto tendra sus propias propiedades y métodos además de que generará un código html que se enviará al cliente. Los objetos que crearán provienen de System.Web.HtmlControls y, entre otros, son: HtmlAnchor, HtmlButton, HtmlForm, HtmlImage, HtmlInputButton, HtmlTable, HtmlTableCell, HtmlTextArea. Si para una tag concreta no existiese una clase a la que enlazarse directamente lo haría a HtmlGenericControl.

De esta forma si tenemos por ejemplo el siguiente código:

<img id="imgSample" runat="server" />

Podemos asignar la ruta para esta imágen de la siguiente forma:

imgSample.Src = "path_to_image/image_name.gif";

O por ejemplo:

<div id="panel">
...
</div>

Y…

panel.Visible = false;

Los Server Controls son Html Server Controls pero que no sólo emiten una tag html sino un código algo más extenso que puede contener varias tags colocadas en distinto orden (por ejemplo, también código javascript). Los Server Controls tienen las siguientes características:

  • Se declaran a partir del nombre de la clase: asp:nombre.
  • Cada declaración de control debe estar cerrada en la misma línea.
  • Todos los Server Controls han de estar dentro de una tag form.

Por ejemplo, un Server Control muy común es la label, este pasa a convertirse en una tag span:

<asp:label id="lblSample" runat="server" />

Podemos asignar propiedades y estilos a los controles como si lo hiciesemos a objetos ya creados:

Text1.Style["font-size"] = "20px";
Text1.Style["color"] = "red";
Text1.Style.Add("background-color", "lightyellow");
Text1.Value = "<Enter e-mail address here>";
Text1.Attributes["onfocus"] = "alert(Text1.value)";

El código anterior crearía la siguiente tag html:

<input id="Text1" type="text" style="font-size:20px;color:red;background-color:lightyellow;" value="<Enter e-mail address here>" onfocus="alert(Text.value)" />

Podemos agregar todos los HtmlControls que queramos a partir de la lista Controls dentro de Page:

HtmlTable table1 = new HtmlTable();
...
this.Controls.Add(table1);

Para los HtmlControls existen dos eventos importantes, el ServerClick y el ServerChange.

Un ejemplo de control de servidor:

<form action="intro4_cs.aspx" method="post" runat=server>
  <h3> Name: <asp:textbox id="Name" runat="server"/>
    Category:  <asp:dropdownlist id="Category" runat=server>
    <asp:listitem>psychology</asp:listitem>
    <asp:listitem>business</asp:listitem>
    <asp:listitem>popular_comp</asp:listitem>
    </asp:dropdownlist>
  </h3>
  <asp:button text="Lookup" runat="server"/>
</form>

En la misma página podemos gestionar los eventos declarando una tag <script language=“C#” runat=“server”>, entonces en esta podemos definir la función a ejecutar cuando se produzca un evento. Por ejemplo el OnClick de un botón:

<script language="C#" runat=server>
void SubmitBtn_Click(Object sender, EventArgs e) {
  Message.Text = "Hi " + HttpUtility.HtmlEncode(Name.Text) + ", you selected: " + Category.SelectedItem;
}
</script>
<!-- Y luego -->
Name: <asp:textbox id="Name" runat="server"/>
<asp:button text="Lookup" OnClick="SubmitBtn_Click" runat="server"/>
<asp:label id="Message" runat="server"/>

El código insertado en un script runat=“server” puede ser accedido desde el código aspnet.

<script language="C#" runat="server">
int subtract(int num1, int num2) {
  return num1 - num2;
}
</script>
<%
  ...
  number = subtract(number, 1);
  ...
%>

Evento Page_Load

La función Page_Load se llama automáticamente al cargarse una página, siendo esta correspondiente al evento.

<script language="C#" runat="server">
void Page_Load(Object Src, EventArgs E) {
    Message.Text = "You last accessed this page at: " + DateTime.Now; // Siendo Message una label
}
</script>

Code-Behind vs Code-Inline

  • Code-Inline es el modo más parecido al antiguo ASP, todo el código es introducido en el archivo .aspx, resulta útil para aplicaciones pequeñas.
  • Code-Behind, en el que se separa el código del archivo .aspx del de aplicación (.cs).

El más interesante es el code-behind, en el que la página se separa en varios archivos (por ejemplo, CodeBehind_cs.aspx y CodeBehind_cs.aspx.cs), donde el primero contendría toda la parte gráfica de la interficie y el segundo la lógica. El código que se introduciría en la segunda sería una clase parcial que heredase de System.Web.UI.Page.

using System;
public partial class CodeBehind_cs_aspx : System.Web.UI.Page {
    protected void Button1_Click(object sender, EventArgs e) {
        Label1.Text = "Hello " + TextBox1.Text;
    }
}

Respecto al Code-Inline decir que es necesario usar la directiva @Import para hacer accesibles los namespaces de los ensamblados disponibles.

Directorios en una aplicación

App_Code

Cuando tenemos un directorio App_Code en nuestra aplicación podemos agregar en él todo el código que queremos para que sea accesible para todas las páginas. Todos los ficheros que se encuentren en este directorio serán compilados en tiempo de ejecución.
Por ejemplo agregamos una clase en el App_Code que no tiene nada que ver con la interface. Luego podemos acceder a dicha clase desde cualquier página.

Bin

Cuando lo que tenemos son librerías ya compiladas y no código, para hacerlas accesibles desde nuestra página lo que haremos será ubicarlas en el directorio Bin del proyecto.

GAC

Como toda aplicación en .NET, las creadas con aspnet pueden acceder a los ensamblados ubicados en la Global Assembly Cache.

Estado de la aplicación

ASPNET gestiona una serie de instancias de HttpApplication correspondiendo cada una al transcurso de una visita a la página, es decir, se asigna una instancia a cada una de las peticiones http entrentes. La HttpApplication se crea la primera vez que se hace una petición al servidor, antes que eso aspnet no ejecuta código. Es entonces cuando se agraga a la lista de instancias y se lanza el evento Application_Start (definido en global.asax); cuando se finaliza se lanza el evento Application_End.

Sesiones

Podemos almacenar datos de usuario para la sesión.
En el fichero Global.asax podemos utilizar el diccionario Session para almacenar los valores que queremos que perduren.

// Guardar datos
void Session_Start () {
    Session["BackColor"] = "beige";
}
// Recoger datos
color = Session["BackColor"];

En el web.config podemos definir el tiempo que se mantiene la sesión activa (por defecto 20 minutos):

<sessionState
  timeout="40"
/>

Si las cookies no están activas, la sesión puede ser tratada a partir de un identificador en la URL, para ello agregaremos lo siguiente al web.config:

<sessionState
  cookieless="true"
/>

Fichero Global.asax

Las funciones del estilo Application_Start, Application_End, Session_Start o Session_End van en un archivo localizado en la raíz de la aplicación denominado Global.asax. Este se compila en una clase la primera vez que se hace alguna petición a cualquier recurso dentro de la aplicación. Este tiene una estructura parecida a la siguiente:

<script language="C#" runat="server">
 
void Application_Start(Object Sender, EventArgs E) {
}
</script>

Si el código necesitase acceder a namespaces adicionales se usaría la directiva @Import al inicio de la página tal como sigue:

<%@ Import Namespace="System.Text" %>

La primera vez que la página es abierta se lanza el evento Start:

void Application_Start(Object Sender, EventArgs E) {
}
 
void Session_Start(Object Sender, EventArgs E) {
  Response.Write("Session is Starting...<br>")
  Session.Timeout = 1
}

Los eventos BeginRequest y EndRequest se lanzan por cada petición.

  • Aquí tienes los archivos de ejemplo de una aplicación denominada PruebaASP2.

Por enlaces

Es el modo más sencillo de navegación entre formularios web, siguiendo el formato de la tag <a> de HTML, mediante el control <asp:HyperLink>:

<form id="Form1" method="post" runat="server">
	<asp:HyperLink id="HyperLink1" runat="server"
	NavigateUrl="WebForm2.aspx">WebForm2</asp:HyperLink>
</form>

Luego podremos cambiar su propiedad NavigateUrl:

HyperLink1.NavigateUrl = "WebForm3.aspx" 

Response.Redirect

Este método causa que el navegador se conecte a una URL específica; al llamarse se crea una nueva página con un header con código 302 (redirección), cuando el navegador la recibe usa esta información para generar otra petición http. Es decir, la redirección se hace en el lado del cliente.
Existe otro formato de llamada que es enviandole además un parámetro boolean. Esto significa que la ejecución de la página actual se ha de terminar, el sistema continuará con la ejecución mientras que el usuario es redireccionado a otra página.
Este método es perfecto para conectar recursos fuera del servidor web donde la página esté hospedada, o para conectar con recursos no-aspx, como páginas html.

Server.Transfer

Este método transfiere la ejecución del fichero .aspx actual a otro en el mismo servidor web, terminando su ejecución y control de flujo. La nueva página todavía utilizará el stream response creada anteriormente, es decir, el navegador mostrará la url de la página original (la redirección ocurre en el servidor sin que el navegador lo sepa).
A este método podemos pasarle un segundo argumento como true, para que se pase los datos del formulario y de la query string a la página transferida. Para ello deberemos recoger el formulario con Context.Handler.

private void Page_Load (object sender, System.EventArgs e)
{
	WebForm1 wf1 = (WebForm1)Context.Handler;
	Label1.Text=wf1.Name;
	Label2.Text=wf1.EMail;
}

Server.Execute

Este método permite a la página aspx actual ejecutar otra página dentro del mismo web server, después de ser ejecutada, se vuelve a pasar el control a la página original desde donde Server.Execute fue llamado. Es una técnica análoga a llamar una llamada a una función de una página aspx, esta tendrá acceso a las colecciones del formulario y de la query string de la página original.
Por defecto la salida de la página ejectuada se añade a la salida de la actual, pero para tener más control de donde colocar el texto generado podemos enviar por parámetro un objeto StringWriter sobre el cual se volcará:

StringWriter sw = new StringWriter();
Server.Execute("WebForm2.aspx", sw);
Literal1.Text = sw.ToString();

Propiedad PostBackUrl

La propiedad PostBackUrl en un control de servidor indica a qué página se enviará los datos del formulario, es decir, si asignamos a un botón esta propiedad con valor a otra página cuando se pulse a ese botón se irá automáticamente a la otra página, luego podemos recoger los valores de la anterior página desde Request.Form.

<asp:Button ID="button1" Runat=server Text="submit" PostBackUrl="~/NewPage.aspx" />

Luego podríamos acceder a los controles de la página anterior con:

TextBox tb = (TextBox)PreviousPage.FindControl("text1");

Pasar datos entre páginas

Por QueryString

Podemos montar una url como string y llamar a otra página:

string MyOccupation = "Software Developer";
string url;
url = "page2.aspx?occupation=" + HttpUtility.UrlEncode(MyOccupation);
Response.Redirect(url);

Y luego recogerla desde la página que hemos llamado:

protected void Page_Load(object sender, EventArgs e) {
  this.TextBox1.Text = Request.QueryString["occupation"];
  RetrievedValue = this.TextBox1.Text;
}

Por sesiones

Guardando y recogiendo en el diccionario Session:

Session["state_index"] = txtstate.text;
string state = Session["state_index"];

Recogiendo las propiedades públicas de la página anterior

Si en una página tubiesemos una propiedad pública podríamos acceder a esta desde el objeto PreviousPage. Podemos indicar el tipo de este objeto, ya que es un no-tipado, indicando en la directiva PreviousPageType de la página destino el VirtualPath:

<%@ PreviousPageType VirtualPath="~/SourcePage.aspx" %> 

Y luego podremos hacer, por ejemplo:

Label1.Text = PreviousPage.CurrentCity;

Recogiendo el valor deseado del formulario

Utilizando el método FindControl, del objeto Page.PreviousPage pasándole el identificador del control del que queramos recoger la info.

TextBox SourceTextBox = (TextBox)Page.PreviousPage.FindControl("TextBox1");

Algunos elementos básicos

Response

Método Redirect

El método Response.Redirect redirecciona el navegador del usuario a una página nueva:

Response.Redirect("Controls_NavigationTarget_cs.aspx?name=" + System.Web.HttpUtility.UrlEncode(Name.Text));

Clase Page

Todos los web forms que se creen en ASP.NET son clases que heredan de la clase System.Web.UI.Page.
Dentro de una clase que herede de Page podemos acceder a las siguientes propiedades:

  • Session, instancia de System.Web.SessionState.HttpSessionState que corresponde a un diccionario común en toda la sesión del usuario, perfecta para almacenar datos de usuario.
  • Application, instancia de System.Web.HttpApplicationState que corresponde a un diccionario común en toda la aplicación.
  • Cache, instancia System.Web.Caching.Cache nos da un mecanismo para optimizar el consumo de memoria.
  • Request, instancia de System.Web.HttpRequest, contiene toda la información enviada por el cliente.
    • Form, corresponde a un diccionario con los valores del formulario.
  • Response, instancia de System.Web.HttpResponse, contiene métodos para la comunicación con el cliente.
    • Redirect, método para indicar que página será la próxima en cargar.
    • OutputStream, corresponde al flujo que se envia al usuario.
    • Write, BinaryWrite o WriteFile para escribir sobre el output stream como texto o como fichero.
  • Server, instancia de System.Web.HttpServerUtility provee de una serie de métodos de ayuda para acceder a la información del servidor web.
    • HtmlEncode y HtmlDecode, para la conversión de texto simple a texto html y viceversa.
    • Transfer, más rápido que el Response.Redirect y con la misma función, pero restringida a la de redirigir únicamente hacia formularios web.
    • MapPath, retorna la dirección física de un fichero pasándole la dirección virtual.
  • User, instancia que implementa System.Security.Principal.IPrincipal, sobre el tipo de usuario que es el cliente.
  • Trace, instancia de System.Web.TraceContext que permite la escritura de traces de la página.

Existe el método SetFocus que permite indicar qué control recibe el foco.
También contiene la propiedad IsPostBack, esta nos indica si es la primera vez que se carga la pagina en ese caso retornará false.

La cabecera de la página

Como cualquier tag con la propiedad runat=“server” la head se convierte en un objeto accesible desde nuestro código siendo del tipo HtmlHead. Contiene las siguientes propiedades:

  • Title: Título de la página que corresponde.
  • StyleSheet: Un objete IStyleSheet que representa la hoja de estilos de la cabecera, como tal podemos eidtarlar utilizando los métodosCreateStyleRule y RegisterStyle.
  • Controls: Podemos añadir o eliminar metadata tags a partir de la colección HtmlMeta.
HtmlMeta metaKeywords = new HtmlMeta();
metaKeywords.Name = "keywords";
metaKeywords.Content = ".NET, C#, ASP.NET";
Page.Header.Controls.Add(metaKeywords);

Directiva Page

Los archivos de páginas (.aspx) comienzan con una directiva Page, la cual indica en qué lenguaje está programada y dónde encontrar el código. Algunos de sus atributos son:

  • Language: Indica el lenguaje utilizado.
  • AutoEventWireup: Indica si los eventos están autoconectados.
  • CodeFile: En páginas compiladas indica el archivo donde está el código al que se hace referencia.
  • Inherits: Indica la clase (que ha de heredar de System.Web.UI.Page) que enlaza.
  • ClassName: Especifica el nombre del resultado de la compilación.
  • Trace y TraceMode: Para indicar si se hace tracing de la página y el modo de este.

Por ejemplo la siguiente línea en el archivo Default.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

Enlaza con la clase _Default del archivo Default.aspx.cs:

public partial class _Default : System.Web.UI.Page {
    protected void Page_Load(object sender, EventArgs e) {
      ...

Otras clases

Units

Para indicar las unidades de medida utilizamos los objetos de la clase Unit. Estos representan un porcentaje, un tamaño fijo… las unidades que podemos expresar en html. Los métodos estáticos de la clase devuelven objetos, aunque también los podemos crear manualmente:

pnl.Height = Unit.Pixel(300);
pnl.Width = Unit.Percentage(50);
...
Unit myUnit = new Unit(300, UnitType.Pixel);
pnl.Height = myUnit;

HttpUtility

Con los siguientes métodos:

  • HtmlEncode: Para codificar strings para colocar en el contenido de la página.
  • UrlEncode: Para codificar strings para colocar en la dirección de la página.

El fichero Web.config

Este fichero se ubica en la ruta raíz de la aplicación y mediante él podemos configurarla, el estilo es parecido al app.config.

Configuración de connection strings

La cadena de conexión se puede almacenar en el fichero Web.config, en la sección <connectionStrings>, de esta forma es sencillo de mantenerla en un solo lugar para todas las páginas de la aplicación.

<configuration>
  <connectionStrings>
  <add name="Pubs" connectionString="Server=(local);Integrated Security=True;Database=pubs;"
     providerName="System.Data.SqlClient" />
  </connectionStrings>
</configuration>

Gestión de errores

Podemos realizarla:

  • A nivel de métodos, es el de toda la vida, utilizando try-catch-finally.
  • A nivel de página, consiste en sobreescribir el evento OnError del objeto Page o el atributo errorPage de esta (esto es, en la directiva de declaración indicar la url del archivo al que se llamará si ocurre un error).
  • A nivel de aplicación, consiste en escribir el evento OnError del objeto Application, dentro del fichero global.asax.

Existen dos métodos que pueden ayudarnos a la gestión de errores:

  • Server.GetLastError: El cual retorna una referencia al objeto Exception que se ha lanzado.
  • Server.ClearError: El cual limpia el error del servidor, si no es llamado el error se propagará. Es decir, si es un error a nivel de página pasará a ser a nivel de aplicación.

El siguiente ejemplo es la sobreescritura del evento OnError:

protected override void OnError (System.EventArgs e)
{
	Server.ClearError();
	Response.Redirect("~/error.html");
}

En el web.config existe una sección donde podemos especificar la página de error que utilizará ASP.NET a la cual nos redirigirá si ocurre una excepción no manejada. Este modo de controlar errores se basa en los siguientes puntos:

  • Propiedad mode: especifica como manejar un error:
    • RemoteOnly, los errores son mostrados para los usuarios remotos, las páginas de error ASP.NET con información detallada sobre el error se darán a los usuarios locales.
    • On, siempre se muestran las páginas personalizadas, si no estubiese definida una página para un error ASP.NET no mostraría información detallada.
    • Off, siempre se muestra información detallada sobre el error ocurrido.
  • Propiedad defaultRedirect: Especifica a qué pagina se redirecciona si ocurre un error.
  • Elementos error: Los cuales definen la acción para un error particular a partir de las propiedades statusCode, que indica el código de error, y redirect que indica a qué página se redireccionará si ocurriese dicho error.
<customErrors mode="On" defaultRedirect="/WebTest/ErrorPages/AppError.html">
  <error statusCode="404" redirect="/WebTest/ErrorPages/404.html" />
</customErrors>



Hay que tener cuidado, porque si se genera un error mientras se maneja errores puede darse un bucle infinito.

Ciclo de vida de una página ASP.NET

Fases

  • Page request, la petición de la página por parte del cliente. Se crea el objeto Page.
  • Start, inicio, se asignan los Request y Response, se determina si la petición es postback o no.
  • Page initialization, inicialización de los controles.
  • Load, si la página es postback se cargan los valores de los controles.
  • Validation, se llama al método Validate de todos los controles y se asigna la propiedad IsValid.
  • Postback event handling, si la página es postback entonces se llaman a los manejadores de eventos.
  • Rendering, se llama al método Render de cada control y se va escribiendo en el OutputStream la respuesta al cliente.
  • Unload, una vez se ha acabado de enviar la página al cliente se eliminan de memoria las propiedades y objetos que ya no se necesitarán.

Orden de llamada de eventos

  • PreInit.
    • Para comprobar si IsPostBack.
    • Para crear o recrear los controles dinámicos.
    • Asignar la master page o el tema dinámicamente.
    • Leer propiedades del perfil.
  • Init, se llama cuando todos los controles han sido inicializados y su skin aplicada.
    • Para leer o inicializar las propiedades de los controles.
  • InitComplete.
  • PreLoad.
  • Load, se llama al OnLoad de la página y al de todos los controles hijo.
    • Para establecer las conexiones de base de datos.
  • Control events, eventos de los controles.
  • LoadComplete.
  • PreRender
    • Para hacer los cambios finales al contenido de la página y sus controles.
  • SaveStateComplete.
  • Render
  • Unload

Otros

  • Esquema del ciclo de vida página: Esquema

Cookies

Las cookies son pequeños archivos de texto que se guardan en el ordenador del visitante de una web y que luego pueden ser recuperados. Los manejamos a partir del tipo System.Web.HttpCookie.

Para crear una cookie simplemente creamos un objeto del tipo HttpCookie a partir de un identificador y de un valor (en el caso siguiente el identificador es subgurim y el valor la fecha actual). Podremos decir cuando queremos que la cookie caduque a partir de la propiedad Expires.

HttpCookie addCookie = new HttpCookie("subgurim", DateTime.Now.ToString());
addCookie.Expires = DateTime.Today.AddDays(1).AddSeconds(-1);
Response.Cookies.Add(addCookie);

Podemos agregar la cookie de forma dinámica:

Response.Cookies["userName"].Value = "patrick";
Response.Cookies["userName"].Expires = DateTime.Now.AddDays(1);

Coger las cookies del cliente

Podemos recoger una cookie concreta a partir del método Request.Cookies.Get:

HttpCookie cogeCookie = Request.Cookies.Get("subgurim");

También podremos cogerla a partir del identificador la lista:

HttpCookie cogeCookie = Request.Cookies["subgurim"];

Al estar en una lista podemos recorrer todas las cookies del cliente:

foreach (HttpCookie cookie in Request.Cookies) {
  Response.Write(cookie.Name + ":" + cookie.Value + "<br />");
}

Modificar y eliminar las cookies

Podemos cambiar el valor de una cookie a partir del método Response.Cookies.Set:

HttpCookie modificaCookie = Request.Cookies.Get("subgurim");
modificaCookie.Expires = DateTime.Now.AddDays(7);
modificaCookie.Value = "hi!";
Response.Cookies.Set(modificaCookie);

O eliminarlas a partir del Response.Cookies.Remove:

Response.Cookies.Remove("subgurim");

O eliminarlas todas:

Response.Cookies.Clear();

Cookies con varios valores

Para crear una cookie con varios valores lo haremos como si fuese un array multidimensional.
Para asignarla lo haremos así…

Response.Cookies["userInfo"]["userName"] = "patrick";
Response.Cookies["userInfo"]["lastVisit"] = DateTime.Now.ToString();
Response.Cookies["userInfo"].Expires = DateTime.Now.AddDays(1);

O así:

HttpCookie addMultiCookie = new HttpCookie("subgurimMultidimensional");
for (int i = 0; i < 10; i++) {
  addMultiCookie.Values.Add(i.ToString(), "Elemento " + i.ToString());
  addMultiCookie[i.ToString()] = "Elemento " + i.ToString();
}
Response.Cookies.Add(addMultiCookie);

Y para recogerla de la siguiente forma:

HttpCookie cogeMultiCookie = Request.Cookies.Get("subgurimMultidimensional");   
string valorCualquiera = cogeMultiCookie.Values.Get("5");

La interface de usuario

Estilos

En los controles que soportan un modelo Style podemos establecer sus propiedades visuales a partir de CSS.
Dentro de un control la información de estilo se gestiona en su propiedad Style (tipo CssStyleCollection), esta es un diccionario que muestra los estilos indexados por cadenas:

<script language="C#" runat="server" >
    void Page_Load(Object sender, EventArgs E) {
        MyText.Style["width"] = "90px";
        Response.Write(MyText.Style["width"]);
    }
</script>

Los controles de servidor pueden definirse su visualización a partir de propiedades:

      <asp:Calendar runat="server"
           BackColor="Beige" 
           ForeColor="Brown"
           BorderWidth="3"
           BorderStyle="Solid"
           BorderColor="Black"
           Height="450"
           Width="450"
           Font-Size="12pt"
           Font-Names="Tahoma,Arial"
           Font-Underline="false"
           CellSpacing=2
           CellPadding=2 
           ShowGridLines=true
       />

También se pueden acceder a propiedades de forma individual a partir de PropertyName-SubPropertyName:

<ASP:Calendar runat="server"
           BackColor="Beige" 
           ForeColor="Brown"
           BorderWidth="3"
           BorderStyle="Solid"
           BorderColor="Black"
           Height="450"
           Width="450"
           Font-Size="12pt"
           Font-Names="Tahoma,Arial"
           Font-Underline="false"
           CellSpacing=2
           CellPadding=2 
           ShowGridLines=true
 
           TitleStyle-BorderColor="darkolivegreen"
           TitleStyle-BorderWidth="3"
           TitleStyle-BackColor="olivedrab"	
           TitleStyle-Height="50px"
 
           DayHeaderStyle-BorderColor="darkolivegreen"  
           DayHeaderStyle-BorderWidth="3"
           DayHeaderStyle-BackColor="olivedrab"
           DayHeaderStyle-ForeColor="black"
           DayHeaderStyle-Height="20px"  
           ...

En los controles de servidor podemos indicar la clase CSS a partir de la propiedad CssClass:

<ASP:Calendar CssClass="calstyle" runat="server" ...

O con la propiedad, simplemente, class:

<div id="Div2" class="divDetails" runat="server"></div>

Una clase css sería:

.errorText
{
	color: Red;
	font-weight: bold;
}

Pero lo más aconsejable, si utilizamos hojas de estilos (css) es anidar los estilos de la siguiente forma:

table.taula { ... }
table.taula td { ... }
table.taula th  { ... }
table.taula tr.evenCell  { ... }
table.taula tr.oddCell { ... }
table.taula td.evenCell { ... }
table.taula td.oddCell { ... }
table.taula td.littleEvenCell { ... }
table.taula td.littleOddCell { ... }

También podemos definir los estilos a partir de código:

Style style = new Style();
style.BorderColor = Color.Black;
style.BorderStyle = BorderStyle.Dashed;
style.BorderWidth = 1;
 
MyLoginTextBox.ApplyStyle (style);
MyPasswordTextBox.ApplyStyle (style);
MySubmitButton.ApplyStyle (style);

Temas

Un tema es un conjunto de ficheros que definen la apariencia de la web. Se ubican en un directorio dentro de nuestro proyecto denominado App_Themes, en este se encuentran ficheros skin, ficheros css y subcarpetas con diversos temas. Los ficheros skin contiene definiciones de estilo para los distintos controles de la aplicación.

Podemos asignar un tema a nivel de página o de configuración:

  • Para asignar un tema a nivel de página, lo que haremos será agregar la directiva <%@ Page Theme=“…” %> al principio de la página indicando el nombre del tema (el nombre de la carpeta bajo el directorio Themes o App_Themes), esto haría que la definición del tema sobreescribiese la del control. En cambio, podemos indicar que sea la del control la que predomine indicando el tema en StyleSheetTheme en vez de en Theme.
  • Para asignar un tema a nivel de configuración agregaremos una sección pages theme en el web.config:
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
    <system.web>
      <pages theme="ExampleTheme"/>
    </system.web>
</configuration>

Si quisieramos desabilitar los temas para un control pondríamos su propiedad EnableTheming a false.

Podemos crear temas a nivel de máquina colocándolos en la carpeta %WINDIR%\Microsoft.NET\Framework\<version>\ASP.NETClientFiles\Themes o enInetpub\wwwroot\aspnet_client\system_web\<version>\Themes.

Podemos agregar una hoja de estilos a un tema añadiendo el archivo css en el directorio de este, los estilos serán aplicables siempre y cuando la definición del head de la página sea <head runat=“server”/>. Un tema podrá contener distintos ficheros .css cuando la página los referencie (mediante una etiqueta <link rel=“stylesheet” href=“…”/> en el elemento <head/>).

Para asignar un tema en tiempo de ejecución lo asignaremos al objeto Page durante el evento PreInit.

Skins

Los skins se definen en archivos .skin dentro del App_Themes, su contenido es la definición de las propiedades visuales de los controles.
Para diferenciarlos, se puede definir la propiedad SkinID para concretar un estilo:

<asp:label runat="server" font-bold="true" forecolor="orange" />
<asp:label runat="server" SkinID="Blue" font-bold="true" forecolor="blue" />
 
<asp:Calendar runat="server" BackColor="#FFFFCC" BorderColor="#FFCC66" BorderWidth="1px" DayNameFormat="FirstLetter" Font-Names="Verdana" Font-Size="8pt" ForeColor="#663399" Height="200px" ShowGridLines="True" Width="220px">
  <SelectedDayStyle BackColor="#CCCCFF" Font-Bold="True" />
  <SelectorStyle BackColor="#FFCC66" />
  <OtherMonthDayStyle ForeColor="#CC9966" />
  <TodayDayStyle BackColor="#FFCC66" ForeColor="White" />
  <NextPrevStyle Font-Size="9pt" ForeColor="#FFFFCC" />
  <DayHeaderStyle BackColor="#FFCC66" Font-Bold="True" Height="1px" />
  <TitleStyle BackColor="#990000" Font-Bold="True" Font-Size="9pt" ForeColor="#FFFFCC" />
</asp:Calendar>

Y luego:

<asp:Label ID="Label1" runat="server" Text="Hello 1" /><br />
<asp:Label ID="Label2" runat="server" Text="Hello 2" SkinID="Blue" /><br />

Podríamos agrupar los ficheros skin por Tema (propuesta 1) nombrandolos como su SkinID o por control (propuesta 2):

Propuesta 1
/WebSite1
  /App_Themes
    /MyTheme
      Default.skin
      Red.skin
      Blue.skin

Propuesta 2
/WebSite1
  /App_Themes
    /MyTheme
      GridView.skin
      Calendar.skin
      Label.skin

Master Pages

La definición de una master page permite definir unos elementos de la página (cabecera, pie de página, navegación…) que serán comunes para todas las páginas asociadas a esta.

La definición de una master page es como las demás solo que estas, mediante el control ContentPlaceHolder puede definir la región que ha de sustituirse. También puede contener contenido por defecto, por si la página derivada no necesita sobreescribirlo. La sintaxis es la siguiente:

<%-- ContentPlaceHolder control --%>
<asp:contentplaceholder id="FlowerText" runat="server"/>
<%-- ContentPlaceHolder with default content --%>
<asp:contentplaceholder id="FlowerText" runat="server">
  <h3>Welcome to my florist website!</h3>
</asp:contentplaceholder>

Una master page está en un fichero .master y para que una página normal derive de esta lo ha de indicar en la propiedad MasterPageFile en la directiva Page, una vez asociada pasará a denominarse Content Page.

 
<%@ Page MasterPageFile="Site.master" %>

Una Content Page puede declarar controles Content para sobreescribir el contenido de la Master Page, este se asocia a un ContentPlaceHolder a través de la propiedad ContentPlaceHolderID.

<%@ Page MasterPageFile="Site.master" %>
 
<asp:content id="Content1" contentplaceholderid="FlowerText" runat="server">
    With sunshine, water, and careful tending, roses will bloom several times in a season.
</asp:content>
<asp:content id="Content2" contentplaceholderid="FlowerPicture" runat="server">
    <asp:Image id="image1" imageurl="~/images/rose.jpg" runat="server"/>
</asp:content>

Es decir, debemos de seguir lo siguiente:

  1. Crear la página master, esta ha de tener una directiva del tipo @Master en vez de @Page.
  2. Las regiones que se puedan modificar estarán en controles <asp:ConentPlaceHolder>.
  3. Crear una página normal, esta sí que tendrá la directiva @Page con el agributo MasterPageFile indicando su propia página master. No deberá de tener más código HTML.
  4. Las áreas que se vayan a sustituir en las masterpages serán controles <asp:Content> que definan el atributo ContentPlaceHolderID que indique el <asp:ContentPlaceHolder> de la página master a sobreescribir.

Si la Master Page define elementos a partir de rutas relativas y la Content Page se encuentra en otra ruta se producirán errores de no encontrar la ubicación. Para solucionar esto podemos:

  • Utilizar URL absolutas.
  • Utilizar URL relativas de aplicación, donde ~ corresponde a la raíz de esta, algo así: <asp:Image ImageUrl=“~/images/banner.gif” runat=“server” />.

Las Master Pages también pueden contener otras Master Pages, por ejemplo, podríamos tener una Master Page que represente la cabecera/pie de página y la navegación global del sitio, y después Master Pages separadas que deriven de esta para definir los aspectos de las diferentes sub-secciones del sitio.

Comunicación entre la MasterPage y el contenido

Cuando utilizamos la directiva MasterType en un WebForm estamos especificando el tipo del que será la página maestra. Esto significa que al acceder a la propiedad Master de la Page tendremos también acceso a sus propiedades. Si utilizamos MasterPages anidadas no podremos acceder a los datos de la raíz desde el WebForm, pero como lo que realmente estamos indicando es el tipo podemos hacer que las MasterPages hereden de un tipo concreto y en la directiva MasterType indicar ese.

<%@ MasterType VirtualPath="Site.master" %>

Por lo tanto, a partir de ahora la Content Page puede referenciar la Master Page mediante la propiedad Master de la clase Page:

Master.FooterText = "This is a custom footer";
AdRotator ad = (AdRotator)Master.FindControl("MyAdRotator");

Para comunicar desde la MasterPage al contenido lo que haremos será lanzar un evento.

Notas

  • La MasterPage inserta la el WebForm entre los eventos PreInit e Init.
  • Podemos indicar la MasterPage por código, pero antes del evento PreInit mediante la propiedad MasterPageFile del objeto Page.
  • Podemos indicar la MasterPage por defecto a partir del fichero de configuración:
<configuration>
  <system.Web>
    <pages master="otc.master" />
  </system.Web>
</configuration>

Seguridad

Perfiles de usuario

Los perfiles de usuario se gestionan a partir de objetos Profile y estos se administran con objetos ProfileManager.

WebServices

Controladores globales, ficheros .ashx

Permiten devolver otro tipo de respuesta que no sea HTML (como por ejemplo XML, JSON…), dándonos la posivilidad de indicar el formato en la cabecera de lo devuelto (text/plain, text/xml…).

Son clases que se tratan como los formularios web, por una parte tienen el nombre del fichero al cual se hará la petición (fichero .ashx donde se indicará cual es su clase) y por otra code begind (su clase en sí, en un fichero .ashx.cs) en una clase que hereda de la interface System.Web.IHttpHandler. En el método ProcessRequest será donde coloquemos lo que devolveremos a partir del método Write del HttpContext.Response que nos vendrá por parámetro.

El siguiente ejemplo utiliza la librería Json.NET para devolver datos en formato JSON (texto plano), por lo tanto primero tenemos el fichero .ashx:

<%@ WebHandler Language="C#" CodeBehind="controller.ashx.cs" Class="WebApplication4.controller" %>

Y luego su clase correspondiente (fichero controller.ashx.cs):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
 
namespace WebApplication4
{
    public class controller : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";
            context.Response.ContentEncoding = System.Text.Encoding.UTF8;
            MyClass MyObject = new MyClass() { name = "Pedro", age = 49 };
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(MyObject);
            context.Response.Write(json);
        }
 
        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}

Notas

Como...

Agregar una librería

Después de agregar un ensamblado a la carpeta bin ya podremos utilizarlo en el code-behind, pero para utilizarlo en el code-inline tendremos que agregar la directiva Register al principio del documento:

<%@ Register assembly="ScsComboBox" namespace="SCS.WebControls" tagprefix="scs" %>

A partir de entonces los controles dentro de SCS.WebControls (el namespace del ejemplo) serán accesibles desde scs:

<scs:ScsComboBox ID="dest" runat="server" EnableDefaultItem="false" Width="100px"/>

Visual Studio

  • Para cambiar el navegador por defecto en VS2008: Botón derecho sobre un .aspx → Browse with. Ahora podemos agregar nuevos navegadores y escoger el de por defecto.
  • Para distribuir la aplicación ASP.NET desde Visual Studio .NET podemos indicar que se copien los archivos necesario a una carpeta, directorio virtual, FTP… Desde el menú → Generar → Publicar la aplicación.
sp/aspnet.1250788639.txt.gz · Última modificación: 2020/05/09 09:24 (editor externo)