Welcome to Comunidad .NET de Cd. Juárez Sign in | Join | Help

Preguntas de los lectores: DataSets y Web Services

Esta pregunta me llegó por e-mail y la respuesta acabó tan larga que mejor la pongo como una entrada:

De antemano te digo que tu blog es muy interesante y se entienden todas las cosas que has puesto... ahora bien tengo una duda que puede sonar un poco tonta pero aqui va...
En cuanto a los xml de los web services en visual studio un dataset que se envia por un web services es convertido a xml para viajar por el HTTP asi que lo puedo dejar de esa manera para que otra aplicacion lo recoja como un xml????
en el caso de que no... al serializar el objeto DataSet obtengo, eso si en la vista del browser un tag String y dentro de ella todo el codigo del xml, evidentemente eso no es lo que se ocupa o si??
Bueno disculpa por las preguntas pero me interesan demasiado las respuestas.... de antemano muchas gracias!!!

—Luis Mario Carvajal

Primero que nada, gracias Luis.  Se siente muy padre que las personas encuentren algo que escribes útil.

Segundo, las preguntas que haces son bien interesantes.  La respuesta a la primera es, sí, un DataSet se serializaría a XML—al tratarse de servicios Web todos los tipos son serializados a XML, porque en escencia estamos hablando de XML sobre HTTP, como tú lo mencionaste.

Sin embargo, no se recomienda utilizar un DataSet para pasar datos, ya que es un objeto bastante complejo: tiene muchas colecciones (DataTables, DataRelations, etc.), y cada una de ellas, a su vez tiene colecciones (un DataTable tiene una colección de DataRows, etc.).  Así que al serializar el grafo de todos eso objetos, acabas con mucho overhead, mucho XML complejo para transmitir solo unos cuantos datos. Y, aunque en teoría sí podrías consumir eso de otra aplicación—dependiendo si estas usando ASP.NET Web Services o WCF, ya que utilizan serializadores distintos—no es muy interoperable con otras plataformas. 

A pesar de estas recomendaciones, debo mencionar que si el consumidor de tu servicio usa .NET, no debe tener problemas para consumir ese DataSet como un objeto de .NET, ya que el generador de la clase proxy que viene con Visual Studio utiliza unos artilugios para des-serializar el DataSet apropiadamente.

Ahora, que si lo que te interesa solo es extraer los datos del DataSet en formato XML, una manera muy sencilla de hacerlo—y mucho mejor que hacer ToString(), creo—es a través del método WriteXml() que es parte de la clase DataSet y DataTable.  Aunque no te da mucho control sobre el XML Schema que utiliza para exportar esos datos, utiliza una estructura bastante sencilla y amigable como para leerlo y manipularlo con otras herramientas.

Finalmente, creo que también es importante mencionar que si simplemente estás exponiendo datos, existen otros formatos más breves (que no usan XML), pero que siguen siendo amigables a los servicios, como JSON.  WCF maneja JSON de una manera relativamente fácil, y puedes consumirlo utilizando ASP.NET AJAX, por ejemplo.  Una última alternativa también es exponer tus datos como un ADO.NET Data Service (que es una característica nueva del .NET Framework 3.5 SP1).

Espero te ayude.

Enjoy smile_shades

Microsoft anuncia Visual Studio 2010 y .NET Framework 4.0

Ayer Microsoft se adelantó al PDC y anunció que Visual Studio 2010 (también conocido por Visual Studio 10 o “Rosario”) y el .NET Framework 4.0 estarían disponibles a finales del 2009 o principios del 2010—seguramente para coincidir con el lanzamiento de Windows 7, tal como lo hicieron con .NET 3.0 y Windows Vista.

Lo curioso, sin embargo es que no dió muchos detalles al respecto.  Según esta página en MSDN, los “pilares” de esa versión son [interpretación mía]:

  • Democratizar el ciclo de desarrollo.  Que en términos prácticos parece que se trata de incorporar aún más modelación en Visual Studio, incluyendo—finalmente—diagramación en UML.  Checa este video en Channel 9 al respecto. Parece que también van a mejorar algunas de las herramientas de pruebas y documentación, sobre todo para poder reproducir pulgas elusivas.
  • Facilitar las tecnologías emergentes.  No sé exactamente a qué se refieran, ¿quizá soporte nativo a Silverlight 2 y cosas así? ¿Facilitar cosas de cloud computing? ¿Desarrollo para mulitprocesadores/multicore?
  • Inspirar deleite en los desarrolladores.  Esto me suena a puro marketingspeak :)
  • Seguir la ola de plataformas de próxima generación.  Esto pudiera referirse a tecnologías asociadas con Windows 7 o Server 2008 R2, o a cosas relacionadas con Live Mesh—parte de la iniciativa de cloud computing de Microsoft—que estoy seguro también tendrán algo de integración.
  • Aplicaciones departamentales avanzadas.  Supongo que se enfocarán a facilitar el desarrollo no solo de “aplicacionzotas” sino también “aplicacioncitas”—que luego crecen como monstruos y luego las quieren usar en todos lados.  ¿Significa que integrarán algunos pricipios de Access? [eek]

Hay una serie de videos ya en Channel 9 acerca de VS 2010.  El blog de Arturo también tiene algo más de información en español al respecto.

Enjoy cool
Posted from Diario de un Dotnetero | 0 Comments
Filed under:

Videos en español de Visual Studio 2008 y más por Channel 9

Para los que no lo conocen, Channel 9 es un sitio de Microsoft para desarrolladores donde puedes encontrar un montonal de videos—y más importante creo—opinar sobre muchas de las tecnologías que maneja la compañía. 

La mayoría de los videos están en inglés, pero hoy descubrí que si juegas con los tags puedes obtener un listado de los videos que está en español.  Este enlace te da dicho listado:

http://channel9.msdn.com/tags/Spanish/

Ahí encontrarás videos sobre Visual Studio 2008, Expression Web, incluso uno que otro sobre Silverlight y Expression Blend.

Por ejemplo, parece que acaban de sacar una serie de cinco partes sobre Expression Web—uno de los productos de la familia Expression diseñados para hacer desde sitios HTML hasta sitios con páginas ASP.NET.

Enjoy smile_shades

Cómo transformar XML sin usar XSLT

El otro día, una compañía externa hizo un una auditoría de seguridad a un sistema grande que manejamos.  Parte de la auditoría consistió en correr la herramienta FxCop contra las DLLs para buscar—entre otras cosas—posibles vulnerabilidades de inyección de SQL.  FxCop produce dichos reportes en XML y eso fue lo que nos entregaron. 

Estos reportes eran enormes y en un formato no muy amigable, así que necesitábamos de alguna forma extraer los datos de ahí para enfocar los esfuerzos de los desarrolladores (qué corregir y en dónde), y también para tabular los datos (número de issues por namespace, DLL, etc.) de manera que se les pudieran presentar a los gerentoides. 

Este es un ejemplo de uno de esos archivos—no te preocupes, todas estas vulnerabilidades ya fueron parchadas, este es un extracto de esos reportes smile_wink.

(Da clic a la imagen para ver un tamaño más grande)

ejemplo de reporte FxCop

