Development

Generadores y Controladores HTTP

ASP.NET proporciona una API de bajo nivel para solicitudes y respuestas que permite a los programadores utilizar clases de .NET Framework para ocuparse de las solicitudes HTTP entrantes. Para ello, los programadores crean clases que admiten la interfaz System.Web.IHTTPHandler e implementan el método ProcessRequest(). Los controladores suelen ser útiles cuando los servicios suministrados por la abstracción del marco de trabajo de página de alto nivel no son necesarios para procesar la solicitud HTTP. Entre los usos habituales de los controladores, se incluyen los filtros y las aplicaciones al estilo CGI, especialmente aquéllas que devuelven datos binarios.

Cada solicitud HTTP recibida por ASP.NET se procesa en último término mediante una instancia específica de una clase que implementa IHTTPHandler. IHttpHandlerFactory proporciona la infraestructura que controla la resolución real de las solicitudes URL en instancias IHttpHandler. Además de las clases IHttpHandlerFactory predeterminadas suministradas por ASP.NET, los programadores pueden opcionalmente crear y registrar generadores que admitan escenarios complejos de activación y resolución de solicitudes.

Configurar generadores y controladores HTTP

Los generadores y controladores HTTP se declaran en la configuración de ASP.NET como parte de un archivo web.config. ASP.NET define una sección de configuración <httphandlers> en la que se pueden agregar y quitar controladores y generadores. Los valores de configuración para HttpHandlerFactory y HttpHandler son heredados por los subdirectorios.

Por ejemplo, ASP.NET asigna todas las solicitudes de archivos .aspx a la clase PageHandlerFactory del archivo global machine.config:

<httphandlers>

 

  <add verb="*" path="*.aspx" type="System.Web.UI.PageHandlerFactory,System.Web" />

 

</httphandlers>

Crear un controlador HTTP personalizado

El siguiente ejemplo crea un controlador HttpHandler personalizado que controla todas las solicitudes que se realizan a "SimpleHandler.aspx".

using System.Web;

 

namespace Acme {

 

    public class SimpleHandler : IHttpHandler {

   

        public void ProcessRequest(HttpContext context) {

            context.Response.Write("Hola a todos");

        }

 

        public bool IsReusable {

            get {

                return true;

            }

        }

    }

}

 

Un controlador HTTP personalizado se puede crear implementando la interfaz IHttpHandler, la cual contiene sólo dos métodos. Mediante una llamada a IsReusable, un generador HTTP puede consultar a un controlador para determinar si se puede utilizar la misma instancia con el f in de atender a varias solicitudes. El método ProcessRequest toma una instancia HttpContext como parámetro y le proporciona acceso a los intrínsecos Request y Response. En el siguiente ejemplo, los datos de solicitud no se tienen en cuenta y se envía una constante de tipo cadena como respuesta al cliente.  

Después de incluir el ensamblado del controlador compilado en el directorio \bin de la aplicación, la clase del controlador se puede especificar como objetivo de las solicitudes. En este caso, todas las solicitudes dirigidas a "SimpleHandler.aspx" se desvían a una instancia de la clase SimpleHandler, la cual reside en el espacio de nombres Acme.SimpleHandler

<configuration>
  <system.web>
    <httpHandlers>
      <add verb="*" path="SimpleHandler.aspx" type="Acme.SimpleHandler, SimpleHandler" />
    </httpHandlers>
  </system.web>
</configuration>
 
Resumen
  1. Los controladores y generadores HTTP constituyen el eje del marco de trabajo de las páginas ASP.NET.
  2. Los generadores asignan cada solicitud a un controlador, que se encarga de procesarlas.
  3. Los generadores y controladores se definen en el archivo web.config. Los subdirectorios heredan la configuración de los generadores..
  4. Para crear un controlador personalizado, hay que implementar IHttpHandler y agregar la clase a la sección <httphandlers> del archivo web.config del directorio.
Development

La directiva @OutputCache

 

Un problema muy común cuando desarrollamos una aplicación Web es el boton Atras o la tecla Backspace ya que generalmente lo que hacen es traer la página que quedó en la caché del cliente en lugar de traerla del servidor, un problema muy típico que a muchos les ha sucedido.

Una aplicación común es cuando se define un boton para logout y en el se codifica algunas sentencias de limpieza de sesiones tal como:

 

Session.Abandon();

 

En .NET existen algunas sentencias que nos van a evitar que se traiga las páginas de caché y en vez de ello las vuelven a traer desde el servidor, refrescando las variables y sessiones. Entre ellas tenemos:

 

HttpContext.Current.Response.Cache.SetExpires(DateTime.Now.AddYears(-10));

HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);

HttpContext.Current.Response.Cache.SetNoStore();

 

ASP.NET proporciona métodos más sencillos para controlar el caché. Puede utilizar el directivo @ OutputCache para controlar resultado de página de caché en ASP.NET. Utilice la clase HttpCachePolicy para almacenar objetos arbitrarios tales como conjuntos de datos a memoria de servidor. Puede almacenar el caché en aplicaciones como el explorador de cliente, el servidor proxy y Microsoft Internet Information Services (IIS). Utilizando el Encabezado HTTP Cache-Control, puede controlar el caché.

 

