captcha para ASP.NET y para Classic ASP

Captcha -> http://es.wikipedia.org/wiki/Captcha.

En imágenes:

screenshot of ASP.NET CAPTCHA server control

Más claro?

Algunos códigos de Captchas para ASP.NET:

Y para el clásico ASP, si para el ASP 3.0: http://captchas.net. Fácil de implementar, aunque nunca hayas trabajado con el clásico ASP, como yop :D.

P.D.: Y ustedes dirán, ASP 3.0 ¿?, pues hay muchos sitios aún con ASP, y hasta la migración a ASP.NET, se les debe dar solución a los problemas comunes de la Web.

Saludos,

Post cruzado

DataList vs Listview

En una de las pasadas charlas, me hicieron una muy buena pregunta: -¿Qué debo usar DataList o ListView?. Recuerden que ListView es uno de los nuevos controles de .Net 3.5.

En cuanto a funcionalidades tenemos que el control DataList admite la selección, edición, y eliminación, y por otro lado el control ListView admite selección, edición, eliminación, inserción, y ordenamiento, y con la ayuda del control DataPager, el control ListView soporta paginación built-in, ósea agregas el control, configuras declarativamente y listo.

Recuerden que los dos controles son para visualizar data, ósea es independiente si lo usas con un ObjectDataSource, LinqDataSource, SqlDataSource, o lo cargas programáticamente.

Vayamos a un ejemplo, para ver la diferencia en el diseño, y el render que estos dos controles producen:

Por cierto recuerden que hay dos niveles en los uso de controles para mostrar data, directamente proporcionales, a más funcionalidad built-in menos controlamos el html generado. Por ejemplo con el GridView, habilitando propiedades tenemos paginación, ordenamiento y más, con el DataList tenemos menos funcionalidades (selección, edición) pero la generación del html es más flexible, y en el control Repeater no tiene ninguna funcionalidad pero nosotros controlamos completamente la generación del html.

Digamos que el control ListView es la evolución de un control Repetaer y DataList juntos, y mucho mejor.

Ahora vayamos con la diferencia entre el control ListView y el DataList:

Si queremos hacer lo hemos puesto arriba con un control ListView sería así:

   1: <asp:ListView ID="lstvAds" DataSourceID="LinqDataSource1" 
   2:    ItemPlaceholderID="itemContainer" runat="server">
   3:     <LayoutTemplate>
   4:         <ul class="classifiedlist">
   5:             <asp:PlaceHolder ID="itemContainer" runat="server" />
   6:         </ul>
   7:     </LayoutTemplate>
   8:     <ItemTemplate>
   9:         <li><a href='<%# Eval("Id", "ShowAd.aspx?id={0}") %>'>
  10:             <img border="0" width="56" height="56" ....
  11:                 src='<%# Eval("PreviewImageId","...") %>' /></a>
  12:             <br /><b><%# Eval("Title") %></b> -
  13:             <%# Eval("Price","{0:c2}") %>
  14:         </li>
  15:     </ItemTemplate>
  16: </asp:ListView>

Para explicar un poco, este modelo de templates. LayoutTemplate, es el estructura base para la distribución de nuestros elementos, en este caso es una lista. ¿Cómo sabe el ListView donde colocar al elemento?, hablamos del clásico ItemTemplate, pues usando el control PlaceHolder le estamos indicado que este será el lugar del elemento. Este es un modo de usarlo, en la ayuda de MSDN, encontrarán otro modo. De ItemTemplate, que decir?, ya lo conocen todos no?

Si quiero hacer lo mismo, pero con un DataList tendría que ser algo así:

   1: <asp:DataList RepeatDirection="Horizontal" ID="dtAds" 
   2:      DataSourceID="LinqDataSource1" runat="server"
   3:      RepeatLayout="Flow">
   4:     <ItemTemplate>
   5:         <ul class="classifiedlist">
   6:             <li><a href='<%# Eval("Id", "ShowAd.aspx?id={0}") %>'>
   7:                 <img border="0" width="56" height="56" ...
   8:                     src='<%# Eval("PreviewImageId","...") %>' /></a>
   9:                 <br /><b><%# Eval("Title") %></b> -
  10:                 <%# Eval("Price","{0:c2}") %>
  11:             </li>
  12:         </ul>
  13:     </ItemTemplate>
  14: </asp:DataList>

