Variables de servidor en ASP.NET
Nuestro servidor ASP.NET aloja una gran cantidad de información útil que, en determinado momento, puede salvarnos de situaciones complejas. Este conjunto de variables puede consultarse mediante el objeto Request.ServerVariables[<NombreVariable>]. Así, si realizamos la siguiente consulta:
string navegador = Request.ServerVariable["HTTP_USER_AGENT"];
La variable navegador alojará, como intuitivamente podremos imaginar, el navegador que está utilizando el cliente que se conecta a nuestro servidor, dato utilizado, por ejemplo, para estadísticas. En nuestro caso, el dato devuelto será el siguiente:
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 3.0.04506.30; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 1.0.3705; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
Hay cantidad de variables de servidor cuya consulta puede hacernos la vida más fácil. Como ejemplo, indicaremos algunas de ellas:
| VARIABLE | SIGNIFICADO | EJEMPLO |
|---|---|---|
| SERVER_PROTOCOL | Protocolo de conexión | HTTP/1.1 |
| REMOTE_ADDR | Dirección IP Remota | 80.24.53.11 |
| LOCAL_ADDR | Direccion IP Local | 127.0.0.1 |
| PATH_INFO | Ruta de la aplicación | /MiAplicacion/Pagina.aspx |
| URL | URL de la página | /MiAplicacion/Pagina.aspx |
| AUTH_TYPE | Tipo de autenticación | Forms |
| SERVER_PORT | Puerto HTTP | 80 |
| HTTP_USER_AGENT | Navegador del usuario | Mozilla/4.0 (compatible; MSIE 8.0;… |
| HTTP_HOST | Nombre del host | MyMachine |
| SERVER_NAME | Nombre del servidor | MyMachine |
| SERVER_SOFTWARE | Servidor web | Microsoft-IIS/6.0 |
| APPL_PHYSICAL_PATH | Ruta física de la aplicación | C:\\Inetpub\\wwwroot\\MiAplicacion\\ |
| HTTPS | ¿Usa SSL? | off |
| AUTH_USER | Usuario autenticado | administrador |
| REMOTE_USER | Usuario remoto | administrador |
| HTTP_CONNECTION | Tipo de conexión HTTP | Keep alive |
| HTTP_ACCEPT_LANGUAGE | Idioma | es |
Existen más variables de servidor, y basta con recorrer con un bucle su contenido para echarle un vistazo a todas:
Hashtable hs = new Hashtable();
foreach (string s in Request.ServerVariables.AllKeys)
{
hs.Add(s, Request.ServerVariables[s]);
}
Almacenamiento y recuperación de parámetros en Sesión y ViewState
Muchas veces necesitamos utilizar parámetros entre distintos métodos de un mismo formulario web, o incluso entre formularios distintos. Una forma dinámica de realizar este intercambio de datos es la utilización del ViewState y del espacio de sesión.
Antes de embarcarnos a almacenar datos y datos en estos dos espacios de memoria, hay que dejar claras dos cosas:
- El ViewState se intercambia continuamente entre cliente y servidor, por lo que es aconsejable no sobrecargarlo. Al aumentar el ViewState, aumentará el tamaño de la página, y por consiguiente, el tráfico de datos y la velocidad de carga de la misma.
- La sesión se almacena en servidor, por lo que si nuestro sitio web posee una carga de datos moderada - alta, el rendimiento del mismo se verá penalizado. Nuevamente, es aconsejable utilizar con cautela este espacio de memoria.
Teniendo claros estos dos conceptos, utilizaremos el ViewState para almacenar datos locales (de una misma página) y la sesión para pasar parámetros entre distintas páginas sin hacer uso de la QueryString. Para los profanos en la materia, explicaremos que la QueryString es la colección de parámetros que pueden, opcionalmente, acompañar a la dirección de la página. Éstos parámetros ofrecen información directamente recopilable por nuestro formulario web, pero cuenta con la desventaja de que es visible para el usuario.
Servicios Web (II): Consumiendo un servicio web
Veíamos anteriormente cómo crear un servicio web simple. A continuación veremos cómo consumirlo.
Si crear un WebService no tiene demasiada dificultad, consumirlo es, si cabe, mucho más sencillo. Crearemos una aplicación web normal y corriente, y sobre ésta, haremos click derecho y seleccionaremos la opción [Agregar Referencia Web...]

Hecho esto, se desplegará un menú que nos permitirá la detección de servicios web. Si introducimos la dirección en la que el servicio está publicado y pulsamos en “Ir” se nos mostrará los métodos que el servicio expone. En la caja de texto derecha añadiremos el nombre que tendrá nuestra referencia (por ejemplo, ServicioSimple) y pulsaremos sobre [Agregar referencia].

Hecho esto, se agregará a nuestro proyecto una referencia a nuestro servicio web, que se mostrará en nuestro proyecto de la siguiente manera:

Finalmente, añadiremos controles a nuestra página para comprobar que nuestra aplicación se comunica perfectamente con el servicio web. Para ello crearemos un GridView, dos Label, una caja de Texto y tres botones.
En el primer botón codificaremos la funcionalidad para cargar el GridView con la primera tabla del DataSet devuelto por el método GetData() de nuestro servicio web. Para ello crearemos una referencia a nuestro servicio, crearemos una referencia a un DataSet e invocaremos el método GetData() del WebService. Finalmente rellenaremos el Grid con el resultado obtenido.
protected void ButtonGrid_Click(object sender, EventArgs e)
{
// Referenciamos el servicio
ServicioSimple.Service referenciaServicio = new ServicioSimple.Service();
// Creamos una referencia a un DataSet
DataSet ds;
// Invocamos el WebMethod GetData()
ds = referenciaServicio.GetData();
// Rellenamos el DataGrid
GridViewDatos.DataSource = ds.Tables[0];
GridViewDatos.DataBind();
}
En el segundo botón haremos que nuestro label muestre el resultado de la invocación al método GetDate(), que recordemos que devolvía la fecha actual.
protected void ButtonFecha_Click(object sender, EventArgs e)
{
// Referenciamos el servicio
ServicioSimple.Service referenciaServicio = new ServicioSimple.Service();
LabelFecha.Text = referenciaServicio.GetDate().ToString();
}
Por último, el tercer botón mostrará el resultado de invocar al método GetDateDiff(int). Para ello le pasaremos al WebService un parámetro que indicará el número de horas que tiene que añadir. Para ello utilizaremos la caja de texto.
protected void ButtonFechaDiff_Click(object sender, EventArgs e)
{
// Referenciamos el servicio
ServicioSimple.Service referenciaServicio = new ServicioSimple.Service();
if (!string.IsNullOrEmpty(TextBoxDiferencia.Text))
{
LabelFechaDiferencia.Text = referenciaServicio.GetDateDiff(Convert.ToInt32(TextBoxDiferencia.Text)).ToString();
}
}
Hecho. Ya hemos creado un servicio web y hemos aprendido a consumirlo.

Servicios Web (I): Creando un servicio web simple
Un servicio web no es más que un conjunto de protocolos y estándares cuyo objetivo es el intercambio de información entre distintas aplicaciones. Los servicios web tienen la peculiaridad de ser independientes de plataforma, es decir, cumplen estándares propios y no dependen ni del hardware sobre el que se ejecuta ni del sistema operativo o servidor web que lo aloja.
Un servicio web intercambia información. Al invocar un servicio web estamos realizando una petición a otra máquina, a la que (opcionalmente) le enviamos información, la procesa y nos devuelve una respuesta, generalmente atómica y serializable, es decir: lo común es que un servicio web nos devuelva un dato o estructura de datos con la información que necesitemos (atómica) en forma de cadena de texto (serializable). Esto es así por el lenguaje común que “hablan” los servicios web: XML.
Si quisiéramos crear un servicio web, en una solución en blanco pulsaríamos sobre Agregar > Nuevo sitio Web…

Hecho esto, seleccionaremos la plantilla “Servicio Web ASP.NET”, y alojaremos el servicio web en nuestro IIS indicándole la ruta que deseemos.

A continuación, crearemos los métodos que queramos exponer, añadiendo el atributo [WebService] a la clase y el atributo [WebMethod] a los métodos que deban ser expuestos.
Crearemos tres métodos: uno que devuelva la hora actual, otro que devuelva nuestra localización geográfica y otro que añada las horas pasadas como parámetro a la hora actual.
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
[WebService(Namespace = "http://localhost/Services/Date")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public Service () {
//Eliminar la marca de comentario de la línea siguiente si utiliza los componentes diseñados
//InitializeComponent();
}
[WebMethod]
public DateTime GetDate() {
return DateTime.Now;
}
[WebMethod]
public string GetLocation()
{
return "UTC/GMT +2, Madrid, Spain.";
}
[WebMethod]
public DateTime GetDateDiff(int horasDiferencia)
{
return DateTime.Now.AddHours(horasDiferencia);
}
}
Hecho esto, iremos a la dirección de nuestro servicio web, lo cual nos mostrará lo siguiente:

Para probar el servicio web, haremos click sobre cualquiera de los métodos expuestos. Si el webservice no requiere ningún parámetro, se nos mostrará directamente el resultado de la invocación:
![]()
En caso contrario, se nos pedirá que introduzcamos el parámetro requerido, lo cual nos llevará a la obtención del dato.

Si analizamos el contenido de la respuesta, comprobaremos que, efectivamente, se trata de un fichero XML.
<?xml version="1.0" encoding="utf-8"?>
<dateTime xmlns="http://localhost/Services/Date">2009-06-09T17:27:00.0874935+02:00</dateTime>
Posteriormente comprobaremos cómo realizar una invocación a un servicio web desde nuestra aplicación.
Añadiendo un TemplateField a un GridView de forma dinámica
La mayor parte de los sitios web que se sirven de listados lo hacen utilizando un esquema como el que sigue:

Como vemos, lo normal suele ser utilizar campos enlazados a la consulta (BoundFields), así como campos-plantilla (TemplateFields) con los que se suele interactuar con el listado (ver detalles, edición, etc.).
Si sabemos de antemano qué datos vamos a obtener, es sencillo “maquetar” nuestro GridView de forma sencilla. El problema radica en el momento en el que el número de columnas que nuestro GridView mostrará sea variable. En este caso, el atributo AutoGenerateColumns deberá ser puesto a True, con lo que perderemos el control del orden de los TemplateFields.
Veamos el siguiente caso: queremos un campo plantilla que muestre un LinkButton que nos permita editar el registro, y otro que nos permita visualizar los detalles del mismo. Queremos uno de estos campos en la primera columna (el de edición) y otro en la última (visualización). Si utilizamos TemplateFields con el atributo AutoGenerateColumns=”True”, lo que lograremos será que ambos botones se sitúen juntos en las dos primeras columnas de nuestro GridView. ¿Cómo hacer que uno de ellos se coloque al final? Añadiéndolo de forma dinámica.
Para comenzar, añadiremos un GridView con un TemplateField conteniendo un LinkButton, colocando el atributo AutogenerateColumns=”True”.

El templatefield contendría un LinkButton:

El resultado sería este:

Seguidamente, acudiremos a nuestro código, listos para editar el evento RowDataBound. En él haremos lo siguiente:
- Declararemos una celda y un LinkButton.
- Daremos formato al LinkButton (nombre, clase, etc.)
- Asignaremos al LinkButton un CommandArgument igual al Identificador (DataKey) de esa fila del GridView
- Añadiremos el LinkButton a la celda, y la celda a la fila
Para ello utilizaremos el siguiente código:
Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound Try ' Si se trata de una fila de datos... If e.Row.RowType = DataControlRowType.DataRow Then Dim celda As New TableCell() Dim boton As New LinkButton() boton.Text = "Detalles" If e.Row.Cells.Count > 1 Then boton.CommandArgument = GridView1.DataKeys(e.Row.RowIndex).Value.ToString() End If ' Añadimos el LinkButton a la celda, y la celda a la fila celda.Controls.Add(boton) e.Row.Controls.Add(celda) End If Catch ex As Exception Throw ex End Try End Sub
Con esto lograremos el buscado esquema [Botón] [CAMPOS] [Botón].