Página ASP.NET de caché

Puede utilizar el directivo @ OutputCache para caché o almacenar en caché mediante código mediante programación utilizando Visual Basic .NET o Visual C # .NET. La directiva @ OutputCache contiene un atributo Location. Este atributo determina la ubicación para elemento almacenado en caché. Puede especificar las siguientes ubicaciones

  1.  

Cualquiera Esto almacena el caché de resultados en el explorador del cliente en el servidor proxy (o cualquier otro servidor) que participa en la solicitud o en el servidor en el que se procesa la solicitud. De forma predeterminada, Cualquiera está seleccionado.

  1.  

Cliente Esto almacena caché de resultados en el explorador del cliente.

  1.  

</UITERM> Indirecto- Esto almacena el caché de resultados en cualquier dispositivo cache-capable (del servidor de origen) que participe en la solicitud.

  1.  

Servidor Esto almacena el caché de resultados en el servidor Web.

  1.  

Ninguno estos turnos lejos del caché de resultados.

 

La directiva @ OutputCache es para controlar el almacenamiento en caché de resultados de páginas en ASP.NET con Visual C# .NET. Puede usar esta técnica para almacenar en caché las páginas del sitio a las que se tenga acceso con más frecuencia, lo que puede aumentar sustancialmente el rendimiento del servidor Web. El rendimiento suele medirse en solicitudes por segundo. Aunque en el ejemplo de código de este artículo se demuestra cómo usar los atributos Duration y VaryByParam, el artículo también incluye una breve descripción de otros enfoques que puede usar con la directiva @ OutputCache

 

Introducción a la directiva @ OutputCache

 

Para utilizar la directiva @ OutputCache para controlar el almacenamiento en caché de resultados de páginas, simplemente hay que agregar la directiva a la parte superior de la página. El método Page.InitOutputCache traduce la directiva en los métodos de la clase HttpCachePolicy.

 

La directiva @ OutputCache incluye los siguientes atributos y opciones:

  1.  

Duration: este atributo especifica cuánto tiempo se almacena un elemento en la caché. El valor de Duration se muestra en segundos.

  1.  

VaryByParam: este atributo determina las entradas de la caché con los parámetros Get o Post. Por ejemplo, si una variable QueryString denominada testVal se establece para el atributo VaryByParam, cada solicitud de página que contenga un valor diferente para testVal se almacena en caché en una página diferente. En el código siguiente se ilustra la sintaxis del atributo VaryByParam:

<%@ OutputCache Duration="Seconds" VaryByParam="testVal"%>
                                                

NOTA: puede especificar un asterisco (*) de modo que se almacenen en caché las diferentes versiones del elemento. Además, puede especificar "none" si sólo existe una versión de un elemento en la caché.

  1.  

Location: este atributo determina dónde se debe almacenar en caché el elemento. Puede especificar las ubicaciones siguientes:

  1.  

Any

  1.  

Client

  1.  

Downstream

  1.  

Server

  1.  

None

En el código siguiente se ilustra la sintaxis del atributo Location:

<%@ OutputCache Duration="Seconds" Location="Client" %>
                                        

  1.  

VaryByCustom: este atributo contiene el valor predeterminado Browser, que significa que se almacena en caché una instancia diferente de un elemento para cada versión del explorador que la solicite. Por ejemplo, tanto Microsoft Internet Explorer 5 como Internet Explorer 5.5 solicitan el elemento. Cuando VaryByCustom se establece en Browser, existe una entrada de la caché para cada versión del explorador. No puede proporcionar una cadena para controlar el almacenamiento en caché de otros escenarios personalizados. La cadena no tiene ningún significado a menos que proporcione código para invalidar el método HttpApplication.GetVaryByCustomString en el archivo Global.asax.

 

En el código siguiente se ilustra la sintaxis del atributo VaryByCustom:

<%@ OutputCache Duration="Seconds" VaryByCustom="string" %>
                                        

  1.  

VaryByHeader: este atributo permite especificar un valor de encabezado HTTP concreto como criterio para determinar diferentes entradas de la caché. En el código siguiente se ilustra la sintaxis del atributo VaryByHeader:

<%@ OutputCache Duration="60" VaryByHeader="Accept-Language" %>
                                        

Cuando use VaryByParam, tenga en cuenta que los cambios de la variable QueryString provocan entradas adicionales en la caché.

 

Tenga presente que Duration se especifica en segundos.

 

Cuando usa VaryByCustom y reemplaza el método HttpApplication.GetVaryByCustomString en el archivo Global.asax, se utiliza la configuración predeterminada de Browser si no se encuentra ninguna correspondencia para la cadena personalizada que se proporciona con el atributo.

Development

Arquitectura de aplicaciones AJAX

Cualquier administrador del sistema, diseñador o desarrollador, puede ver su trabajo afectado significativamente por AJAX. Los administradores tienen que asegurarse de que la el nivel de seguridad sea lo bastante alto como para afrontar los nuevos tipos de ataques posibles. Los administradores de la intranet tienen que garantizar que JavaScript no esté deshabilitado en ningún explorador. A los diseñadores web se les presentan nuevos desafíos que conseguir, ya que se encuentran con características que ahora son accesibles con AJAX que antes eran imposibles o impracticables. Y los desarrolladores disponen de una API nueva y una nueva perspectiva general de programación con la que familiarizarse. Dicho todo lo cual, ¿qué sentido tiene AJAX para los arquitectos?