Ahora, se me ocurrió que estos archivos se podían transformar a algo menos plano—como otro archivo de XML o un CSV—de manera que pudiera ser importado a Excel fácilmente.  Algo así como lo siguiente:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Vulnerabilities>
  <Vulnerability>
    <Module></Module>
    <Namespace></Namespace>
    <Type></Type>
    <Method></Method>
    <Issue></Issue>
  </Vulnerability>
  <Vulnerability>
    <Module></Module>
    <Namespace></Namespace>
    <Type></Type>
    <Method></Method>
    <Issue></Issue>
  </Vulnerability>
</Vulnerabilities>

La sola idea de hacer una hoja de estilos XSL para transformar eso me daba escalofríos, así que fue una buena oportunidad para practicar mi LINQ-Fu.  Para ello me ayudé de LINQPad—una excelente herramienta para probar snippets de LINQ.

Armando el query

Mi primer query fue este:

XElement xml = XElement.Load(@"C:\Users\Carlos\Desktop\sampleFxCopReport.xml");
 
var query =
    from e in xml.Descendants("Issue")
    where e.Ancestors("Message").Attributes("TypeName").First().Value == "ReviewSqlQueriesForSecurityVulnerabilities"
    select new
    {
        Module = e.Ancestors("Module").Attributes("Name").First().Value,
        Namespace = e.Ancestors("Namespace").Attributes("Name").First().Value,
        Type = e.Ancestors("Type").Attributes("Name").First().Value,
        Method = e.Ancestors("Member").Attributes("Name").First().Value,
        Issue = e.Value
    };

Como puedes ver, cargar el archivo es trivial.  Puedes hacerlo a través del método Load() de la clase XElement o XDocument.

Luego, declaré una variable de tipo var porque no estaba seguro exactamente del tipo de los objetos que regresaría mi query—utilicé un tipo anónimo, el cual explicaré en un minuto.

Si no estás muy familiarizado con queries de LINQ, solo recuerda que en su nivel más básico, tienes un from/where/select

  • Primero le dices a qué objetos quieres hacerle query (from),
  • luego especificas un filtro que deje solo los que te interesen (where) y
  • finalmente le indicas una expresión de cómo quieres proyectar tus datos en la salida (select).

En este caso, se me hizo más fácil elegir primero todos los elementos <Issue> dentro del documento XML, ya que a partir de ellos puedo obtener el resto de la información viendo los nodos ancestros.  Logré hacer esto con una sola línea en el from gracias al método Descendants() de la clase XElement.  En otras palabras estoy diciendo “selecciona los elementos <Issue> en el documento, y por cada uno de ellos dame una variable e de donde extraer más información”.  Puedes pensarlo como algo parecido a un foreach.

Luego, indiqué en el filtro where que únicamente deseo los <Issue> donde el mensaje (<Message>) sea de tipo vulnerabilidad de SQL (TypeName=”ReviewSqlQueriesForSecurityVulnerabilities”).  Como los elementos <Message> son ancestros de <Issue>, utilicé Ancestors() para acceder a ese elemento y luego Attributes() para obtener el valor de atributo TypeName y poder hacer la comparación.

Finalmente, en la proyección el select new crea un tipo (una clase pues) sin nombre con 5 propiedades, que son inicializadas con los valores de las expresiones.  Esto crea una collección de tipo IEnumerable<T> donde T es el tipo anónimo—¿ves por qué fue necesaria la variable var?

El resultado del query es este (da clic para ver la imagen más grande):

resultados del primer query

Pero, ¿qué tal si quisiera ordenar mis resultados primero por Module, luego por Namespace, Type y Method sucesivamente?  Sencillo.  Puedo agregar una cadena de OrderBy’s a mi query original o puedo agarrar el resultado del query y ordenarlo así:

var ordered =
    query.OrderBy(x => x.Method).OrderBy(x => x.Type)
    .OrderBy(x => x.Namespace).OrderBy(x => x.Module);

Esta manera de hacerlo involucra las famosas expresiones lamda, pero no me quiero desviar en explicarlas.  Por ahora sólo tómalas como ejemplo y nota que puedes encadenar las cláusulas.

Esto es un buen comienzo, pero ahora quiero esos datos en algo que se le parezca a un documento XML.

Entonces agregué esto después de mi query:

XDocument xdoc = new XDocument();
xdoc.AddFirst(new XElement("Vulnerabilities"));
 
foreach (var element in query)
{
    xdoc.Root.Add(
        new XElement("Vulnerability", new XElement("Module", element.Module)
                                    , new XElement("Namespace", element.Namespace)
                                    , new XElement("Type", element.Type)
                                    , new XElement("Method", element.Method)
                                    , new XElement("Issue", element.Issue)
                                    ));
}

Primero creo un nuevo documento XML utilizando la clase XDocument, y le agrego un elemento raíz <Vulnerabilities>.  Luego por cada elemento de mi lista ordenada, agrego un elemento <Vulnerability> que contendrá cinco elementos, uno por cada propiedad que me interesó, y que tendrán el valo.  Nota que los constructores “raros” de XElement facilitan enormemente la tarea, y que los métodos AddFirst() y AddNew() se encargará de cerrar los elementos adecuadamente—a diferencia de la forma en que se utiliza un XmlWriter, por ejemplo.

El resultado:

resultados del query

Esto ya es prácticamente lo que quiero.  Sin embargo, mi código hasta ahorita son como 30 líneas—principalmente por el formato, en realidad solo he utilizado como 7 instrucciones—y me gustaría condensar el código más.  Además descubrí que el ordenamiento en realidad no lo necesito—puedo hacerlo en Excel—y que al documento XML le falta la declaración <?xml> al pricipio.

Sintetizando el código

Así que decidí cambiar la proyección (el select pues) de mi query original.  El total del código quedó así:

XElement xml = XElement.Load(@"C:\Users\Carlos\Desktop\sampleFxCopReport.xml");
 
IEnumerable<XElement> query =
    from e in xml.Descendants("Issue")
    where e.Ancestors("Message").Attributes("TypeName").First().Value == "ReviewSqlQueriesForSecurityVulnerabilities"
    select new XElement("Vulnerability",
        new XElement("Module", e.Ancestors("Module").Attributes("Name").First().Value),
        new XElement("Namespace", e.Ancestors("Namespace").Attributes("Name").First().Value),
        new XElement("Type", e.Ancestors("Type").Attributes("Name").First().Value),
        new XElement("Method", e.Ancestors("Member").Attributes("Name").First().Value),
        new XElement("Issue", e.Value)
        );
 
XDocument xDoc = new XDocument(
    new XDeclaration("1.0", "UTF-8", "yes"),
    new XElement("Vulnerabilities", query)
    );

Nota que con solo 2 instrucciones—la instrucción de carga no cuenta—logré hacer la transformación (¡!) smile_omg.   Veamos los cambios significativos al query.

Primero, el resultado es almacenado en una variable que ya no es tipo var, sino IEnumerable<T> donde T es XElement.  Esto es porque en la proyección (el select) ya no estoy utilizando un tipo anónimo para construir un objeto, sino los constructores de la clase XElement para obtener objetos de este tipo.

Finalmente, a la hora de crear el nuevo documento XML, utilizo también un constructor alterno de XDocument, para primero pasarle la declaración XML, y agregarle un elemento <Vulnerabilities> que tendrá como contenido el resultado de mi query—la lista de nodos <Vulnerability> con sus respectivos elementos hijo.  ¿Así o más mágico? smile_teeth

[Pronunciarse en tono de vendedor de chuchulucos por T.V.:] ¡Pero aún hay más!