En cuanto al DataList, para lograr algo parecido debemos hacer que el tipo de Layout sea Flow, y no un Table. Ahora en cuanto al ItemTemplate, noten que hemos puesto el elemento <ul> dentro de el, otra posibilidad hubiera sido colocarlo dentro del HeaderTemplate, y dentro del FooterTemplate colocar el </ul>. Aunque el html generado no sería el que esperamos, más adelante veremos el porque.

El html generado por el ListView es:

   1: <div id="ctl00_Main_UpdatePanel1">
   2:     <ul class="classifiedlist">
   3:         <li><a href='ShowAd.aspx?id=16'>
   4:             <img border="0" width="56" ...
   5:                 src='PhotoDisplay.ashx?photoid=17&amp;size=small' /></a>
   6:             <br />
   7:             <b>Soda Stereo</b> - S/. 30.00 </li>
   8:         <li><a href='ShowAd.aspx?id=15'>
   9:             <img border="0" width="56" ...
  10:                 src='PhotoDisplay.ashx?photoid=16&amp;size=small' /></a>
  11:             <br />
  12:             <b>Red Bull</b> - S/. 23.00 </li>
  13:     </ul>
  14: </div>

Y el html generado por el DataList:

   1: <div id="ctl00_Main_UpdatePanel1">
   2:     <span id="ctl00_Main_dtAds"><span>
   3:         <ul class="classifiedlist">
   4:             <li><a href='ShowAd.aspx?id=16'>
   5:                 <img border="0" width="56" ...
   6:                     src='PhotoDisplay.ashx?photoid=17&amp;size=small' /></a>
   7:                 <br />
   8:                 <b>Soda Stereo</b> - S/. 30.00 </li>
   9:         </ul>
  10:     </span><span>
  11:         <ul class="classifiedlist">
  12:             <li><a href='ShowAd.aspx?id=15'>
  13:                 <img border="0" width="56" ...
  14:                     src='PhotoDisplay.ashx?photoid=16&amp;size=small' /></a>
  15:                 <br />
  16:                 <b>Red Bull</b> - S/. 23.00 </li>
  17:         </ul>
  18:     </span></span>
  19: </div>  

A primera vista podemos apreciar que el html generado por el ListView es más limpio que el generado por el control DataList, noten que los dos están dentro de un UpdatePanel de ahí el div contenedor, pero noten que además el control DataList genera un elemento span para el control en si, y por cada ítem, también genera un elemento span. Pero el ListView genera html puro, por así llamarlo. Digamos que es como una diferencia entre el control Literal y el control Label, recuerden que el uso de este elemento span por la mayoría de controles de ASP.NET al hacer render, es lo que permite darle colores, diseño, y todo eso directamente a través de las propiedades del control, o usando por ejemplo los ItemStyle, y todos los ABCStyle. En cambio los que no usan span, como control Literal, Repeater o el ListView, nosotros podemos personalizar completamente el diseño del html a generar.

Por cierto, si hubiéramos puesto el elemento <ul> en el HeaderTemplate y el elemento </ul>, en el FooterTemplate, del control DataList, el resultado generado sería algo así:

   1: <div id="ctl00_Main_UpdatePanel1">
   2:     <span id="ctl00_Main_dtAds"><span>
   3:         <ul class="classifiedlist">
   4:     </span><span>
   5:         <li><a href='ShowAd.aspx?id=16'>
   6:             <img border="0" width="56" height="56" class="col_photo" alt="Ad preview photo."
   7:                 src='PhotoDisplay.ashx?photoid=17&amp;size=small' /></a>
   8:             <br />
   9:             <b>Soda Stereo</b> - S/. 30.00 </li>
  10:     ...
  11: </div>

Noten que el elemento <ul>, colocado dentro del HeaderTemplate, también es contenido dentro de un control span, y debido a esto podemos usar el HeaderStyle, para personalizar el diseño del título de mi lista. Y en esto caso parece que sería mejor el primero modelo, ya que este último va contra las reglas de anidación, y a su vez esto va contra los estándares.

Quedo claro las diferencias?, digamos que el control ListView es una mixtura del control Repeater, podemos personalizar el contenido html generado a nuestro antojo, y el control DataList, podemos implementar funciones de selección, edición, y eliminación, pero además es recargado ya que podemos implementar ordenamiento, inserción, y paginación, claro con la ayuda del control DataPager.

Y que debo usar?, pues depende del escenario, pero me parece que el ListView va a dejar atrás al control DataList, sobretodo si estamos acostumbrados a explotar el uso de CSS.

Algunos artículos usando el control ListView:

P.D.: Nadie dijo que con el control Repeater no se pueda paginar, o por ahí alguien diga yo he hecho inserciones con el Repeater :S, pero de manera built-in por así llamarlo, no permiten estas funcionalidades.

Saludos,

Post cruzado

MCPD 70-547: Requerimientos y Disenio de la Aplicacion

En cada tema que tratemos de la serie MCPD, iniciaremos con una pequeña frase o pregunta, que llame a la reflexión, claro siempre y cuando sea necesario :).

Cuando los requerimientos se terminan después que se termina la aplicación :S…” (f1)

Aunque para las metodologías ágiles, los requerimientos estáticos no son buenos, para eso están las iteraciones para contemplar los nuevos requerimientos o los cambios en algunos requerimientos. Y esto es normal y aceptable, y muchas veces el negocio necesita de estos cambios. Pero hombre, en algún momento tiene que acabar el proyecto, para poder liberar el software, y los nuevos requerimientos podrían pasar a una segunda versión del software. Como pueden ver hay distintos escensarios, y no hay una manera única de afrontar todos los escenarios.

Pero este cambio, en los requerimientos o los nuevos requerimientos, no son el problema, si es que son considerados dentro del ciclo desarrollo, como lo hacen las metodologías ágiles a través de las iteraciones, en lapsops de tiempo razonables. Cuando me refería a la frase f1, me refería más a los requerimientos ambiguos o incompletos, por ejemplo, te dicen: -Quiero una interfaz de usuario bonita. Y tu puedes hacer una interfaz de usuario bonita, para ti, pero no bonita para la persona que te lo pidió, y muchos de estos tipos de requerimientos son una de las cosas que afectan en retrasos en los tiempos de entrega del software.

Ojo, que tampoco se entienda que no se aceptan nuevos requerimientos una vez iniciado, a veces el negocio es el exige nuevos requerimientos, o cambios, imaginemos que el estado, o algún organismo dentro del estado, cambia el formato de la presentación de los registros de la contabilidad, no vas a decir, -no vamos hacer eso por que esta fuera de tiempo dentro de nuestro proyecto. Es que sin eso, puede que tu software le sea inútil a la persona que lo use, y simplemente tienes que hacerlo o hacerlo. Se nota la diferencia en los cambios de estos tipos de requerimientos porque el negocio lo pide, a los cambios por requerimientos ambiguos?, y claro tampoco es que nunca se acabarán los requerimientos, ya que en algún momento se tendrá que cerrar el proyecto, y los nuevos requerimientos deberán ir en una nueva versión del software.

Notar que los requerimientos, no son lo mismo que diagramas de casos de uso. Se pueden complementar, pero no son lo mismo, los requerimientos se pueden resumir como lo que quiere el usuario, y los casos de uso como puntos de vista del proceso que reflejan como cumpliremos con los requerimientos. Y por lo que he visto, puedes hacer proyectos sin casos de uso, pero no puedes hacer proyectos sin requerimientos, y si los haces, el software no será lo que el cliente quiso. Con esto no digo que los diagramas de casos de uso sean innecesarios, es más muchos veces estos podrían aclarar la forma de afrontar un proceso dentro de un escenario, pero con respecto a los diagramas UML pienso que se debería usar siempre y cuando sean necesarios, y no solamente por cumplir, salvo que dentro de tu contrato este contemplado hacer todos los diagramas, aunque algunos de estos no sean ni usados. Pero otro post, responderé al último comentario del último link :D.

Y lograr tener “los requerimientos”, es una tarea que implica empeño y cuidado. Si no me equivoco creo que dentro de la preguntita: “¿Por qué fallan los proyectos?”, un alto porcentaje lo tienen requerimientos incompletos. De lo contrario no se hablaría de la Ingeniería de Requerimientos o Análisis de Requerimientos, ni habrían métodologías para la Ingeniería de Requerimientos. Se clasifican diversos tipos de requerimientos, y me parece bueno, ya que te permite saber si al terminar el software has satisfecho todas las necesidades de la mayoría, no todos, de la organización:

Business Requirements, normalmente la visión del negocio, como por ejemplo, después de la implementación del sistema, quiero estar entre las principales organizaciones de mi rubro.

User Requirements, son los requerimientos que tiene que hacer el usuario final para cumplir su trabajo, como por ejemplo, quiero que cada vez que realice una venta, el stock de mi producto disminuya.

Functional Requirements, estos pueden derivarse de los requerimientos del negocio, y los requerimientos del usuario, y son básicamente los requerimientos que necesitas para el desarrollo, como por ejemplo, voy a necesitar crear controles de búsqueda.