Las aplicaciones de AJAX son un desafío porque introducen conceptos completamente nuevos y una base nueva. La función del arquitecto es esencial porque el paradigma de AJAX es un puente de unión entre los entornos de cliente y servidor. Tener una visión arquitectónica clara es vital para determinar qué lógica y procesamiento tienen lugar en el cliente y qué parte permanece en el servidor, así como qué objetos de datos pueden intercambiar el cliente y el servidor.

AJAX al rescate

Las Web se usó en un principio para compartir páginas estáticas de información. Durante los últimos años, evolucionó hacia un medio mucho más dinámico. Hoy, la web está compuesta por páginas muy interactivas; sin embargo, todavía depende mucho de un paradigma que se basa en la transición de páginas enteras. Cuanto más interactúa el usuario con una página, más frecuentemente deben crearse y servirse dichas páginas a su explorador. Hay muchas consecuencias negativas que se derivan de servir páginas interactivas de esta manera, como una actualización lenta de las páginas y el parpadeo. Se trata de una solución nada elegante que lleva con frecuencia a una experiencia de usuario pobre. AJAX implica un cambio muy deseado en este paradigma que permite obtener aplicaciones web más limpias y establecer la base para una generación nueva de aplicaciones. AJAX está realmente destinado al usuario final. Gracias a las características de AJAX, una aplicación web se vuelve mucho más interactiva y tiene mayor capacidad de respuesta. Es más rápida y fácil de usar. Se anima al usuario a hacer más cosas con la página, ya que la interacción y las respuestas (y la realimentación en el caso de operaciones lentas) se administran de un modo mucho más elegante. En términos generales, el usuario consigue tener una experiencia mucho mejor.

Con AJAX, se ejecuta más código en el explorador y esto requiere proporcionar más scripts a las páginas del cliente. Pero esto deja algunas preguntas importantes sin contestar. ¿Qué clase de script? ¿Quién escribirá este script? ¿Y a qué principios y pautas arquitectónicas se adherirá este script?

En esta columna, explicaré AJAX desde un punto de vista arquitectónico para ayudar a desarrolladores y arquitectos a hacer selecciones más reflexionadas. Al mismo tiempo, se dará a los diseñadores y administradores suficiente información de contexto para que puedan llevar a cabo sus trabajos con más facilidad. Al tratarse de un tema bastante importante, lo dividiremos en dos partes. No se pierda la columna del próximo mes, en la que vamos a continuar hablando de este tema.

La arquitectura de AJAX

Si está pensando en aplicar AJAX, vea la figura 1, que ilustra las implicaciones arquitectónicas del cambio. Una aplicación web tradicional realiza todas sus acciones en el servidor. Sólo ocasionalmente la aplicación es la que emite código de scripts para ejecutar una tarea en el cliente, por ejemplo, para administrar la validación de datos.

fig01
 

Una aplicación de AJAX usa un marco de cliente que se ocupa de emitir llamadas al servidor web. A continuación un marco de servidor de AJAX se preocupa de la solicitud y devuelve una alimentación de datos al cliente. Con frecuencia esto será una secuencia de datos de JavaScript Notation Object (JSON), pero pueden usarse otros formatos, como XML, RSS y CSV.

El cliente recibe alimentaciones de datos y actualiza la IU con JavaScript. El servidor responde a solicitudes devolviendo datos sin procesar y codificados en un formato concreto. El consumo del ancho de banda se minimiza, la velocidad de las aplicaciones aumenta debido a que las solicitudes tardan menos en completarse y las actualizaciones de IU pueden hacerse efectivas sin necesidad de ninguna devolución visible. Pero aunque esto resuelve muchos problemas, el aumento en la acción sobre el cliente genera también problemas nuevos, como prácticas nuevas de codificación, peligros nuevos de seguridad, problemas de accesibilidad, etcétera.

¿Qué es un marco de AJAX?

Para mantener AJAX activo en una página web deben cumplirse unas cuantas condiciones. En primer lugar, es necesario que el explorador sea compatible con JavaScript. También se requiere una conexión permanente a Internet, ya que las aplicaciones de AJAX no pueden funcionar sin conexión. Cuando se han hecho todas las solicitudes en el nivel de la página, igual que ocurre con aplicaciones que no son AJAX, el explorador puede ofrecer navegar por un conjunto de estas páginas en la memoria caché, y de esta forma se puede seguir trabajando sin conexión. Este mismo comportamiento tendría que codificarse explícitamente en el marco basado en el script que está asociado al explorador en una aplicación de AJAX. Se está trabajando mucho en esta área y se están desarrollando algunas nuevas herramientas de ayuda. La capacidad de usar aplicaciones AJAX sin conexión es un desafío para muchos proveedores de software.

Cualquier aplicación seria de AJAX requiere un marco especial. Generalmente, el marco elegido se articula en partes separadas para cliente y servidor.