¿Quieres saber lo que se necesita para guardar el nuevo documento de XML a un archivo?

xDoc.Save(@"C:\Users\Carlos\Desktop\transformedReport.xml");

Así que con un total de 4 instrucciones logré cargar un archivo complejo de XML, transformarlo y escribir los resultados a otro más amigable.

[Pronunciarse en tono de vendedor de chuchulucos por T.V.:] ¡Pero aún hay más!

Sintetizándo el código aún más

¿En verdad quieres ponerte quisiquilloso con el query?  Puedes lograr la totalidad de la lógica con solo 3 instrucciones—una para cargar el archivo original, otra para transformarlo y una más para guardar el archivo resultante—si utilizas expresiones lambda.  Este ejemplo no lo explico porque igual y te acabo confundiendo más, pero creo que ilustra el poderío de LINQ y las nuevas clases para manipular XML.

XElement xml = XElement.Load(@"C:\Users\Carlos\Desktop\sampleFxCopReport.xml");
 
XDocument xDoc = new XDocument(
  new XDeclaration("1.0", "UTF-8", "yes"),
    new XElement("Vulnerabilities",
      xml.Descendants("Issue")
      .Where(i => i.Ancestors("Message").Attributes("TypeName").First().Value == "ReviewSqlQueriesForSecurityVulnerabilities")
      .Select(e => new XElement("Vulnerability",
              new XElement("Module", e.Ancestors("Module").Attributes("Name").First().Value),
              new XElement("Namespace", e.Ancestors("Namespace").Attributes("Name").First().Value),
              new XElement("Type", e.Ancestors("Type").Attributes("Name").First().Value),
              new XElement("Method", e.Ancestors("Member").Attributes("Name").First().Value),
              new XElement("Issue", e.Value)
              )
          )
      )
  );
 
xDoc.Save(@"c:\users\Carlos\Desktop\transformedReport.xml");

¿Qué tal, eh? smile_nerd

Conclusión

Este artículo mostró un ejemplo de cómo transformar un documento XML utilizando LINQ to XML.  También mostró de manera práctica qué son los tipos anónimos (“clases sin nombres”), cómo cargar y escribir archivos XML con las clases XElement y XDocument incluidas en el .NET Framework 3.5, e ilustró brevemente el uso de expresiones lambda.  La mayoría de los conceptos—excepto quizá las expresiones lambda—aplican también si estás utilizando Visual Basic como tu lenguaje de desarrollo para .NET.

Enjoy. smile_shades

Google Chrome beta tampoco me impresiona

Todo mundo y su abuelita para ahora se ha de haber enterado que Google lanzó su propio browserWired tiene un artículo interesante de por qué se tardaron tanto para lanzarlo, cuando para muchas personas era una evolución lógica.

Bajo riesgo repetir artículos anteriores, tengo que admitir que cuando comencé a ver la lista de características “inovadoras” me sorprendió lo no inovadoras que en realidad son:

  • Omnibox. Básicamente una versión del Awesomebar (Firefox 3) o del Smart Address Bar de IE8 beta2, pero con búsqueda integrada. Moderadamente interesante. Se parece también al search box que trae Flock—y el cual espero fusionen con el Awesomebar para Flock 2 final.
  • Pestañas independientes. Rara vez se me ha ofrecido que una pestaña haga que truene el navegador. De las pocas veces que me ha sucedido es cuando corro IETab dentro de Firefox, e incluso en esas instancias FF hace buen trabajo en recuperar mi sesión. Pero, la idea es interesante. Tanto que al parecer se le ocurrió lo mismo al equipo de Internet Explorer 8.
  • Acceso directo a aplicaciones. Un concepto que se me hizo bastante útil, desde que el equipo de Mozilla comenzó con el proyecto Prism hace casi un año (¿?)—y del cual, naturalmente hay una extensión para Firefox.
  • Pestañas dinámicas. Yo suelo mantener una sola ventana de navegador abierta—si no ¿pa’ qué quiero las pestañas, verdad?—pero si les gusta esta característica, también pueden encontrarla en Safari.
  • Modo incógnito. O como dijo un amigo mío, modo “p0rn” jejeje—y no que yo lo use, ¿verdad? Hmm… ¿dónde he visto eso? ¡Ah! Qué tal en Safari (conocido como Private Browsing) y en IE 8 beta 2 (conocido como InPrivate).
  • Marcadores instantáneos. Ver Flock, y FF 3. No digo más.

De lo único que en verdad puedo ver inovador es el motor de JavaScript que le pusieron, V8, que al parecer patea traseros en desempeño. Y aunque algunos autores han argumentado que JavaScript es “solo una parte mínima del Web”, yo les digo: ¿Alguna vez has intentado correr Gmail, Slashdot o Facebook en IE7 o previos contra cualquier otro navegador moderno? JavaScript sí importa, y mucho.

Tratando de no tirar mucho rollo—demasiado tarde, lo sé—sí hubo cosas que me gustaron:

  • Desempeño. Jala hecho la mater cuando no está detrás de un proxy—lean un poco más abajo.
  • Google Gears integrado. No tienes que instalar esto por separado para utilizar, por ejemplo, Google Reader en modo offline. No sorprendente, dado que otro producto de Google, pero es útil que lo traiga integrado.
  • Interfaz minimalista. De las primeras cosas que le hago a Firefox es quitarle todos los botones y cosas extra y si vieran mi pantalla verían que mi arreglo quedó prácticamente idéntico al que usaron en Chrome. Safari también viene de cajón así.
  • Herramientas de desarrollo Web incluidas. Al igual que Safari, puedes seleccionar un elemento y dar “Inspect Element” para obtener información de CSS, etc.
  • Búsqueda en la página amigable. Casi igual que la de Safari—¿comienzan a ver un patrón?

image

Si quisiera resumir “lo bueno” diría que en muchos sentidos, Chrome es como Safari, pero sin el rendereo borroso de fonts en Windows y con Gears integrado.

Lo que de plano no me gusto, y de hecho impide que lo use de tiempo completo:

  • No le gustan los proxies, sobretodo los que te piden username y password. Ni siquiera puedes instalarlo si estás detrás de un proxy de este tipo. Y el desempeño se va por el caño, con muchas páginas que no se llegan a cargarse completas—no pude correr Gmail, lo cual es el colmo. Esto quizá es de esperarse de un beta—Safari tuvo problemas similares que resolvieron en la versión final—pero por ahora es un dealbreaker para mi.
  • Fallas de compatibilidad con sitios sociales. Algunas cosas en Facebook y MySpace no funcionan aún con Chrome. Unas simplemente hacen una experiencia menos agradable y otras de plano hacen que no puedas utilizar funcionalidad de estos sitios. MySpace puede irse a chiflar alpistle—es el sitio del demonio en lo que a mi concierne—pero Facebook está bastante bien armado hasta donde sé. Pero si el navegador no jala bien en estos sitios, ¿cuántos chavalos de 12 a 17 años que se la pasan viviendo ahí lo usarían?
  • No trae soporte para RSS. Solo muestra el XML del feed. ¿Cómo se supone que voy a leer mis noticias?