Quality-of-Service Requirements, o antes llamados requerimientos no funcionales, como dice el nombre, estos son los que darán la calidad a tu servicio, y estos giran alrededor de la performance, escalabilidad, estándares, y otros. -No quiero que mis transacciones demoren más de 60 segundos. Sobre este termino se está enfatizando bastante, y muchas guías de implementación de soluciónes, ahondan sobre ellos: Sun Java Enterprise System Deployment Planning Guide, ahi podemos encontrar otros términos como seguridad, disponibilidad entre otros.

Ya tienes los requerimientos completos?, eso es lo que crees, y viene el siguiente paso, el diseño mi aplicación. Para los que tiene amplia experiencia, esta no debe ser una tarea difícil, claro dependiendo del escenario. Pero que pasa si es tu primera aplicación?, una recomendación que me gusto del libro, y que siempre recomiendo, es revisar aplicaciones Web ya existentes. Es obvio, que pocas veces encontrarás a algún buen amigo que te comparta su aplicación. Pero hasta que llegue el amigo, que nos comparta sus aplicaciones, nosotros tenemos Starter Kits, y otras aplicaciones que hay de MS, y otros modelos que encontremos en la web.

No siempre nuestro primer diseño, será el mejor, pero hay que tratar de que sea el menos peor, y leer las recomendaciones de gente que haya hecho algunos diseños, y tratar por lo menos que nuestro diseño sea flexible a los cambios, como un modelo en capas.

Para comprobar el correcto diseño de una aplicación, podemos realizar prototipos y hacer pruebas de concepto (POC), y verificar la validez de nuestro diseño. Ojo, tampoco van a tomar todos los requerimientos para hacer el prototipo *-), si no, ya no fuera prototipo. Como comentario, en muchas empresas (casa de software), apuestan por la realización de prototipos para implementar nuevas tecnologías o vender algunos productos, muchas veces estos prototipos son hasta gratis para las empresas que acepta la implementación, obvio que el beneficio viene después tanto para la empresa donde se implementa el prototipo, y para la casa de software.

En el libro, hablan sobre dos tipos de prototipos Mock-up y POC, digamos que Mock-up es como sólo el diseño de la aplicación, y POC es la funcionalidad que debe cumplir con los requerimientos, y al final los dos hacen el prototipo.

A ver resumiendo:

  • Tener claro los requerimientos, no pasar requerimientos ambiguos o incompletos. Hay algunas características para saber que tenemos un buen requerimiento, que no se ambiguo, que este completo, que sea necesario, que sea fiable, entro otros.
  • Si aparecen cambios en los requerimientos, dejarlos para la siguiente iteración, y si los cambios son grandes e impiden que se cierre un proyecto, dejarlos para la siguiente versión.
  • Tener cuidado al hacer el diseño de la aplicación, y realizar un pequeño prototipo para verificar la validez de nuestro modelo.

Y algo que me olvidaba, siempre tratar de que los requerimientos estén escritos y aprobados. Ya que muchas veces esta es nuestra carta de defensa, y es que a veces se proyecta una duración de dos meses para un grupo de N requerimientos, pero en el primer mes se cambian requerimientos ambiguos o incompletos, y ahora son N^ requerimientos, y si no tenemos documentado los requerimientos iniciales, al final la culpa de no terminar en los dos meses, adivinen de quién es?, y es ahí cuando el programador deja de tener vida, se debería considerar que si hubo requerimientos ambiguos, el trabajo ya se avanzo, y si se hizo mal o bien (por que fue con requerimientos ambiguos), ya esta hecho, y se invirtió tiempo en el, se debe ser consciente que ya no se terminará, en dos meses, quizá se necesita de un par de semanas más. Tampoco se debe cerrar a que no se termina en dos meses y punto, si necesita para ese tiempo, simplemente por que se necesita, se podría contar con otro recurso, que ayude a corregir la implantación de los cambios en los requerimientos, para que así los demás recursos puedan continuar con su trabajo normal, y se termine en el tiempo requerido. Revisar la Tabla 2, de este PDF, y ver como afecta requerimientos incompletos en el ciclo de vida desarrollo de software, diseño y codificación.

Otros Links que encontré por ahi:

P.D.: Esto es la parte teoría de lo que he visto que ha pasado, y que yo mismo he pasado, en los proyectos, aunque en los proyectos es más emocionante y más presionante, full adrenalina :).

Saludos,

Post cruzado