Existen dos tipos principales de código de script en una página de AJAX: el código en el nivel del sistema del marco elegido y el código a nivel de usuario, que implementa el comportamiento previsto de la página. El código en el nivel del sistema proporciona el motor usado para enviar solicitudes asincrónicas al servidor web y así procesar cualquier respuesta. El código en el nivel de usuario actualiza la IU de la página, y lo hace usando esencialmente scripting de modelo de objetos del documento (DOM). Así que nos encontramos con una de las preguntas que mencionaba antes: ¿Quién escribe qué? Para tratar el tema, nos centraremos en un marco concreto de AJAX: las extensiones de AJAX de ASP.NET.

Extensiones de AJAX de ASP.NET

ASP.NET AJAX Extensions es una extensión de ASP.NET 2.0 que ofrece capacidades tanto a los sitios web nuevos como a los ya existentes. Hay dos modelos de programación para AJAX de ASP.NET: la representación parcial y los servicios remotos. Estos dos modelos suponen dos arquitecturas radicalmente diferentes en la aplicación y en consecuencia presentan diferentes pros y contras. (Probablemente ya se habrá visto que la mayoría de las características de AJAX conllevan tanto ventajas como desventajas).

En pocas palabras, la representación parcial permite mantener una arquitectura semejante a la de una aplicación clásica de ASP.NET 2.0. Simplemente ofrece un conjunto de herramientas nuevas de servidor que permiten implementar actualizaciones de página sin parpadeos.

Los servicios remotos, por otro lado, requieren un back-end orientado a servicios e invocado por un front-end de AJAX con un uso bastante profuso de scripts. Casi todos los procesos fundamentales de las aplicaciones, incluidas la autenticación, la paginación de datos y la clasificación, deben volver a diseñarse. Debe producirse código de servidor para los servicios específicos de la aplicación y debe también seleccionarse un formato (como, por ejemplo, JSON) para el intercambio de datos. Finalmente, debe organizarse un cliente y prestarse la atención requerida para limitar la codificación a tareas de nivel de IU y mantener la mayor parte de la lógica empresarial fuera del cliente.

El enfoque de los servicios remotos ofrece una experiencia AJAX más completa, mientras que la representación parcial ofrece una transición más fácil, con una mejora progresiva de las características de la aplicación existente.

Estos dos enfoques pueden combinarse hasta cierto punto. Por ejemplo, se puede mantener la misma arquitectura tradicional de web, agregar algunas actualizaciones sin parpadeos aquí y allá, y entonces tomarse tiempo para volver a producir algunas características claves orientadas a los servicios. Las extensiones de AJAX de ASP.NET proporcionan varios ingredientes claves, pero las partes más elementales de este trabajo para crear unas aplicaciones magníficas de AJAX todavía dependen de usted. La figura 2 muestra los componentes del cliente y del servidor del marco de ASP.NET AJAX Extensions.

Una ojeada a la representación parcial

La columna Código malvado de Jeff Prosise de junio de 2007 (msdn.microsoft.com/msdnmag/issues/07/06/WickedCode)
ofrece un excelente debate acerca de la representación parcial con AJAX
de ASP.NET. Desde un punto de vista arquitectónico, la representación
parcial no agrega nada nuevo. Se trata sólo de una manera interesante
de mejorar las aplicaciones heredadas con algunas capacidades de AJAX,
la más importante de las cuales es la actualización de páginas sin
parpadeos.

La representación parcial no requiere
aprender muchas técnicas nuevas y tiene un impacto muy limitado en el
código existente. También ofrece un mecanismo de reserva sencillo para
tratar aspectos de una aplicación que pueden verse afectados a raíz de
la adopción de AJAX, por ejemplo la seguridad y la accesibilidad.
Básicamente, si en el proceso de actualización surgen problemas al
convertir algunas partes del código existente a AJAX, simplemente se
pueden dejar los bloques de código tal y como estaban y seguir adelante.

Una
solicitud de representación parcial a menudo se conoce como una
devolución de AJAX. El término es bastante apropiado y representa
perfectamente lo que sucede en realidad. Una devolución de AJAX es como
una devolución clásica de ASP.NET, salvo porque la lleva a cabo una
parte de código de script definida en la biblioteca del cliente de AJAX
de ASP.NET. Aunque se presenta disfrazada como una llamada remota pura
de AJAX, una devolución de AJAX se parece a una solicitud regular de
devolución para los componentes del tiempo de ejecución de ASP.NET. Una
vez en el servidor, la solicitud pasa por el ciclo de vida habitual de
las solicitudes de devolución y origina eventos como Init, Load y
PreRender. En el servidor, una devolución de AJAX difiere de una
devolución clásica de ASP.NET sólo en el algoritmo que usa para
representar el marcado final. Este algoritmo diferente es clave para la
mejora del rendimiento y la ausencia de parpadeo en la página. Sin
embargo, el modelo de la aplicación sigue siendo el mismo que en
ASP.NET. La figura 3 muestra el ciclo de vida modificado de una solicitud de devolución de AJAX.

Todo es igual en las devoluciones de AJAX y de
ASP.NET, salvo en lo que se refiere a la implementación de la fase de
representación. Una devolución de AJAX todavía inicia eventos de
notificación como Load y PreRender, y aún procesa la información de
viewstate y activa eventos de estados cambiados y de devolución como
TextChanged y Click.