¿Matará Chrome a IE? Lo dudo. Habrá que ver lo que sucede. En mi opinión esto tomaría tiempo, aunque es interesante que algunos ya le achacan el 3% del mercado después de su lanzamiento. Google es una compañía a la par con los recursos y reputación de Microsoft, lo cual introduce una dinámica interesante, sobretodo para los que desarrollamos aplicaciones Web. Antes probablemente te preocupabas por que tus sitios jalaran en IE o Firefox, si mucho—al pobre de Opera nunca lo han pelado y mucho menos a Konqueror et.al. Ahora que tienes Safari y Chrome en el mercado, creo que finalmente comenzaremos una era donde los estándares en el desarrollo del Web cobren la importancia que debieron tener desde el principio. *Cruzando los dedos para que suceda*

Enjoy.

Visual Studio 2008 Service Pack 1 ya está disponible

Al menos para suscriptores de MSDN.

Official MSDN Subscriptions Blog : Visual Studio 2008 Service Pack 1 files are also now available

Oh, y también ya soltaron la versión RTM de SQL Server 2008.

Enjoy

Posted from Diario de un Dotnetero | 0 Comments
Filed under:

Reseña del Lanzamiento de Visual Studio 2008

Alex Briseño puso una muy buena reseña del evento que tuvimos el pasado martes 27 de mayo, repleto de fotografías, pa’ que vayan a leerla. 

La verdad yo me divertí un chorro, a pesar de que quedé exhausto porque me tocó dar 3 pláticas—lo cual implica hablar casi tres horas—me dió mucho gusto ver tanta gente.  También se sintió bien padre que que ahora sí tuvimos bastantes cosas que regalar como todos esos paquetes de desarrollador con Visual Studio 2008, SQL Server 2008 y Windows Server 2008, así como los discos de Windows Vista y las suscripciones de TechNet.

Pero lo más chido creo que fue definitivamente el final, cuando nos pusimos a jugar—o a hacer el intento de jugar—boliche y a echarnos unas chelas con toda la raza hardcore que se quedó hasta esa hora. 

El momento priceless se lo llevó Sergio, después de ganarle a Alex: “No pos si es la primera vez que juego”... ajá... sí cómo no... jejeje

Posted from Diario de un Dotnetero | 0 Comments
Filed under: ,

Cómo acceder a controles dentro de un GridView

Esta entrada salió como resultado de una pregunta que hicieron en el Foro de la Comunidad .NET.  La pregunta, esencialmente, es: ¿Cómo accedo a un control que tengo en una columna templeteada dentro de un GridView de ASP.NET?

Me pareció buena la pregunta, así que hice un pequeño ejemplo para ilustrarlo.   Una columna templeteada (TemplateField) es distinta a una normal (BoundField) en que tienes más control sobre los controles que aparecen en la columna.  En otras palabras, tú especificas qué quieres que se muestre cuando el renglón está en modo "normal" (ItemTemplate) o cuando está en modo "edición" (EditItemTemplate).  Puedes tener múltiples controles dentro de la columna, en lugar de solo uno que represente el dato.

La siguiente página contiene un GridView con tres columnas que vienen de un SqlDataSource.  Los datos provienen de la clásica base de datos Northwind.   En este caso estoy recuperando datos de la tabla de productos:

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb"
  Inherits="_Default" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
  <title>Accediendo a Elementos en un GridView</title>
  <style type="text/css">
    #miGrid
    {
      width: 450px;
      float: left;
    }
  </style>
</head>
<body>
  <form id="form1" runat="server">
  <asp:Button runat="server" ID="leerElementosButton" Text="Leer elementos" />
  <div id="miGrid">
    <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
      DataKeyNames="ProductID" DataSourceID="SqlDataSource1" 
      EmptyDataText="No hay registros que mostrar.">
      <Columns>
        <asp:BoundField DataField="ProductID" HeaderText="ID Producto" 
          InsertVisible="False" ReadOnly="True" />
        <asp:BoundField DataField="ProductName" HeaderText="Nombre Producto" />
        <asp:TemplateField HeaderText="Descontinuado">
          <EditItemTemplate>
            <asp:CheckBox ID="CheckBox1" runat="server" 
              Checked='<%# Bind("Discontinued") %>' />
          </EditItemTemplate>
          <ItemTemplate>
            <asp:CheckBox ID="CheckBox1" runat="server" 
              Checked='<%# Bind("Discontinued") %>' Enabled="false" />
          </ItemTemplate>
        </asp:TemplateField>
      </Columns>
    </asp:GridView>
    <asp:SqlDataSource ID="SqlDataSource1" runat="server" 
      ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
      ProviderName="<%$ ConnectionStrings:NorthwindConnectionString.ProviderName %>"
      SelectCommand="SELECT [ProductID], [ProductName], [Discontinued] FROM [Products]">
    </asp:SqlDataSource>
  </div>
  <div id="resultados">
    <asp:Label runat="server" ID="resultadosLabel" />
  </div>
  </form>
</body>
</html>

Para acceder, por ejemplo, al CheckBox que está dentro de la columna templeteada, primero necesitas una referencia al renglón, ya que el ID del control se repetirá n veces (una por cada renglón del Grid). 

Esto se puede hacer de varias formas, por ejemplo, si tienes un manejador para un evento clic en alguno de los controles dentro del renglón pues en ese caso el sender viene siendo el renglón en sí, entonces únicamente te falta encontrar el CheckBox de ese renglón para leer sus propiedades.   Otra forma de hacerlo, como en el siguiente ejemplo, es leer todos los renglones y por cada uno encontrar el CheckBox que le corresponde al renglón:

Partial Class _Default
  Inherits System.Web.UI.Page
 
  Protected Sub leerElementosButton_Click(ByVal sender As Object, _
    ByVal e As System.EventArgs) Handles leerElementosButton.Click
 
    Dim grid As GridView = Me.GridView1
    Dim checkBox As CheckBox
    Dim resultado As New StringBuilder
 
    For Each renglon As GridViewRow In grid.Rows
      checkBox = CType(renglon.FindControl("CheckBox1"), CheckBox)
      If checkBox.Checked Then  'Hacer algo con esta información
        resultado.Append(String.Format( _
          "El renglón {0} está descontinuado <br />", renglon.DataItemIndex))
      End If
    Next
 
    resultadosLabel.Text = resultado.ToString()
 
  End Sub
End Class

En resúmen, la idea clave aquí es que el GridView tiene una colección de renglones (de tipo GridViewRow) y cada uno de estos renglones tiene su correspondiente colección de controles que están dentro de ese renglón.  El GridViewRow también te da acceso al DataItem que contiene los datos asociados al renglón, en caso de que lo requirieras.

El resultado de correr el código anterior (dando clic al botón) es el siguiente:

Espero les ayude.

Enjoy smile_shades

Posted from Diario de un Dotnetero | 0 Comments
Filed under: ,

Creo que he estado trabajando mucho...

Me salió esto hoy.  Creo que Visual Studio está tratando de decirme algo...

Atajos de teclado para Visual Studio

Una de las maneras más fáciles de incrementar tu productividad cuando utilizas casi cualquier programa es aprenderte los atajos de teclado—los mentaos keyboard shortcuts, pues.  De hecho tengo amigos que odian levantar las manos del teclado cuando están programando.  Si alguna vez has usado algún editor de texto como vi, quizá hayas apreciado que una vez que dominas la complejidad de los comandos, en realidad se siente como si estuvieras "platicando" con el editor. Y aunque yo no llegaría al extremo de recomendar que manejes Visual Studio con los comandos de vi, sí recomiendo enormemente que te aprendas algunos de los más comúnes que ya vienen de cajón con el IDE.

