Cuestiones sobre ASP.NET

Transcripción

Cuestiones sobre ASP.NET
dnm.todotnet.qa
Dino Esposito
Cuestiones sobre ASP.NET
Este mes responderemos algunas preguntas relacionadas con el desarrollo Web y
ASP.NET en particular. Las cuestiones abordan temas que van desde la importación
de datos de fuentes externas y sitios Web,hasta tareas asíncronas y la representación
de imágenes almacenadas en bases de datos.
Dino Esposito
es mentor de Solid Quality
Learning y autor de “Programming
Microsoft ASP.NET 2.0 Core
Reference” y “Programming
ASP.NET 2.0 Applicatinos Advanced
Topics”, ambos de Microsoft
Press.Afincado en Italia, Dino es
un ponente habitual en los
eventos de la industria a nivel
mundial.Visita su blog en:
http://weblogs.asp.net/despos.
Puede enviarle sus consultas a
[email protected]
tran información actualizable desde otros sitios: por
ejemplo noticias deportivas. No creo que ninguno de
mis clientes realmente quisiera tal tipo de servicio pero
sí que pienso que la importación de datos externos desde otros sitios Web sería una poderosa característica
a considerar.
Hasta donde yo sé, hay dos formas típicas de
implementar algo similar. Una consiste en utilizar un
servicio Web para obtener cualquier información
contractual expuesta por el sitio. Esto significa, sobre
todo, algún tipo de acuerdo entre las dos partes.
Cuanta más información valiosa, más tendrás que
pagar por ella, probablemente. Desde un punto de
vista tecnológico, simplemente se accede a la información de entrada (normalmente, cadenas), y la muestras en la forma adecuada. El segundo enfoque, supone suscribirse a algún origen de datos RSS. Es un
sitio que expone información publicable y la hace disponible, virtualmente a cualquier cliente, gratis. En
este caso, abres un socket hacia el destino RSS, obtienes la información –una cadena XML– y la incorporas en tus páginas.
En ambos casos, un acuerdo implícito o explícito existe entre tu sitio y el del origen de la información. Pero, para decirlo todo, existe un tercer
enfoque: el clásico Screen-scrapping. Aunque nacida
históricamente en mainframes hace 25 años, la técnica recobró actualidad con el advenimiento de las
páginas Web. Consiste en la posibilidad de descargar una página completa y analizarla para extraer la
información válida. Por ejemplo, se puede descargar una página de cotizaciones de bolsa, y mostrar
solo aquellas en las que estás interesado. Se analizan los contenidos eliminando todo menos los 3 ó
4 valores a buscar.
“
Para leer orígenes RSS, se utilizan
típicamente herramientas como
RssBandit o SharpReader. ¿Cómo
podrías leer uno de estos orígenes
en una página ASP.NET? Lo que
muchos sitios Web hacen es utilizar
un control de usuario compuesto
Si el sitio Web de origen no tiene una oferta RSS,
ésta sería mi opción predilecta. Screen-scrapping debería considerarse únicamente como último recurso.
Para leer orígenes RSS, se utilizan típicamente herramientas como RssBandit o SharpReader. ¿Cómo
podrías leer uno de estos orígenes en una página
ASP.NET? Lo que muchos sitios Web hacen (incluyendo las páginas MSDN) es utilizar un control de
usuario compuesto. La clave de este control, contendría un código similar al del fuente 1.
La variable text contiene la salida del origen en
formato XML. El contenedor ProcessFeed recorre
los elementos XML y construye un texto imprimible en HTML. Si seleccionamos una aproximación
más elegante, podríamos devolver un array de objetos personalizados a partir de ProcessFeed que solamente almacenaran líneas individuales para ser transformadas en lenguaje de marcas posteriormente. El
código del fuente 2 muestra cómo construir una lista de enlaces a los últimos “posts”.
”
<<dotNetManía
<< Algunos de los sitios Web que visito regularmente mues-
49
<< dnm.laboratorio.net
“
WebRequest req;
string rssData = String.Empty;
req = WebRequest.Create(RSSFEED);
using (WebResponse response = req.GetResponse())
{
StreamReader reader;
string text = String.Empty;
using (reader = new
StreamReader(response.GetResponseStream()))
{
text = reader.ReadToEnd();
}
Cualquier operación puede ser
fácilmente catalogada en dos formas:vinculada a la CPU o a un
proceso de entrada/salida
// Process the RSS data
rssData = ProcessFeed(text);
}
Fuente 1
string ProcessFeed(string feed)
{
StringBuilder sb = new StringBuilder();
XmlDocument doc = new XmlDocument();
doc.LoadXml(feed);
XPathNavigator nav = doc.CreateNavigator();
XPathNodeIterator iterator;
// Title and description
iterator = nav.Select(“/rss/channel/title”);
iterator.MoveNext();
sb.AppendFormat(“<h3>{0}</h3>”,iterator.Current.Value);
iterator = nav.Select(“/rss/channel/description”);
iterator.MoveNext();
sb.AppendFormat(“<i>{0}</i>”, iterator.Current.Value);
XmlNodeList items=doc.SelectNodes(“/rss/channel/item”);
sb.Append(“<ul>”);
foreach(XmlNode n in items)
{
XmlNode title = n.SelectSingleNode(“title”);
XmlNode link = n.SelectSingleNode(“link”);
XmlNode date = n.SelectSingleNode(“pubDate”);
sb.AppendFormat(“<li><a href=\”{0}\”>{1}</a> on {2}</li>”,
link.InnerText, title.InnerText, date.InnerText);
}
sb.Append(“</ul>”);
return sb.ToString();
}
<<dotNetManía
Fuente 2
50
Este código puede ser fácilmente incorporado en
un control de usuario compuesto hecho a partir de
una tabla o rejilla.
He construido varias soluciones utilizando tareas
asíncronas, pero reconozco que no he prestado demasiada atención al término I/O bound (vínculo).
¿Significa esto que cualquier operación asíncrona no
estrictamente relacionada con entrada/salida es perniciosa?
Cualquier operación puede ser fácilmente catalogada en dos formas: vinculada a la CPU o a un
proceso de entrada/salida. En el primer caso, el
tiempo de compleción está determinado por las
características de la propia CPU y la memoria disponible. En el otro, la situación es radicalmente
distinta, y la CPU espera –la mayor parte del tiempo– a que los dispositivos de entrada/salida terminen su trabajo.
Ahora bien, ¿cuál es el objetivo último de un proceso asíncrono? Un empleo típico es cuando necesitamos que nuestra interfaz de usuario no se “congele” mientras termina algún proceso en background, de
larga duración potencial. En este sentido, no hay ninguna diferencia importante entre los dos tipos de operaciones. Esto es correcto en tanto que estemos considerando escenarios de “clientes ricos”, como aplicaciones Windows Forms. Para aplicaciones
ASP.NET las cosas son algo distintas. Si has escrito
ese código para aplicaciones Windows no debe de
haber problema.
¿Qué operaciones son buenos candidatos a implementarse como páginas Web asíncronas? Para decirlo en otra forma, ¿qué operaciones requieren, o al
menos, sugieren claramente la adopción de páginas
asíncronas en una aplicación ASP.NET? Intentemos
formalizar brevemente el concepto de proceso asíncrono dentro del contexto de ASP.NET.
“
La necesidad del proceso
asíncrono deriva de un
tiempo excesivo en el
tráfico de la información de
entrada/salida, respecto
del tiempo de proceso.
”
”
“
cualquiera que sea el origen de la
imagen a mostrar, sólo puede
incluirse en una página a través
del elemento <img> y, por
consiguiente, vía URL
”
teriores releases y en la versión final. Sin embargo, el
problema que me condujo a esa situación al principio
no desaparece. ¿Cómo puedo construir mi propio control de imagen dinámico en ASP.NET 2.0?
En ASP.NET, dispones de dos controles de servidor para mostrar imágenes: Image y HtmlImage. Ambos
controles suministran un ligero nivel de abstracción
sobre algunas de las propiedades del elemento <img>
de HTML. Ambos controles, en definitiva, solo permiten referenciar imágenes vía URL, y establecer
algunos atributos de presentación.
Como sugieres, en el mundo real, los gráficos pueden venir de una gran variedad de orígenes. Por ejemplo, pueden provenir de un fichero, se pueden leer a
partir de un campo de una base de datos, o se pueden
generar dinámicamente en memoria utilizando una
API gráfica. Solo en el primer caso –el del fichero en
disco– podemos aplicar adecuadamente el elemento
<img> y el API de ASP.NET. En todos los otros casos,
los programadores deben escribir su propio código
para conseguirlo. Veamos cómo.
El hecho es que, cualquiera que sea el origen de
la imagen a mostrar, sólo puede incluirse en una página a través del elemento <img> y, por consiguiente, vía
URL. Toda la lógica empleada para obtener la imagen, debe de ser embebida en código accesible a través de una URL. En ASP.NET, la URL puede apuntar a un manejador HTTP personalizado. El control
DynamicImage, de hecho, se apoya en el manejador
cacheimageservice.axd, un manejador incrustado que
ha sido liberado de la plataforma en alguna manera.
En ASP.NET 2.0, comienzas por crear un manejador análogo HTTP y diseñarle para aceptar en la
cadena de consulta cualquier información que pueda
ser útil para identificar la imagen y su origen. El viejo control DynamicImage encapsulaba mucha de esta
información (cadenas de conexión, consultas, ID) en
sus propios parámetros, aislando, por tanto, el manejador HTTP subyacente del desarrollador. Este manejador ejecutará cualquier código necesario para obtener los bytes de la imagen, establecer el tipo MIME
apropiado y devolver los bytes. Para evitar consultas
repetitivas y algunos ciclos de CPU, el manejador
HTTP puede almacenar imágenes en el caché y acceder a ellas la próxima vez que se necesiten.
Traducción por Marino Posadas
<<dotNetManía
La necesidad del proceso asíncrono deriva de un
tiempo excesivo en el tráfico de la información de
entrada/salida, respecto del tiempo de proceso. En
tales situaciones, la CPU está en estado de espera o
es infrautilizada la mayor parte del tiempo, esperando que algo suceda. Y en particular, en las operaciones de entrada/salida en el contexto de ASP.NET, porque los subprocesos en servicio están bloqueados también y el pool de servicio de subprocesos es un recurso finito y crítico.
Se obtienen mejoras en el rendimiento si se utilizan modelos asíncronos en operaciones de
entrada/salida. En la implementación de .NET
Framework, cuando se hace una llamada asíncrona
no existen subprocesos bloqueados mientras la operación está pendiente.
Ejemplos típicos de operaciones de entrada/salida son todas las operaciones que requieren acceso a
algún tipo de recurso remoto o que interaccionan
con dispositivos hardware externos. Las operaciones
sobre bases de datos o servicios Web no locales, son
las más comunes para considerar la creación de páginas asíncronas.
En ASP.NET, las operaciones de larga duración
de CPU (por ejemplo, algún algoritmo que requiera
actuar sobre datos en memoria) son también buenas
candidatas a una implementación asíncrona para mantener en número de subprocesos administrados en un
nivel suficientemente alto. En este caso, sin embargo, todavía está recargada con algo de trabajo, y la
ganancia de rendimiento es menor que en las operaciones de entrada/salida.
En suma, cualquier tarea de larga duración debería de ser llamada de forma asíncrona, tanto en
Windows como en ASP.NET. En este último caso,
sin embargo, es particularmente importante en los
procesos de entrada/salida. Si uno de estos procesos
(por ejemplo, la llamada a un servicio Web), es implementado de forma asíncrona, la CPU del servidor no
se ve afectada, y puede procesar con prontitud otras
peticiones. Para operaciones vinculadas a la CPU,
también las llamadas asíncronas pueden ofrecer algo
de mejora en Windows, al ejecutarse en un subproceso diferente. Para aplicaciones ASP.NET, sin embargo, no debieran esperarse grandes mejoras. Siempre
es mejor la llamada asíncrona pero las páginas se mostrarán lentamente, ya que la CPU tiene que realizar
un gran trabajo para generarlas. Una aproximación
más eficaz sería separar las operaciones de larga duración a un servidor remoto y transformar la tarea tipo
CPU en una del tipo entrada/salida.
En los primeros días de ASP.NET 2.0 –trabajo
con ella desde las primeras versiones alpha, en verano de 2003– podía referenciar fácilmente imágenes
almacenadas en una base de datos SQL Server usando control a medida –el control <asp_
DynamicImage>–. Este control, fue eliminado en pos-
[email protected] [email protected]
<< dnm.laboratorio.net
51

Documentos relacionados