Una página de AJAX de
ASP.NET debe incluir una instancia del control ScriptManager. Este
control es el auténtico centro neurálgico de las páginas de AJAX de
ASP.NET. Se ocupa de vincular la página a cualquier archivo de script
del marco que sea necesario y organiza la representación parcial si
detecta que se está produciendo una devolución de AJAX. El control
ScriptManager comprueba si hay un encabezado HTTP en la solicitud para
determinar si se trata de una devolución de AJAX. Lo que viene a
continuación es un resumen del archivo MicrosoftAjaxWebForms.js que
establece el encabezado HTTP antes de activar la solicitud de AJAX:

   request.get_headers()['X-MicrosoftAjax'] = 
'Delta=true';

Para ver qué hace que el estadio de
representación sea diferente en una devolución de AJAX, observe más de
cerca el resumen siguiente del ensamblado System.Web.Extensions:

   protected override void OnPreRender(EventArgs e) {
base.OnPreRender(e);
if (IsInAsyncPostBack)
PageRequestManager.OnPreRender();
}

En concreto, el
fragmento de código que se mostraba anteriormente procede del control
ScriptManager. Como puede apreciarse, el director de scripts registra
un controlador de eventos de representación preliminar. Al iniciarse,
el controlador detecta si está comprometido con una devolución de AJAX
y, si es así, invoca un método desde la clase interna de
PageRequestManager. El método de OnPreRender de la clase
PageRequestManager hace lo siguiente:

   internal void OnPreRender()
{
_owner.SetRenderMethodDelegate(
new RenderMethod(this.RenderPageCallback));
}

Es bastante simple, el método establece
una subrutina específica para representar el marcado para la solicitud
actual. SetRenderMethodDelegate es un método definido en la clase
System.Web.UI.Control. Como no está destinado a un uso público, este
método asigna básicamente un controlador de eventos que la página o el
control usarán para representar su contenido. En el fragmento de código
anterior, se invoca al método en la página actual que acaba invalidando
todo el proceso de representación para la solicitud actual. El
verdadero código responsable del marcado de una devolución de AJAX se
define por lo tanto en el método RenderPageCallback, un método interno
de la clase PageRequestManager. (Para obtener más información sobre el
control de ScriptManager, consulte el artículo de Ben Rush sobre este
tema en MSDN® Magazine).

Básicamente
el proceso de representación modificado para una devolución de AJAX
establece bucles en todos los paneles de actualización de la página
implicados en la devolución y acumula el marcado de cada uno. Todos los
fragmentos del marcado, junto con campos ocultos y cualquier
información de errores, se empaquetan en una secuencia de respuestas y
se pasan al cliente. Diseccionemos ahora una llamada habitual de
representación parcial en el contexto de una página de muestra.

Puede usar diversas herramientas para supervisar
paquetes HTTP entrantes y salientes. Para esta columna, usé la
herramienta Web Development Helper de Nikhil Kothari, que puede
descargarse de forma gratuita en projects.nikhilk.net/Projects/WebDevHelper.aspx.La
respuesta de una devolución de AJAX es una secuencia de texto que puede
consultarse como una tabla de registros con las columnas Size, Type, ID
y Content. Cada registro se conoce como nodo delta.

Un nodo delta identifica un cambio posible sucedido
durante la devolución de AJAX. No todas las respuestas incluyen el
mismo conjunto de nodos delta; depende de lo que sucede durante el
ciclo de vida del servidor de la solicitud y la estructura del marcado
original.Técnicas de optimización para la representación parcial

Después de examinar la figura 6,
observará que la respuesta está compuesta por dos bloques grandes:
marcado y viewstate. Los datos de validación de eventos (una
característica relacionada con la seguridad de ASP.NET 2.0), los campos
ocultos personalizados, los scripts y otros tipos de nodos normalmente
ocupan unos cuantos bytes en total. El tamaño de viewstate es un viejo
problema que tienen las páginas de ASP.NET. Por desgracia, la
representación parcial con AJAX de ASP.NET, no hace nada para
corregirlo. Todavía necesitará mantener un viewstate eficaz y compacto
para poder mejorar el tiempo de descarga. Así que, ¿qué se puede hacer
para reducir el marcado de una página? Básicamente, se pueden tener
paneles más pequeños que devuelvan sólo la cantidad mínima de marcado
necesario para ese clic particular.

Observe de nuevo el código de la figura 4.
La lógica en la página es bastante sencilla, pero ilustra lo que
queremos decir. Básicamente, cuando el usuario hace clic en el botón,
se usa todo el contenido del TextBox para actualizar la etiqueta.

La
página sólo contiene un control UpdatePanel que lo incluye todo: cuadro
de texto, botón, separador y etiqueta. Hablando desde el punto de vista
de la lógica, esto puede ser aceptable. Si se desea identificar una
región de la página para actualizarla autónomamente, puede ser una
opción válida. Si embargo, si se define de este modo, la región
contiene una parte considerable de código que no se actualiza entre
devoluciones. Los controles TextBox y Button, por ejemplo, no se
actualizan en esta página, y el separador <hr> es un texto
estático sin formato.