El problema es que Visual Studio tiene 8 millones 557,934 comandos.  Bueno, quizá algunos menos, pero aún así son un titipuchal.  Y lo que es peor, los atajos de teclado cambian de acuerdo a la configuración general de Visual Studio.  Esta es la configuración que te pregunta la primer vez que arrancas el IDE o si das Tools>Import and Export Settings...>Reset all settings.

Ventana de diálogo de configuración general de Visual Studio

Aquí es donde ayudan algunos documentos de referencia rápida.  Si primordialmente desarrollas en Visual Basic, y utilizas esa configuración (Visual Basic Development Settings), aquí hay un PDF de Microsoft que los resume. 

Si usas la configuración de Visual C# Development Settings, para desarrollar primordialmente en C#, están este para Visual Studio 2005 y este otro para Visual Studio 2008.

Sin embargo, yo utilizo la configuración para desarrollo general (General Development Settings) porque desarrollo tanto aplicaciones Web como Windows, a veces en C# y a veces en Visual Basic, aparte que ya me había aprendido algunos atajos desde versiones anteriores de Visual Studio.  Como no encontré ninguna referencia rápida para esta configuración, creé mi propio documento.  Puedes descargarlo del sitio de la Comunidad.

Mi recomendación personal es, no intentes aprenderlos todos de un zopetón.  Dice un proverbio: "¿Cómo te comes un elefante? Un bocado a la vez".  Así que mejor escoge un grupo de comandos y practica cada uno por separado, repitiéndolo al menos 20 veces.  Lo que yo hice fue agarrar una archivo con código y practicar un comando a la vez en diferentes partes del archivo mientras lo "vocalizaba mentalmente" hasta que quedaba grabado en mi memoria muscular.  Luego practicaba el siguiente comando hasta terminar el grupo.  Al día siguiente me enfocaba en un grupo distinto, y así sucesivamente.

Cómo crear tus propios atajos

Por supuesto, también puedes definir tus propios atajos.  Estos atajos pueden ejecutar un comando del IDE o alguna macro que hayas creado para alguna tarea específica.  Por ejemplo, hay dos atajos que a mi me ha sido útil definir: uno para comparar el archivo actual contra la versión en el controlador de código y otro para obtener el historial del archivo actual en el controlador de código.

Para definirlos, primero ve a Tools>Options... y luego Environment>Keyboard.  Al hacerlo verás la siguiente ventana:

En la parte donde dice Show commands containing, teclea parte del comando, p. ej. "compare".  Esto traerá una lista de posibles comandos.  En este caso, el que busco es File.Compare.  Luego, selecciona el comando adecuado de la lista y pon el cursor en la parte donde dice Press shortcut keys. Presiona la combinación que desees utilizar.  Si la combinación ya está siendo utilizada por algún otro comando, esta información será mostrada en la parte de abajo donde dice Shortcut currently used by.  En mi caso escogí la combinación Ctrl+Alt+F,C para finalmente darle clic en el botón Assign

Repite los mismos pasos para el comando File.ViewHistory y utiliza el atajo Ctrl+Alt+F,H—o cualquier otra combinación que más te guste.

En fin, creo que esto da la idea.  Enjoy smile_shades

La Generación M: Al borde del un nuevo cambio

Hoy me tocó dar una plática bastante diferente a la que estoy acostumbrado.  Resulta que los chavos de la carrera de Tecnologías Computacionales del Tec de Monterrey Campus Juárez (mi "alma mater") hicieron un evento llamado El Congreso con la finalidad de atraer a más chavos (y chavas, claro, si no qué chiste) de las prepas y secundarias locales hacia las carreras de "sistemas".

Aparentemente algunos de ellos habían leído mi blog y me enviaron un correo para invitarme a participar como expositor, lo cual se me hizo un honor.  Se siente medio raro regresar a la escuela de donde te graduaste para "enseñar algo".  Pero cuando me dijeron que la audiencia serían principalmente lepes de preparatoria comencé a ponerme un poco nervioso.  Después de todo, han pasado casi 10 años—a ver díaganlo: "uuuuuuuuuuuuu!"—desde que dejé de dar clases, y no me paraba a hablar enfrente de un grupo de esa edad.  Mi mente inmediatamente comenzó a dar vueltas: "Demonios, ¿de qué les puedo hablar? ¿De qué manera puedo encontrar un tema donde tengamos algo en común, y que hable de tecnología?" 

Pensándola un poco más caí en cuenta que muchos de estos chicos, son modelo 90 o más reciente—osea que nacieron después de 1990—lo cual me hizo sentir más ruco todavía porque yo soy setentayquíhúbole.  Mientras más lo pensaba más me era evidente que hay un a brecha entre esta generación y la mía.  Comencé a recordar cómo era el mundo cuando yo tenía la edad de ellos—hace 15 años más o menos—y cómo había cambiado el mundo desde entonces hasta ahora, hasta que me cayó el veinte: "¿y por qué no hablar precisamente sobre eso?".

Así que eché un poco de alucine este fue el resultado.

Generación i

La i es de internet.  Esta es la generación a la que creo que pertenezco.  En ella incluyo a las personas que eran adolescentes durante los pricipios de la década de 1990 y que nos tocó, por un lado, ver el nacimiento del internet—sí ya sé que el interné existía desde los 70s y 80s pero no fue sino hasta los 90s que el Web lo trajo a las masas ¿verdad?—y por otro lado presenciar cambios históricos a nivel mundial como la caída del comunismo.

 

Aún recuerdo ver en la televisión cómo derribaban el muro de Berlín.  Recuerdo ver también en la T.V. los tanques en Rusia mientras intentaron el golpe de estado contra Gorbachev y sentirme triste porque leí su libro sobre la perestroika y el glasnost.  Recuerdo la caída, país por país, de la cortina de hierro en Europa y también la primera Guerra del Golfo Pérsico donde una coalición de países decidió luchar contra Saddam Hussein.

Para cuando tuve edad de entrar en a la carrera en 1994, el mundo entero parecía enamorado de nuevo con el capitalismo y la apertura de mercados.  México llevaba poco que había firmado el TLC y en el Tec hasta inventaron carreras nuevas como la de Lic. en Comercio Internacional.  También por aquellos tiempos el internet comenzaba a salir de las escuelas y a entrar a los hogares.  El Tec, que hasta entonces había sido el único ISP de Cd. Juárez, le dejó eso a compañías como Infolink (si mal no recuerdo)—¿se acuerdan cuando tenían que pagarle a alguien y marcarles por teléfono con su módem para estar "en línea"? ¿No? Chin.

El caso es que se respiraba un ambiente de apertura.  En el lado tecnológico esa actitud comenzó a reflejarse en movimientos como el de Open Source.  Las personas comenzaron a colaborar a pesar de las grandes distancias gracias a la red que ahora cobraba vida.  Estábamos en plena "globalización 1.0", como lo describe Thomas Friedman y el mundo se estaba aplanando.  El internet había fomentado la globalización y la globalización ayudó al crecimiento de la red.  Por supuesto que ese momento no me dí cuenta de lo que ocurría porque estaba inmerso en él.  Para cuando me gradué de la carrera en 1998, "eso del e-mail" y de trabajar a distancia se había vuelto bastante común. 

Generación M

La M es de móbil, es decir un pochismo deformado mío de mobile phones, también conocidos como teléfonos celulares.  Esta es la generación que en estos momentos está en la adolescencia.

