
05/01/2008 06:55 por
zorry
En el proyecto en el que trabajo actualmente, tenemos que probar cómo se comporta la aplicación web bajo carga de muchos usuarios. Para realizar la carga, empleo Visual Studio 2005 Team Suite.
En una primera aproximación para realizar las pruebas de carga, realicé una captura web mediante la herramienta nativa de Visual Studio. En principio funciona bien, captura las peticiones http a la aplicación, pero como nuestra aplicación funciona con Ajax, las peticiones que realiza la aplicación de manera asíncrona mediante Javascript no son capturadas, con lo que las pruebas no son completas.
La solución que he encontrado ha sido emplear Fiddler para capturar el tráfico. Se arranca esta herramienta de captura antes de arrancar la aplicación web, se realiza la prueba de navegación desde un navegador, y posteriormente, Fiddler permite salvar todo el tráfico entre nuestro navegador y la aplicación web (incluido Ajax) como prueba de Visual Studio.
Posteriormente, este archivo webtest puede importarse en un proyecto de pruebas de Visual Studio 2005 Team suite para realizar las pruebas de carga.
51acd91e-f777-40f4-a0a7-fe91b2742ca8|0|.0

29/12/2007 08:12 por
zorry
Revisando el fix que hice ayer, y debido sobre todo a que no me gusta hacer modificaciones en librerías que no dependen de mí (sobre todo, para evitar que en una nueva release del AjaxControlToolkit me machaquen los cambios), me he fijado en una propiedad del ToolkitScriptManager denominada CombineScriptsHandlerUrl. Esta propiedad permite especificar un handler específico para manejar la combinación de todos los script del AjaxControlToolkit. De modo que me dispongo a deshacer los cambios que hice ayer, y hago varios cambios en mi aplicación web:
- En la definición del ToolkitScriptManager, he incluído el siguiente atributo: CombineScriptsHandlerUrl="~/CombineScriptsHandler.ashx"
- He creado un nuevo handler en la aplicación con el nombre definido en el nombre anterior. En el archivo ashx he introducido el siguiente código:
1: <%@ WebHandler Language="C#" Class="CombineScriptsHandler" %>
2:
3: using System;
4: using System.Web;
5: using AjaxControlToolkit;
6:
7: public class CombineScriptsHandler : IHttpHandler
8: {
9: /// <summary>
10: /// ProcessRequest implementation outputs the combined script file
11: /// </summary>
12: /// <param name="context"></param>
13: public void ProcessRequest(HttpContext context)
14: {
15: if (!ToolkitScriptManager.OutputCombinedScriptFile(context))
16: {
17: throw new InvalidOperationException("Combined script file output failed unexpectedly.");
18: }
19: }
20:
21: /// <summary>
22: /// IsReusable implementation returns true since this class is stateless
23: /// </summary>
24: public bool IsReusable
25: {
26: get { return true; }
27: }
28: }
29:
Con estos cambios por fin he conseguido que la aplicación funcione correctamente en modo cookieless, y sin los problemas de javascript que me estaba encontrando anteriormente.
82354f83-f178-464d-8e98-09ec589bb2f2|0|.0