Una mejor opción sería
reducir UpdatePanel para que sólo incluya el control Label, es decir,
el único control del servidor que se actualiza en cualquier devolución
activada por el botón. En general, deben identificarse con cuidado las
relaciones de las devoluciones entre los controles: examinar
básicamente cuál actualiza cuál y diseñar paneles que puedan
actualizarse para incluir un número mínimo de controles para una acción
determinada de un usuario. En el contexto del ejemplo que se muestra en
la figura 4, aquí hay un esquema mejor:

<asp:TextBox runat="server" ID="TextBox1" /> 
<asp:Button runat="server" ID="Button1" Text="Update"
OnClick="Button1_Click" />
<hr />
<asp:UpdatePanel runat="server" ID="UpdatePanel1">
<ContentTemplate>
<asp:Label runat="server" ID="Label1" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Button1" />
</Triggers>
</asp:UpdatePanel>

El control UpdatePanel ahora contiene
sólo el control Label. Esto significa que ningún marcado (sin
modificar) será devuelto para los controles textbox y button. De forma
predeterminada, un control UpdatePanel se actualiza cuando uno de sus
controles secundarios causa una devolución o se actualiza otro
UpdatePanel de la página. Este comportamiento puede alterarse con
algunas propiedades públicas, por ejemplo, UpdateMode,
ChildrenAsTriggers y Triggers.

En particular,
UpdateMode determina si UpdatePanel se establece para actualizar de
forma incondicional (el predeterminado) o sólo bajo ciertas
condiciones. Si desea realizar un actualización condicionada, es decir,
una configuración clave para optimizar los paneles que se van a
actualizar, empiece por establecer UpdateMode en Conditional:

<asp:UpdatePanel runat="server" ID="UpdatePanel1" 
UpdateMode="Conditional">

Observe que, sin embargo, las actualizaciones condicionadas son relevantes sólo si se tienen diversos paneles en una página.

Puede
que haya situaciones donde parezca difícil dividir una página en un
conjunto de paneles normalizados. Una técnica que podría ayudarle en
estos casos es evitar que los elementos secundarios activen
devoluciones. La propiedad ChildrenAsTriggers es una propiedad booleana
(establecida en verdadero de forma predeterminada) que determina si los
controles secundarios de un panel actúan como activadores de eventos de
devolución de AJAX. En el fragmento de código siguiente, el control
Button1 no hace que se actualice el panel:

<asp:UpdatePanel runat="server" ID="UpdatePanel1" 
ChildrenAsTriggers="false">
<ContentTemplate>
<asp:Button runat="server" ID="Button1" Text="Update"
OnClick="Button1_Click" />
<asp:Label runat="server" ID="Label1" />
</ContentTemplate>
</asp:UpdatePanel>

Al hacer clic en un
botón secundario de un panel configurado de esta forma, tiene lugar una
devolución de AJAX para ejecutar cualquier código de devolución adjunto
en el botón, por ejemplo, el método Button1_Click, pero no se devuelve
ningún marcado para actualizar el panel.

La
tercera propiedad implicada en la actualización condicionada es
Triggers. Se trata de una propiedad de recopilación y muestra los
eventos de control que ordenarán un actualización del panel, como ésta:

<asp:UpdatePanel runat="server" ID="UpdatePanel1">
<ContentTemplate>
<asp:Label runat="server" ID="Label1" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Button1"
EventName="Click" />
</Triggers>
</asp:UpdatePanel>

En este caso, el
evento Click de Button1 actualizará el panel. El control Button1 puede
colocarse en cualquier lugar de la página. Tenga en cuenta que estamos
hablando de eventos del servidor. Es decir, si se desea actualizar un
panel cuando el usuario cambia la selección en una lista desplegable,
debe agregarse primero el atributo AutoPostBack a la lista desplegable.

Todavía
puede configurar un panel para que se actualice cuando un evento de
estado cambiado tenga lugar en el servidor durante una devolución de
AJAX. Observe el siguiente código:

<asp:TextBox runat="server" ID="TextBox1" /> 
<asp:UpdatePanel runat="server" ID="UpdatePanel1">
<ContentTemplate>
<asp:Label runat="server" ID="Label1" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger
ControlID="TextBox1"
EventName="TextChanged" />
</Triggers>
</asp:UpdatePanel>

La etiqueta se actualiza siempre que el contenido TextBox1 cambia:

Sub TextBox1_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles TextBox1.TextChanged
Label1.Text = TextBox1.Text
End Sub

El evento
TextChanged, así como otros eventos de estado cambiado, son eventos del
servidor que se inician como resultado de una devolución. La página aún
necesita un botón, o un control de devolución automática, para activar
la devolución y así actualizar la etiqueta.

El gráfico de la figura 7
resume las posibles ventajas que pueden obtenerse de aplicar técnicas
de optimización a los paneles que pueden actualizarse. Mediante la
representación parcial, el tamaño del paquete de solicitudes aumenta
poco, pero incluso en el caso menos optimizado la respuesta que se
obtiene es más pequeña que la de una situación típica de ASP.NET. Y,
por supuesto, los usuarios no experimentan más parpadeos.