Cuando comencé mi plática, abrí con una pregunta: "¿Cómo sería tu vida... sin tu celular?"  Hubieran visto la reacción.  Fue una exclamación colectiva de auténtico horror: "¡Ay NOOoooo!", jejeje. "¿...sin Google? ¿...sin el Internet? ¿Qué música escucharías? ¿Qué sería diferente?"  Y ya cuando habían parado la oreja puse una diapositiva que decía: "Así era el mundo hace apenas 15 años".

A veces creo que no se le ha dado crédito a la impacto que han tenido los celulares—y sí, yo también considero que son odiosos y ojalá no los hubieran inventado, pero pues ni modo ya ganaron.  "En mis tiempos..."—como dicen los viejitos—los únicos que traían celulares eran los narcos y la gente de muuuucha lana.  Eran esos horrendos ladrillos Motorola que les duraba la pila una hora y podían se utilizados como arma de defensa personal.

 

Hoy en día parece que los chavitos nacen con el celular en la mano.  He visto niños de 7 y 8 años—entre ellos algunos de mis sobrinos—con celular propio, lo cual me parece absurdo, pero es la realidad.  Todo tipo de vagancias y mal comportamiento es videograbado con su teléfono para subirlo a YouTube.  Para ellos se ha convertido en una extensión de su persona.  Algunos de ellos incluso se identifican con su celular, lo cual es en verdad preocupante. 

Esto está ocasionando cambios interesantes.  Por ejemplo, todos esos mensajitos de texto—y la flojera que causa tener que teclearlos, supongo—están ocasionando cambios informales y deformaciones al español escrito.  Una conversación típica podría ser:

—Ke rollo?
—No ps nada
—Vas a ir al cine vdd?

Este tipo de deformaciones también están creciendo por el uso de mensajería instantánea (Messenger, Google Chat, Skype, etc.).  Cuando intento platicar con una de mis sobrinas por Messenger, a veces me dan ganas de darle un sape virtual y decirle: "¡escriba bien, no sea payasa!", pero me las aguanto.  Estos programas, también los están acostumbrando a que ahora se puede tener conversaciones de video o voz internacionales gratis o a muy bajo costo.  En otras palabras, la dimensión de la distancia comienza a cambiar.  El mundo no solo es plano sino que comienza a encogerse.

Una característica más que se me ocurre sobre la generación M es que, los chicos de ahora están (¿mal?)acostumbrados a tener las cosas on-demand, es decir, cuando ellos quieren y como ellos quieren.  Si quieren música, se van a iTunes, o BitTorrent o <inserte aquí la herramienta de piratería de moda>, la bajan y listo; ya no están limitados por la música de la radio o los discos en la tienda del mall.  Si quieren un libro es cuestión de pedirlo por Amazon o similares y obtenerlo.  ¿Aburrido? Solo "prende" YouTube y puedes perder horas enteras viendo todo tipo de tarugadas; ya no están limitados a lo que ofrece la tele.  La palabra clave, supongo, es opción.  Ahora tienen más opciones que nunca.  Lo cual quizá es bueno y malo a la vez.

Por otro lado también se pueden observar una serie de cambios y situaciones sociales interesantes.  Una de ellas me la apuntó Alex Briseño: los hijos de los dueños de muchas empresas están comenzando a tomar las riendas.  Es decir, un empresario que hoy tiene 50-60 años y que puso su negocio propio ahora está dándole el control a su hijos para que se hagan cargo.  Estos "hijos de dueños" son de la generación i, y no se sienten intimidados por la tecnología, lo que es más, lo ven como algo favorable, algo que trae un valor agregado.  Si alguna vez se han dedicado al negocio de vender "sistemas" se habrán quizá dado cuenta que con excepción de empresarios con mucha visión, la mayoría de la generaciones anteriores percibían esto como un costo, no como algo que les pudiera ayudar a ganar dinero.  Los "hijos de dueño", sin embargo, no solo no tienen problema con esto, sino que te buscan para que les hagas un sistema.  Eso a su vez comienza a cambiar la dinámica de la competencia en muchos ámbitos.

Combinado con la maduración de la globalización 2.0, el inicio de la 3.0 esto está permitiendo que los David comiencen a competir con los Goliat.  La Cola Larga está comenzando a esparcirse.  Dos ejemplos locales son que en Cd. Juárez, en los últimos 6 u 8 meses, Cablemás comenzó a competir con Telmex en telefonía; Volaris e InterJet, dos aerolíneas de bajo costo comenzaron a competir con Aeroméxico.

Pero con todas las maravillas de la tecnología hay otra cosa que está ocurriendo: está creciendo la brecha digital, el digital divide.  Es decir después de darte cuenta que el internet es maravilloso y que el acceso a la información es una necesidad porque uno como individuo está compitiendo con personas de todo el mundo, la siguiente pregunta inevitablemente es "¿y qué hay de los millones de mexicanos que aún viven en extrema pobreza? ¿Cómo sobreviviran en este nuevo mundo?"

Desgraciadamente no hay respuestas alentadoras.  La única manera de competir es a través de la educación y de ofrecer algo más.  En otras palabras, no competir en la maquilada de las cosas o de la información—siempre habrá mano de obra más barata en un país más desesperado—sino competir ofreciendo las cosas que requieren de más coco, de más intelecto. Seguro, un ingeniero hindú o chino de sistemas promedio sale más barato que yo, pero ninguno, de todos los que conozco y con los que he trabajado tiene la misma capacidad que yo.  Y no es por ser arrogante, simplemente les ha faltado cayo y colmillo.  No significa que no haya ingenieros competentes en otros países, significa que esos ingenieros no son de bajo costo.  Incluso eso está cambiando claro, al punto que en 10 años quizá estemos hablando de otros países.

Esta es una realidad difícil de aceptar.  Aunque hay que mencionar que sí hay algunas personas haciendo algo concreto al respecto.  Proyectos como el de Una Laptop Por Niño (OLPC) están tratando de atacar este tipo de problemas, pero la tecnología en sí es una solución insuficiente.

Generación W

La W es de wireless.  Esta generación serían los hijos de la generación M, nacidos quizá unos 15 o 20 años más en el futuro.

Si todo progresa como hasta ahora, más temprano que tarde la idea de las redes inalámbricas a nivel ciudad o región se harán realidad a través de cosas como WiMAX o mesh networks.  En otras palabras para entonces ya no estarás atado a tu casa o tu restaurante favorito para estar conectado.  Esto no solo dará a pie a dispositivos más sencillos y a la vez sofisticados—¿imaginas el iPhone del futuro?—sino que haría el sueño de OLPC una realidad.

Una vez liberados de los cables, estos niños podrán asimilar información y tecnología de manera casi instantánea.  De hecho, la idea de adiciones bio-tecnológicas al cuerpo humano no está completamente fuera del rango de posibilidades.  Imagina que en lugar de cargar un dispositivo como un celular o tableta inteligente que te brinda información, ésta esté integrada a ti.  Una red inalámbrica ubicua y un "chip" integrado podría darle la capacidad a los niños de este siglo de comunicarse y compartir información pseudo-psíquicamente en una red verdaderamente P2P.  Piensa en los Borg, de Star Trek, pero no tan feos y con independencia de acción.