28/12/2007 15:12 por
zorry
Ok, por fin tengo mi aplicación funcionando en modo cookieless (para que funcione ciertas cosas de la aplicación que la consume). Instalo la última version del AjaxControlToolkit, configuro el tag ToolkitScriptManager correctamente, y pongo el tag CombineScripts a true, para que me combine todos los scripts generados por el toolkit en uno sólo.
Y al cargar la página, me pierde la sesión, en las trazas de IIS, veo que se está llamando a mi página inicial con otro SessionID, con lo que me da un error al cargar los scripts y la página no funciona...
En concreto el problema es que trata de cargar el script sin poner delante el SessionID:
/WebApp/Resumen.aspx?_TSM_HiddenField_=ctl00_scriptManager_HiddenField&_TSM_CombinedScripts_=%3b%3bAjaxControlToolkit%2c+Version%3d1.0.11119.32029%2c+Culture%3dneutral%2c+PublicKeyToken%3d28f01b0e84b6d53e%3aes-ES%3a2d550902-56f7-46bd-9795-b930029c9f3f%3ae2e86ef9%3a9ea3f0e2%3a9e8e87e9%3a1df13a87%3a80f47b59%3ad7738de7
Tenemos que lograr que el AjaxControlToolkit renderice la siguiente llamada para asegurarnos que no se pierde la sesión:
/WebApp/(S(w4fcmx45goyog355ydy4rw3w))/Resumen.aspx?_TSM_HiddenField_=ctl00_scriptManager_HiddenField&_TSM_CombinedScripts_=%3b%3bAjaxControlToolkit%2c+Version%3d1.0.11119.33116%2c+Culture%3dneutral%2c+PublicKeyToken%3d28f01b0e84b6d53e%3aes-ES%3af5528113-d4f3-4bcc-99aa-dc1a40d76a47%3ae2e86ef9%3a9ea3f0e2%3a9e8e87e9%3a1df13a87%3a80f47b59%3ad7738de7
Para ello, abrimos el código del AjaxControlToolkit... En concreto tocamos en la clase ToolkitScriptManager.cs... (Tengamos en cuenta que estoy trabajando con la release del 19 de Noviembre de 2007). La línea a modificar es la 144, y la reemplazaremos dejando el siguiente código:
144: _combinedScriptUrl = String.Format(CultureInfo.InvariantCulture,
145: "{0}?{1}={2}&{3}={4}", ((null != _combineScriptsHandlerUrl) ? _combineScriptsHandlerUrl.ToString()
146: : (new Uri(Page.Request.Url, Page.Request.RawUrl)).AbsolutePath)
147: , HiddenFieldParamName, HiddenFieldName, CombinedScriptsParamName,
148: HttpUtility.UrlEncode(SerializeScriptEntries(_scriptEntries, false)));
El código modificado se encuentra en la línea 146. De esta manera, se parsea la Url de la petición haciendo que se solicite la Url del script con el id de sesión, funcionando así correctamente la llamada Cookieless.
b3b7c0b1-e88d-463b-be94-01fe639b59ee|0|.0

03/06/2007 19:06 por
zorry
Bueno, tras una gran pausa, sigamos con este pequeño tutorial acerca de cómo usar las extensiones Ajax en .Net.
Partimos de una versión modificada de la demo del artículo anterior. Recordemos que en el artículo anterior vimos como realizar actualizaciones parciales de la página mediante el control UpdatePanel, evitando realizar postbacks completos del cliente al servidor, evitando el redibujado completo del navegador en cada cambio de la página.
En esta demo, en lugar de realizar la carga de un DropDownList desde otro, lo que hacemos es realizar la carga de un GridView dependiendo de la selección desde un DropDownList:
Lo que ocurrirá es que el usuario no sabrá si debe esperar para trabajar con la página, si la carga del grid inferior tarda más de lo normal (por ejemplo, si la base de datos está sobrecargada, o la consulta es compleja o trae muchos datos). Para ello, emplearemos el control UpdateProgress que nos facilita las extensiones Ajax. Para ello, en la página maestra, introduciremos el siguiente código:
<asp:UpdateProgress ID="UpdateProgress1" runat="server" >
<ProgressTemplate>
<div class="progress">
<asp:Image ID="Image1" runat="server"
ImageUrl="~/images/indicator_mozilla_blu.gif"/>
Actualizando página
</div>
</ProgressTemplate>
</asp:UpdateProgress>
Mediante este control, conseguimos que el HTML que está dentro del ProgressTemplate se muestre cuando las extensiones Ajax detecten que hay una llamada asíncrona al servidor. Dentro del template se puede poner cualquier código HTML ya que en cliente se renderiza con un DIV oculto. En este caso, estoy mostrando un DIV con una imagen animada y un texto indicando al usuario que la página se está actualizando. Este DIV tira de una clase llamada progress, que contiene cualquier decoración CSS que se nos ocurra. En nuestro caso, quería que se mostrara sobre los controles que están siendo actualizados, por lo que la clase progress queda en el ejemplo asi:
.progress
{
border-right: #ff6633 thin solid;
border-top: #ff6633 thin solid;
vertical-align: middle;
border-left: #ff6633 thin solid;
border-bottom: #ff6633 thin solid;
position: absolute;
background-color: #ffcc66;
text-align: center;
padding: 10px;
left: 100px; top: 100px;
}
Tras aplicar esto, y cambiar de selección en el DropDownList, podremos ver el siguiente efecto:
Esto es todo, hasta la siguiente entrega del tutorial.
f7a21ad3-47d5-42eb-8dba-be6c73120a94|0|.0