Debo advertir, sin embargo, que las páginas con un
viewstate grande quizás no se beneficien de la representación parcial.
Puede que ahorre 5 KB de marcado, pero no es mucho si tiene que cargar
con 30 KB de viewstate.

Pero a veces, viewstate
es sólo un cabeza de turco inocente de un problema que se originó en
otra parte. Supongamos que tiene un control de calendario en una página
de ASP.NET y se usan paneles que pueden actualizarse para mantener una
actualización sin conflictos:

<asp:UpdatePanel runat="server" ID="UpdatePanel1">
<ContentTemplate>
<asp:Calendar runat="server" ID="Calendar1" />
</ContentTemplate>
</asp:UpdatePanel>

El marcado para este fragmento no es
menor de 7 KB, y puede crecer hasta 10 KB si se agregan algunos
estilos. Ahora bien, si se desactiva el viewstate del calendario, se
ahorrará aproximadamente 1 KB de datos, que es sólo un 10 por ciento
del tamaño total. Esto es así porque Calendar es un control pesado en
términos de marcado. El viewstate tiene poco que ver con este problema.
Una página de ASP.NET AJAX no debería usar controles Calendar para las
funciones de selección de fechas. En vez de eso, AJAX Control Toolkit
ofrece un extensor, el control CalendarExtender, que, cuando se ha
agregado a un TextBox sin formato, permite seleccionar fechas,
ahorrando 10 KB de marcado.

Este código hace emerger un calendario siempre que el cuadro de texto recibe el foco de entrada:

<asp:textbox runat="server" ID="TextBox1" />
<act:CalendarExtender ID="CalendarExtender1" runat="server"
TargetControlID="TextBox1"
OnClientDateSelectionChanged="updateLabel"
Format="dd/MM/yyyy" />

<asp:UpdatePanel runat="server" ID="UpdatePanel1"
UpdateMode="Conditional">
<ContentTemplate>
<asp:label runat="server" ID="Label1" />
</ContentTemplate>
</asp:UpdatePanel>

El calendario se
crea completamente en el cliente y sólo requiere la descarga de un par
de iconos pequeños. El extensor escribe automáticamente la fecha
seleccionada en el TextBox complementario. Sin embargo, con un poco de
código de JavaScript, puede administrar el evento de la selección de
fechas de cliente y hacer cualquier cosa que necesite.

Compensación de la representación parcial

La
representación parcial es la manera más rápida de adornar un sitio web
de ASP.NET con capacidades de AJAX. No requiere ni habilidades nuevas
ni una arquitectura nueva. En vez de eso, se presta a mejorar
progresivamente un sitio web existente. Pero comparado con un enfoque
puro de AJAX (llamadas del cliente directo a los servicios remotos) la
representación parcial sufre penalizaciones considerables en su
rendimiento.

Como norma general, se recomienda la
representación parcial como el mejor enfoque para crear una primera
versión sólida de AJAX de un sitio. Progresivamente puede irse alejando
de la arquitectura clásica de ASP.NET y empezar a crear un conjunto de
servicios back-end y un nivel de presentación sólido. En la entrega
siguiente de Cutting Edge, exploraremos los servicios remotos
relacionados con AJAX. Es fantástico desde el punto de vista de la
arquitectura, pero puede requerir volver a diseñar completamente la
aplicación y origina unos cuantos problemas nuevos.

Development

Arquitectura de Aplicaciones de 3 capas

Tipos de componentes

El análisis de la mayoría de las soluciones empresariales basadas en modelos de componentes por capas muestra que existen varios tipos de componentes habituales. En la figura 2.1 se muestra una ilustración completa en la que se indican estos tipos de componentes.

Nota   El término componente hace referencia a una de las partes de la solución total, como los componentes de software compilado (por ejemplo, los ensamblados de Microsoft .NET) y otros elementos de software, como las páginas Web y los programas de Microsoft® BizTalk® Server Orchestration.

Aunque la lista que se muestra en la figura 2.1 no es completa, representa los tipos de componentes de software más comunes encontrados en la mayoría de las soluciones distribuidas. A lo largo de este capítulo describiremos en profundidad cada uno de estos tipos.

 

f02aa01