¿Todavía suena como ciencia ficción?  Considera que en unos 15 años seguramente habrá avances significativos en la nanotecnología y que según algunos expertos para el 2029 también habrá tanto el hardware como el software necesario para tener inteligencia artificial a nivel humano.  Supon que se retrasen algunos años, el doble aproximadamente, y esto no se de sino hasta mediados de siglo.  Los niños de la generación W estarán apenas entrando a la adolescencia.

Sin embargo hay cosas que podrían descarrilar todo esto.  Conflictos globales persistentes, como la actual guerra en Irak podrían llevar a un des-aplanamiento del mundo y a que se vuelvan a cerrar las fronteras, regresándonos a la era Reagan.  Simplemente consideren algunos de los argumentos de los actuales candidatos demócratas a la presidencia de EE.UU., Barack Obama y Hillary Clinton.  Ambos han expresado que quieren re-negociar el TLC.  Entre eso, y el muro—perdón, "barda"—fronterizo que tan insistentemente y están construyendo, no inspira precisamente un ambiente de apertura para el futuro.  Siguiendo esta línea de pensamiento, no es tampoco descabechado pensar en un Great Firewall estadounidense o europeo modelado después del de China.  Si esto llegara a ocurrir y regresáramos a un mundo cerrado, la humanidad en mi humilde opinión, se estaría dando en la torre de motu proprio.

Pero todas estas son meramente posibilidades.  Lo bonito del futuro es que aún no está escrito, ¿verdad?

Apple libera Safari para Windows, IE8 beta no me impresionó

Parece que Apple acaba de liberar la versión final de Safari.  Y aunque las versiones beta tuvieron algunos detalles (desde problemas con los fonts hasta problemas para autenticar a través de un proxy), la versión final parece haber atado los cabos sueltos.  Una adición particularmente útil para los desarrolladores Web es que integraron las herramientas de desarrollado (WebKit) que antes solo estaban disponibles en la Mac:

Y aunque esto no es nada nuevo para gente que desarrolla con Firefox, es bueno tenerlo en otros navegadores.

Por otro lado hace un par de semanas el equipo de Internet Explorer anunció los features de IE8 al liberar el beta 1 de ese navegador el cual también incluirá herramientas de desarrollo Web estilo Firebug.  <sarcasmo>Qué bien, ya no voy a tener que bajar el Developer Toolbar y el Web Development Helper por separado.</sarcasmo>  En cuanto a los otros "features", ummm, a ver: WebSlices = Firefox Live Bookmarks on steroids, Activities = Smart Tags rehashed, y AJAX navigation = Something that should come with your AJAX framework.  Lo único decente va a ser la mejora en el performance de JavaScript, lo cual les urgía corregir, pero de ahí en más nada particularmente inovador.

Posted from Diario de un Dotnetero | 0 Comments
Filed under:

Aguas con el SDC (Síndrome del Desarrollador Callado)

Ya van varias veces que veo esto ocurrir en diferentes proyectos y diferentes compañías, así que asumo que es algo relativamente común.

La historia casi siempre es la misma: se vende un proyecto grande a un cliente, quizá algo ajustado de tiempo, pero suficiente para hacerlo.  Se hace el análisis y se bosqueja el diseño rápidamente.  Se reparte la chamba y todos en el equipo se ponen a jalar: "Tú aviéntate este módulo, tú este y yo este otro".

Ves a uno de los desarrolladores involucrados en el proyecto todos los días en su esquinita, tecleando como hormiga.  Sabes que está chambeando (o al menos crees saber que está chambeando).  Cuando le preguntan:

—¿Qué rollo? ¿Cómo vas con eso?

—Bien—contesta sencillamente.  No se queja, no da detalles.  Así que asumes que todo va bien, ¿verdad?

Pasa una semana, quizá un mes o dos... tres meses, y de pronto esa persona comienza a enfermarse o a faltar misteriosamente y de buenas a primeras decide renunciar.  Para entonces ya estás a una semana de entregar el sistema que prometiste, y cuando comienzas revisar el código que el cuate hizo, te das cuenta que: 1) lo que hizo no funciona o 2) lo que hizo hace algo pero no era lo que se supone que tenía que hacer.  En otras palabras estás jodido en aprietos.

Entonces el proyecto entra en pánico.  Se oprime el botón rojo y comienzan a sonar alarmas.  Llamadas desesperadas.  Baja de unas cuerdas del techo un equipo S.W.A.T. de desarrolladores externos (o si no tienes pues con los mismos de tu equipo) y se junta a la raza en el war room para ver cómo canijos se puede hacer en una semana lo que un chango no hizo en 3 o 4 meses.  Todo mundo entra en overdrive codificando día, noche y fines de semana casi sin dormir.

Si tienes suerte, y gente MUY talentosa, igual y logras la meta.  Pero muchas veces no es suficiente.

¿Qué fue lo que pasó?  Acabas de ser víctima del SDC, o Síndrome del Desarrollador Callado.

Una de las cosas que a menudo hacemos al desarrollar software es que cuando el schedule anda apretado, lo primero que se hace es mandar a la goma las revisiones de código, las pruebas unitarias, etcétera.  Es decir, lo primero en sacrificarse en aras del calendario, normalmente son las buenas prácticas de desarrollo de software, que irónicamente son tu más valiosa herramienta para terminar a tiempo y con calidad. 

Lo que acaba ocurriendo es que si las sacrificas y tienes uno de esos desarrolladores con SDC, lo más probable es que esa persona no esté entendiendo los requerimientos y/o no tenga las habilidades para pasarlos a código y tiene demasiado temor de que se sepa.  Así que no pide ayuda, no se queja, no hace preguntas.  Simplemente se va a su esquinita y hace el intento.  Cuando va pasando el tiempo y se acerca el deadline (por algo trae dead la palabra) esa persona comienza a sentir la presión que a menudo se manifiesta en enfermedad/desaparición.

No me malinterpreten, conozco dos o tres desarrolladores excelentes, algo anti-sociales, que chambean en su cubículo/esquina, calladitos, enclaustrados una semana o dos y cuando emergen salen con una fregonería de código.  Pero son dos o tres de un montononal que conozco.

Lo peor es que la solución al SDC casi siempre es bien simple: hacer revisiones frecuentes del avance, no solo a lo que se ve (es decir, las pantallas, páginas, o lo que sea visible del sistema), sino a nivel código.  Cada semana (cuando MUCHO) juntar a otro desarrollador, y a un tester o persona que conozca los requerimientos: —A ver, vamos a ver cómo va esa pantalla.

No se trata de traer a la raza a latigazos, y tampoco se trata de hacer que la raza no le busque por su cuenta.  Se trata de no esperarse para descubrir las broncas cuando es demasiado tarde para hacer algo al respecto.  Sobre todo de que no se atasque el proyecto por cosas sencillas.  Yo, personalmente, si me atoro con algo (ya googulié, y ya lo intenté de dos o tres formas distintas) más de 3 o 4 horas y no puedo salir de ahí, inmediatamente agarro uno de mis compañeros y comienzo a explicarle el problema.  A veces con solo explicarlo se me viene una idea que resuelve el atorón, y cuando no, ellos me pueden dar ideas nuevas o enfoques que a mí no se me habían ocurrido.  Por muy chicho que creas ser, nunca faltan los días—o meses jejeje—en los que puedes caer en un lapsus brutus.

Así que si son uno de esos desarrolladores con SDC, por amor de Diosito, levanten la mano cuando se les atore la carreta.  No se esperen a que sea demasiado tarde.  Les prometo que nadie los va a morder.