26/03/2007 05:03 por
zorry
A continuación veremos un primer ejemplo de implementación mediante el framework de Microsoft de AJAX. Para verlo, crearemos un "ASP.NET AJAX-Enabled website" en Visual Studio 2005, y lo denominaremos Ejemplo. Esta plantilla de Visual Studio nos generará un sitio Web, con un archivo Web.config con las modificaciones necesarias para que Ajax.Net funcione correctamente, así como una página default.aspx, la cual incluirá una referencia al control ScriptManager. Recordemos que en el artículo anterior vimos que el ScriptManager es el control necesario para que Ajax.pueda funcionar.
Incluimos el control ScriptManager
Es necesario incluir un control ScriptManager en cada página que vaya a emplear AJAX. En caso de una aplicación que emplee páginas maestras, lo ideal es incluirlo en la página maestra, evitando de esta manera tener que incluirlo en todas las páginas.
Eliminaremos la página default.aspx de la solución, y crearemos una página maestra denominada "master.master". Dentro de esta página, justo encima del control ContentPlaceHolder, incluiremos la siguiente línea:
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true" />
Es importante especificar el atributo EnablePartialRendering, ya que es el que nos permitirá realizar modificaciones parciales de las páginas.
Empleamos el control UpdatePanel
Crearemos una página que emplee la página maestra que acabamos de crear, añadimos una "Web Content Form" llamada "default.aspx". Dentro de ésta página, vamos a crear dos controles DropDownList encadenados, de manera que cuando seleccionemos un valor del primero, cargue los valores del segundo. Para ello, empleamos el siguiente código, dentro de la página:
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<asp:DropDownList ID="ddl" runat="server" AutoPostBack="true" OnSelectedIndexChanged="ddl_SelectedIndexChange">
<asp:ListItem Text="Email" Value="1" />
<asp:ListItem Text="Telefono" Value="2" />
</asp:DropDownList>
<asp:UpdatePanel ID="updatePanel" runat="server">
<ContentTemplate>
<asp:DropDownList ID="ddl2" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
</asp:Content>
Adicionalmente, en el archivo default.aspx.cs incluiremos el siguiente código:
protected void ddl_SelectedIndexChange(object sender, EventArgs e)
{
ddl2.Items.Clear();
if (ddl.SelectedValue == "1")
{
ddl2.Items.Add(new ListItem("Valor 1", "1"));
ddl2.Items.Add(new ListItem("Valor 2", "2"));
}
else
{
ddl2.Items.Add(new ListItem("Valor 3", "3"));
ddl2.Items.Add(new ListItem("Valor 4", "4"));
}
}
De esta manera podremos ver cómo, al seleccionar un valor en el desplegable, el segundo desplegable cambia de valor. Pero en este caso, la actualización se está haciendo mediante un postback completo, en lugar de emplear Ajax para redibujar el segundo desplegable. Esto es así, porque el UpdatePanel no sabe que tiene que redibujarse al cambiar el primer desplegable (el primer desplegable está fuera del UpdatePanel). Para modificar la página y conseguir que se emplee Ajax, existen dos posibilidades:
- Introducir el primer desplegable dentro del UpdatePanel. De esta manera el UpdatePanel realizará las llamadas por Ajax a todos los eventos de servidor que se produzcan en su interior.
- Modificar el UpdatePanel, introduciendo un trigger configuranod el UpdatePanel para que "escuche" los eventos realizados por el desplegable. Ésta es la mejor manera desde mi punto de vista, puesto que para que las recargas sean óptimas, los UpdatePanel deberían ser lo más pequeños posibles.
Por tanto, la solución sería la siguiente, modificar el UpdatePanel introduciendo este código (antes o después del tag ContentTemplate):
<Triggers>
<asp:AsyncPostBackTrigger ControlID="ddl" EventName="SelectedIndexChanged" />
</Triggers>
1324c9e6-a239-48d6-a710-611b36fb4e94|0|.0