Los tipos de componentes identificados en el escenario de diseño de ejemplo son:

  1. Componentes de interfaz de usuario (IU). La mayor parte de las soluciones necesitan ofrecer al usuario un modo de interactuar con la aplicación. En el ejemplo de aplicación comercial, un sitio Web permite al cliente ver productos y realizar pedidos, y una aplicación basada en el entorno operativo Microsoft Windows® permite a los representantes de ventas escribir los datos de los pedidos de los clientes que han telefoneado a la empresa. Las interfaces de usuario se implementan utilizando formularios de Windows Forms, páginas Microsoft ASP.NET, controles u otro tipo de tecnología que permita procesar y dar formato a los datos de los usuarios, así como adquirir y validar los datos entrantes procedentes de éstos.
  2. Componentes de proceso de usuario. En un gran número de casos, la interactuación del usuario con el sistema se realiza de acuerdo a un proceso predecible. Por ejemplo, en la aplicación comercial, podríamos implementar un procedimiento que permita ver los datos del producto. De este modo, el usuario puede seleccionar una categoría de una lista de categorías de productos disponibles y, a continuación, elegir uno de los productos de la categoría seleccionada para ver los detalles correspondientes. Del mismo modo, cuando el usuario realiza una compra, la interactuación sigue un proceso predecible de recolección de datos por parte del usuario, por el cual éste en primer lugar proporciona los detalles de los productos que desea adquirir, a continuación los detalles de pago y, por último, la información para el envío. Para facilitar la sincronización y organización de las interactuaciones con el usuario, resulta útil utilizar componentes de proceso de usuario individuales. De este modo, el flujo del proceso y la lógica de administración de estado no se incluye en el código de los elementos de la interfaz de usuario, por lo que varias interfaces podrán utilizar el mismo "motor" de interactuación básica.
  3. Flujos de trabajo empresariales. Una vez que el proceso de usuario ha recopilado los datos necesarios, éstos se pueden utilizar para realizar un proceso empresarial. Por ejemplo, tras enviar los detalles del producto, el pago y el envío a la aplicación comercial, puede comenzar el proceso de cobro del pago y preparación del envío. Gran parte de los procesos empresariales conllevan la realización de varios pasos, los cuales se deben organizar y llevar a acabo en un orden determinado. Por ejemplo, el sistema empresarial necesita calcular el valor total del pedido, validar la información de la tarjeta de crédito, procesar el pago de la misma y preparar el envío del producto. El tiempo que este proceso puede tardar en completarse es indeterminado, por lo que sería preciso administrar las tareas necesarias, así como los datos requeridos para llevarlas a cabo. Los flujos de trabajo empresariales definen y coordinan los procesos empresariales de varios pasos de ejecución larga y se pueden implementar utilizando herramientas de administración de procesos empresariales, como BizTalk Server Orchestration.
  4. Componentes empresariales. Independientemente de si el proceso empresarial consta de un único paso o de un flujo de trabajo organizado, la aplicación requerirá probablemente el uso de componentes que implementen reglas empresariales y realicen tareas empresariales. Por ejemplo, en la aplicación comercial, deberá implementar una funcionalidad que calcule el precio total del pedido y agregue el costo adicional correspondiente por el envío del mismo. Los componentes empresariales implementan la lógica empresarial de la aplicación.
  5. Agentes de servicios. Cuando un componente empresarial requiere el uso de la funcionalidad proporcionada por un servicio externo, tal vez sea necesario hacer uso de código para administrar la semántica de la comunicación con dicho servicio. Por ejemplo, los componentes empresariales de la aplicación comercial descrita anteriormente podría utilizar un agente de servicios para administrar la comunicación con el servicio de autorización de tarjetas de crédito y utilizar un segundo agente de servicios para controlar las conversaciones con el servicio de mensajería. Los agentes de servicios permiten aislar las idiosincrasias de las llamadas a varios servicios desde la aplicación y pueden proporcionar servicios adicionales, como la asignación básica del formato de los datos que expone el servicio al formato que requiere la aplicación.
  6. Interfaces de servicios. Para exponer lógica empresarial como un servicio, es necesario crear interfaces de servicios que admitan los contratos de comunicación (comunicación basada en mensajes, formatos, protocolos, seguridad y excepciones, entre otros) que requieren los clientes. Por ejemplo, el servicio de autorización de tarjetas de crédito debe exponer una interfaz de servicios que describa la funcionalidad que ofrece el servicio, así como la semántica de comunicación requerida para llamar al mismo. Las interfaces de servicios también se denominan fachadas empresariales.
  7. Componentes lógicos de acceso a datos. La mayoría de las aplicaciones y servicios necesitan obtener acceso a un almacén de datos en un momento determinado del proceso empresarial. Por ejemplo, la aplicación empresarial necesita recuperar los datos de los productos de una base de datos para mostrar al usuario los detalles de los mismos, así como insertar dicha información en la base de datos cuando un usuario realiza un pedido. Por tanto, es razonable abstraer la lógica necesaria para obtener acceso a los datos en un capa independiente de componentes lógicos de acceso a datos, ya que de este modo se centraliza la funcionalidad de acceso a datos y se facilita la configuración y el mantenimiento de la misma.
  8. Componentes de entidad empresarial. La mayoría de la aplicaciones requieren el paso de datos entre distintos componentes. Por ejemplo, en la aplicación comercial es necesario pasar una lista de productos de los componentes lógicos de acceso a datos a los componentes de la interfaz de usuario para que éste pueda visualizar dicha lista. Los datos se utilizan para representar entidades empresariales del mundo real, como productos o pedidos. Las entidades empresariales que se utilizan de forma interna en la aplicación suelen ser estructuras de datos, como conjuntos de datos, DataReader o secuencias de lenguaje de marcado extensible (XML), aunque también se pueden implementar utilizando clases orientadas a objetos personalizadas que representan entidades del mundo real necesarias para la aplicación, como productos o pedidos.

Componentes de seguridad, administración operativa y comunicación. La aplicación probablemente utilice también componentes para realizar la administración de excepciones, autorizar a los usuarios a que realicen tareas determinadas y comunicarse con otros servicios y aplicaciones.