smile_shades

Evento de Microsoft en El Paso

Dado que no sé si el grupo de usuarios de .NET de El Paso ya pasó a mejor vida, les paso información de un evento que realizará Microsoft este próximo jueves.  Se me hizo interesante, ya que últimamente he estado hablando de IIS 7 y ASP.NET:

MSDN Events: What’s New in IIS7 and Extending ASP.NET 2.0 Application Services

Thursday, January 31, 2008 12:00 PM - 4:00 PM
Welcome Time: 11:30 AM

Theater - Cinemark Tinseltown USA

11855 Gateway West
El Paso Texas 79936
United States

Para registrarse y obtener más detalles sobre el evento, vayan a la siguiente dirección:

http://msevents.microsoft.com/cui/EventDetail.aspx?culture=en-US&EventID=1032359805

Tengan en mente que este evento es en inglés (que igual no es problema).  También tomen en cuenta que aunque la página de registro dice que es de 1PM a 5PM, esto es tiempo del Centro así que sería de 12PM a 5PM tiempo local.

Les resalto los temas que me parecieron interesantes:

Session 1 | Safer, Smarter, Stronger: What’s New for Web Developers in IIS7

  • Authentication methods and integration between ASP.NET and IIS 7
  • Writing IIS managed handlers and modules
  • How the IIS protocol listeners support hosting WCF services on TCP, Named Pipes and more
  • IIS handler permissions, request filtering and administration lists
  • How the XML replacement for the Metdata Config file makes it easy to duplicate Web servers
  • Features and protocols that make IIS 7 secure right out of the box

Session 2 | Extending ASP.NET 2.0 Application Services

  • Membership, role and profile provider overviews
  • How to configure the built-in providers and use the basic login, role and navigation controls
  • How to create and integrate a custom provider
  • Using application services from AJAX and Silverlight clients
  • Using ASP.NET 3.5 client application services from a Windows client.

Espero verlos ahí. smile_shades

Posted from Diario de un Dotnetero | 0 Comments
Filed under: ,

¿Dónde quedó el usuario ASPNET en Windows Vista? ¿Y qué $#!N&@2 es eso de los Application Pools?

Hoy aprendí algunas cosas más al continuar con mis aventuras de desarrollo ASP.NET en Windows Vista.  Muchas de estas cosas aparentemente no son nuevas, vienen desde IIS 6 que era la versión incluida con Windows Server 2003, pero yo nunca los usé, así que hasta ahora me vengo enterando.

La primer lección salió cuando andaba buscando el usuario ASPNET de mi máquina para asignarle permisos de escritura sobre un directorio donde mi aplicación permite que los usuarios suban archivos.  Después de un rato de jugar Where's Waldo con el usuario, me convencí que simplemente no existía.  Resulta que el ASP.NET Worker Process—el proceso bajo el cual se ejecuta el código de ASP.NET—corre ahora por default bajo la cuenta NETWORK SERVICE (aunque esto se puede cambiar fácilmente).  Ah, y por cierto, el Worker Process ahora se llama w3wp.exe, en lugar de aspnet_wp.exe.

La segunda lección vino cuando quise correr mi aplicación.  Resulta que si usas módulos HTTP (<httpModules>) en tu web.config, recibirás un mensaje de error porque IIS 7 intenta correr las aplicaciones por default en un Application Pool llamado—duh—DefaultAppPool, y éste tiene un Managed Pipeline Mode puesto a Integrated.

¿Güat?  A ver si me puedo explicar.  Si abres la consola administrativa de IIS y te vas a Application Pools, verás algo como esto:

De cajón, Vista traía los dos primeros—Classic .NET AppPool y DefaultAppPool.  El tercero fue creado cuando instalé SQL Server Reporting Services, así que por ahora ignóralo.

Lo primero que me pregunté fue ¿qué $#!N&@2 demonios es eso de los Application Pools?

Resulta que es una manera muy padre de segregar y asignar una aplicación Web—o más correctamente su Application Domain—a un Worker Process determinado.  Un Pool puede tener varios AppDomains, y estos estarán separados de los que corran en otros pools. Considera este ejemplo:

 

Aquí tenemos tres aplicaciones de ASP.NET, cada una con su directorio virtual.  Las primeras dos están asignadas al primer Application Pool, y la tercera aplicación está asignada al segundo.  Esto es EXCELENTE por varias razones:

¿Que pasaba antes si una falla en una de las aplicaciones web hacía que se reciclara el Worker Process?  Pues todas las aplicaciones se "reiniciaban"—botando posiblemente a las sesiones y todo el show—porque los Application Domains están corriendo en el mismo proceso ejecutable. Me ha pasado. Teníamos una applicación Web corriendo en el mismo servidor que un servicio Web (en una máquina con Windows 2000 si mal no recuerdo), y de vez en cuando la aplicación hacía que se reciclara el Worker Process—maldito Crystal Reports—llevándose entre las patas al Web Service.  Ahora es posible asilar ese tipo de fallas.

¿O qué pasaría si quiero correr una aplicación de ASP.NET v1.x en el mismo servidor que una de ASP.NET v2.x?  Un Worker Process solo puede correr una versión del .NET Framework, hasta donde sé, así que con Application Pools ahora puedes lograrlo.

Y más relevante para el problema que yo tenía, IIS 7 tiene una manera distinta de manejar los httpModules—llamado Managed Pipeline Mode. DefaultAppPool usa Integrated. Así que lo que tenía que hacer en mi caso era asignar el directorio virtual de mi aplicación al Classic .NET AppPool que utiliza el modo Classic, para no tener que cambiar la configuración (y posiblemente código) de mi aplicación.

Si inspeccionas las opciones avanzadas de un Application Pool te das cuenta que puedes configurar cosas interesantes. 

Las que me llamaron la atención fueron:

  • .NET Framework Version. Para seleccionar qué versión quieres utilizar para las aplicaciones Web que corren en el Pool, o si no quieres permitir que corra código administrado (p.ej. una aplicación de ASP clásico o PHP que no tenga nada que ver con .NET).
  • Managed Pipeline ModeIntegrated utiliza el modo IIS 7, donde la configuración de los httpModules están centralizados y supuestamente tiene varios beneficios que aún no conozco; Classic permite que cada aplicación web mantenga su configuración.
  • Identity.  La cuenta de usuario y bajo el cual corre el Worker Process. Esto afecta directamente los permisos de seguridad de las aplicaciones en el Pool.  Los valores posibles son: NetworkService, LocalService, LocalSystem, SpecificUser; este último por si quieres especificar una cuenta creada por ti.
  • Identity Specific User Credentials.  Para poner las "credenciales" (el password pues) del usuario si usas Identity=SpecificUser.
  • CPU Limit, Limit Interval y Limit Action.  Sirven para limitar el porcentaje de CPU que consume el Worker Process en un tiempo determinado y hacer algo si se excede, como por ejemplo, matarlo.
  • Private Memory Limit y Virtual Memory Limit.  Sirven para limitar la memoria real y virtual que utiliza el Worker Process. ¿Alguna vez le has pegado a un System.OutOfMemoryException? Yo si, y no es divertido.

Una vez que comencé a entender este rollo, asignar mi aplicación al Pool correcto fue súper sencillo.  Simplemente te vas a las opciones avanzadas de tu directorio virtual y lo cambias.

 

Enjoy smile_shades
More Posts Next page »