No todos los problemas se resuelven programando, a algunos hay que hacerles la magia…

http://sergiot2.com/blogimages/2008/06Jun/18_magia.jpg

Un post de reflexión :D, y que servirá de referencia a otros.

Recurrentemente ante situaciones donde estás horas y horas, con un problema y no encuentras el código que lo haga funcionar, visitas todos los foros, en español, inglés, y hasta chino, y nada, y a la gente que envías un email esta apretada con sus quehaceres, lo último que queda es hacer la magia.

¿Pero qué es la magia?. La magia es la experiencia, el sentido común, y la habilidad que vas acumulando conforme aumenta tu participación en proyectos (exitosos o no). No se han dado cuenta que su ki, aumenta después de cada proyecto?, pues una manera de comprobarlo es revisando los primeros códigos que hacíamos, y que cuando los revisas, has los llegas a negar… pero esa es otra historia.

Ahora la adquisición de conocimientos es de todo el contexto: compañeros, proyecto, usuarios, y todo lo que rodea al proyecto. aprendes buenas prácticas, aprendes malas prácticas, (ya sabes que no hacer), aprendes de los buenos jefes de proyectos, también de los malos, incrementa tu capacidad de negociación, y tomar responsabilidad, sobre todo para que no tener que resolver bugs de otros te chanten muertitos de otros, aprendes a tratar con las personas, después de tratar con los usuarios, aprendes aguantar a los compañeros chinches, (no se como se dirá en otros países, pero alguien chinche es aquella persona que hace llegar al límite tu nivel de paciencia).

¿Y como aplico la magia para resolver un problema de programación?

Lo primero, es saber donde buscar, y donde preguntar, y a quién preguntar, recordar que probablemente nosotros no seamos los primeros con el mismo problema. El detalle viene en que quizás la solución no encaje en nuestra aplicación, o sea muy trabajosa, o sea muy compleja, entonces la opción es dar una alternativa, al requerimiento del usuario.

Debemos analizar nuevamente el requerimiento y buscar soluciones alternativas, hombre que de alguna manera tienes que satisfacer el requerimiento del usuario. Y estas alternativas dependiendo del requerimiento pueden variar, quizás haciendo cambios en el diseño, lo solucionemos, o quizás anexando información, ya la magia nos dirá que hacer.

Un ejemplo:

Problema: Desde una página aspx, estoy enviando los productos seleccionados en la página, y estoy abriendo un popup a través de JavaScript, pero si los navegadores tienen habilitado bloquear los popups, la aplicación pierde de alguna manera el flujo actual, y si estoy limpiando los productos seleccionados después de hacer postback, los productos seleccionados se pierden, y el usuario no sabe si tiene que volver a seleccionar los productos.

Solución: Buscar el código JavaScript para detectar si el usuario tiene activada esta opción.

Re-Problema: El problema puede venir, por ejemplo si para abrir el popup estamos registrando el código desde una página ASP.NET, y para hacerlo esto necesita un postback, ahora si el postback hace otros eventos, y dependiendo de nuestro código, tengamos que hacer más código para no perder algunas variables que estemos usando, y que todo funcione correctamente, y se hace todo un rollo.

Solución-Alternativa: Cambiar el diseño, e indicar al usuario que productos están seleccionandos. Así, si el navegador usuario tiene habilitado el bloqueo de popups, no tengo que hacer código extra por que le estoy informado cuales son productos seleccionados, y que no tiene que volverlo hacer.

Y eso, no todo se resuelve programando.

Por eso siempre ante alguna pregunta de código media marciana, siempre pregunto cual es el requerimiento, y quizás esta re-pregunta demuestre que no queremos ayudar o desconocimiento del tema que puede ser cierto, pero quizás no necesitemos un código marciano, solo cambiar de alguna manera el requerimiento.

Saludos,

Elementos html Flash validos por la W3C

Hay que tener algunas consideraciones a la hora de embeber el html de flash en nuestras páginas web y que este sea un código válido por la W3C.

Lo primero que tenemos que tener en cuenta es no usar el objeto embed, que lo encontramos por ejemplo en las referencias de YouTube:

   1: <object width="425" height="344">
   2:    <param name="movie" value="http://www.youtube.com/v/MrMNHwmd9Hc&hl=en">
   3:    </param>
   4:    <embed src="http://www.youtube.com/v/MrMNHwmd9Hc&hl=en" 
   5:           type="application/x-shockwave-flash" width="425" height="344">
   6:    </embed>
   7: </object>

Este objeto embed, no es parte de la especificación XHTML, y por ende no pasara la validación. El ajuste consiste en no usar el objeto embed, y en su lugar sólo usar el objeto param:

   1: <object width="425" height="344" 
   2:      data="http://www.youtube.com/v/42znqcedrX0"
   3:      type="application/x-shockwave-flash" >
   4:    <param name="movie" value="http://www.youtube.com/v/42znqcedrX0" />            
   5: </object>

Veamos el caso por ejemplo de un MP3 Player:

   1: <object type="application/x-shockwave-flash" 
   2:      data="http://sergiot2.com/audio/player.swf"
   3:      width="290" height="24" id="audioplayer1">
   4:    <param name="movie" value="http://sergiot2.com/audio/player.swf" />
   5:    <param name="FlashVars" 
   6:          value="playerID=1&amp;autostart=yes&amp;loop=yes&amp;" +
   7:                 "bg=0xf8f8f8&amp;leftbg=0xeeeeee&amp;lefticon=0x666666&amp;" + 
   8:                 "rightbg=0xcccccc&amp;rightbghover=0x999999&amp;" + 
   9:                 "righticon=0x666666&amp;righticonhover=0xFFFFFF&amp;" +
  10:                 "text=0x666666&amp;slider=0x666666&amp;track=0xFFFFFF&amp;" +
  11:                 "border=0x666666&amp;loader=0x9FFFB8&amp;" + 
  12:                 "soundFile=http%3A%2F%2Fsergiot2.com%2Faudio%2FGeorgeMichael-Faith.mp3" />
  13:    <param name="quality" value="high" />
  14:    <param name="menu" value="false" />
  15:    <param name="bgcolor" value="#FFFFFF" />
  16: </object>

NOTA: En el atributo value use “+” para concatenar por cuestión de espacio en el blog se debería colocar todo junto sin concatenar. Notar además como a través de la parámetro FlashVars, podemos pasar variables al objeto flash, si es que lo necesitará. Si desea MP3 Audio Player en su sitio web:

Si desean verificar la validación, pueden hacerlo en la siguiente página: http://sergiot2.com/blog/validW3C.aspx.

Mas sobre el tema de Flash, y la validación:

Saludos,

Cuando una aplicacion deja de funcionar, por la conexion a la BD

El otro día estaba revisando una aplicación, que inexplicablemente dejo de funcionar el acceso a datos. No se mostraba nada en la portada, no había información, -chess… nos hackearon. Pero revisando la base de datos todo estaba bien, toda la información estaba como debería estar. Era una aplicación Web de terceros, revise la configuración del proveedor de acceso a datos, y entre una de las configuraciones que era SQL Server, me decía que no se podía establecerla conexión, sin más detalles. Pero la base de datos estaba online y funcionando correctamente, comencé  a indagar cuales fueron los últimos cambios, si se instalaron add-ins, o se cambio alguna configuración, y nada.

Para la conexión estaba usando un login SQL, así que entre con ese usuario por el SQL Server Management Studio, y el mensaje fue clarísimo:

SQL Server 2005 - Your password is expired.

You password is expired. You must enter another password before you can log on”.

Y esto debido que durante la creación del usuario marcaron la opción, “Enforce password expiration“:

SQL Server 2005 - Enforce password expiration

Cabe resaltar que esta feature de SQL Server 2005 sólo funciona sobre Windows Server 2003 (imagino que W2k8 también debe funcionar).

La recomendación es activar esta opción, por medidas de seguridad. Pero imagino que cada organización tendrá sus propias políticas. Pero vamos al tema, que pasa si habilito la opción, que recomendaciones se debe tener en la aplicación.

¿Dónde cambiamos el número de días de expiración?

Pues usa la misma política que las cuentas de Windows. Nos vamos Herramientas administrativas, e ingresamos a Local Security Policy. Dentro de Account Policies -> Password Policy, cambiamos los días para la edad máxima del password.

http://sergiot2.com/blogimages/2008/06Jun/12_LocalPolicy.jpg

Nota: Estas son las configuraciones por defecto, no la tomen como ejemplo, aún no soy el indicado para hablar de estos temas, todavía no me han dado completamente un server para jugar (6). Artículo relacionado al tema: SQL Server 2005 Login Properties to Enforce Password Policies and Password Expiration.

¿Y cómo le digo a la aplicación que cambie el password?

Pues el administrador debería tenerlo agendado en el Outlook con un reminder de un par de días. Pues si no pasa esto, podemos activar alertas programáticamente, para notificar ante la necesidad de cambiar la cadena de conexión.

   1: static void Main(string[] args)
   2:    {
   3:      String cn = "data source=192.168.1.8; database=northwind; uid=tinysa; pwd=password";
   4:  
   5:      using (SqlConnection sql = new SqlConnection(cn))
   6:      {
   7:        using (SqlCommand cmd = new SqlCommand(
   8:                        "SELECT * FROM Customers WHERE CompanyName LIKE 'a%'",
   9:                        sql))
  10:        {
  11:          try
  12:          {
  13:            sql.Open();
  14:            SqlDataReader rd = cmd.ExecuteReader();
  15:  
  16:            Console.Write("Customers: ");
  17:            while (rd.Read())
  18:            {
  19:              Console.WriteLine("{0}, ", rd["CompanyName"]);
  20:            }
  21:  
  22:            sql.Close();
  23:          }
  24:          catch (SqlException sqlEx)
  25:          {
  26:            if (sqlEx.Number == 18487)
  27:            {
  28:              //send email, sms a webMaster.
  29:              Console.WriteLine("El password de la conexion ha expirado");
  30:            }
  31:          }
  32:          catch (Exception ex)
  33:          {
  34:            Console.WriteLine("hubo un error: {0}", ex.ToString());
  35:          }
  36:        }
  37:      }
  38:  
  39:      Console.ReadLine();
  40:  
  41:    }

NOTA: El ejemplo es didáctico, la cadena de conexión debería ser colocada en el archivo web.config, y este debería ser encriptado.

Notar que el código de Error de SQL de este mensaje es el número 18487, y si sucede este problema podemos enviarle un mensaje por msn, bloquearlo hasta que cambie la cadena de conexión y lo actualice en el web.config configurar para enviarle un email al encargado de la Web o Aplicación, notificándole lo sucedido.

Hay otros tipos de errores, que también podríamos considerar:

  • 15113 – Login failed for user ‘%.*ls’ Reason: Password validation failed. The account is locked out.
  • 18463 – Login failed for user ‘%.*ls’. Reason: Password change failed. The password cannot be used at this time.
  • 18464 – Login failed for user ‘%.*ls’. Reason: Password change failed. The password does not meet policy requirements because it is too short.
  • 18465 – Login failed for user ‘%.*ls’. Reason: Password change failed. The password does not meet policy requirements because it is too long.
  • 18466 – Login failed for user ‘%.*ls’. Reason: Password change failed. The password does not meet policy requirements because it is not complex enough.
  • 18467 – Login failed for user ‘%.*ls’. Reason: Password change failed. The password does not meet the requirements of the password filter DLL.
  • 18468 – Login failed for user ‘%.*ls’. Reason: Password change failed. An unexpected error occurred during password validation.
  • 18487 – Login failed for user ‘%.*ls’. Reason: The password of the account has expired.
  • 18488 – Login failed for user ‘%.*ls’. Reason: The password of the account must be changed.

Extraído de: Changing Passwords Programmatically. Imaginen que el administrador creo el user, y marco la opción cambiar el password la primera vez de login, y no lo haga y nos de esa password para conectarnos a la aplicación… hay casos….

Hay otra opción, y es cambiar el password a través de una página de administración. La clase SqlConnection, tiene un método llamado ChangePassword, para esta tarea. En esta referencia hay un código ejemplo, sólo hay que agregar la siguiente línea (la número 5):

   1: private static string ModifyConnectionString(
   2:        string connectionString, string NewPassword)
   3:    {
   4:      //AGREGAR ESTA LINEA
   5:      SqlConnection.ChangePassword(connectionString, NewPassword);
   6:  
   7:      // Use the SqlConnectionStringBuilder class to modify the
   8:      // password portion of the connection string. 
   9:      SqlConnectionStringBuilder builder =
  10:          new SqlConnectionStringBuilder(connectionString);
  11:      builder.Password = NewPassword;
  12:      return builder.ConnectionString;
  13:    }

Es como cambiarla usando el Sql Server Management Studio, y este código podríamos incluirlo dentro de las páginas de administración, ya que necesita que algún admin ingrese el nuevo password para el usuario.

Saludos,

no que no, Geeks.ms en el buscador de firefox :D, y mas…..

Desde hace tiempo que vengo usando y agregando todos los sitios comunes que visito, al buscador de IE, ya que te da mucha flexibilidad para agregar un nuevo buscador, y hasta se puede hacer que el buscador te de algunas otras funcionalidades, como la de validador.

Pero Firefox, no te da está misma flexibilidad, bueno sin add-ins y en la instalación por defecto, no he logrado hacerlo. Pero Firefox si soporta OpenSearch, pero no todos los sitios tienen habilitado el OpenSearch :(, y hasta esperar que lo habiliten…

Pues existe una solución muy sencilla y práctica, basada en OpenSearch, y es simular nosotros la página con el descubrimiento para búsquedas. La receta:

   1. Primero creamos un archivo Xml, con el siguiente código:

   1: <OpenSearchDescription>
   2:    <ShortName>Geeks.ms Search</ShortName>
   3:    <LongName>
   4:      Geeks.ms - Todo lo que los geeks de Windows y .Net tiene que contar
   5:    </LongName>
   6:    <Description>
   7:      Geeks.ms - Todo lo que los geeks de Windows y .Net tiene que contar.
   8:    </Description>
   9:    <Tags>buscador, asp.net, windows, search, visual studio</Tags>
  10:    <Url type="text/html" template="http://geeks.ms/search/SearchResults.aspx?q={searchTerms}"/>
  11:    <Image height="16" width="16" type="image/x-icon">http://geeks.ms/favicon.ico</Image>
  12:    <Attribution>
  13:      Copyright http://sergiot2.com/blog. All rights reserved.
  14:    </Attribution>
  15:    <SyndicationRight>open</SyndicationRight>
  16:    <AdultContent>false</AdultContent>
  17:    <Language>es</Language>
  18:    <OutputEncoding>UTF-8</OutputEncoding>
  19:    <InputEncoding>UTF-8</InputEncoding>
  20: </OpenSearchDescription>

Por poner un ejemplo. El shortName es lo que aparecerá en el cuadrito de búsqueda, atención con la URL, y como enlazamos a la búsqueda, image para el icono, y otros atributos.

   2. Ahora en la página deseada y dentro del elemento head, agregamos lo siguiente:

   1: <link title="Geeks.ms Search" type="application/opensearchdescription+xml" 
   2:         rel="search" href="searchGeeks.xml" />

Notar, que acá hacemos referencia al archivo xml, creado previamente.

   3. Ahora sólo nos queda abrir la página en cuestión: http://sergiot2.com/blog/searchEngine.aspx, en Firefox obviamente.

   4. Nos vamos al buscador, y agregamos el buscador para “Geeks.ms Search“. Notar que en la opción de agregar saldrá el icono del sitio donde estén, en este caso, el icono de mi sitio:

http://sergiot2.com/blogimages/2008/06Jun/06_addSearch.jpg

5. Pero no se preocupen no van a tener que ver el feo icono 😀, después de agregar el buscador ya toma el icono asignado en el archivo xml:

http://sergiot2.com/blogimages/2008/06Jun/06_searchGeeks.jpg

No son grandes cosas, pero siempre ahorra un poco de tiempo para búsquedas en sitios que usamos con mayor frecuencia.

Ahora sólo deje tres buscadores, el de Geeks.ms para buscar entradas y no repetirlas, o alguna entrada que vi y necesito, mi blog que también uso como repositorio de algún código, y el MS Events, que visito de vez en cuando para buscar un WebCast, este último esta programado para buscar WebCast en inglés, si desean le hacen el cambio en la URL para buscar los de nuestro idioma.

P.D.: A medida que los vaya necesitando voy a ir agregando otros buscadores que uso, da mucha lata hacerlo todos juntos :D.

Saludos,

Moviendo Aplicaciones Web ASP.NET 2.0 a IIS 7.0?

A ver veamos, nosotros tenemos dos modos de correr una Aplicación Web en IIS 7.0, en modo clásico o en modo integrado, y esto lo configuramos a nivel de un Application Pool.

El modo clásico, es como conocemos al trabajo de ASP.NET con IIS 6.0, el modo integrado es nuevo modelo de trabajo de IIS 7.0, que entre una de las features, me van permitir extender mi servidor, y usar funcionalidades propias que sólo tenia en ASP.NET, con otros lenguajes como Php, ASP clásico, o en páginas estáticas. Revisar el siguiente enlace para mayores detalles: ASP.NET Integration with IIS7.

Ahora, estoy moviendo una Aplicación Web ASP.NET que funciona de lujo en IIS 6.0, a trabajar con IIS 7.0, ¿qué recomendaciones debemos tener?

Primero, si estamos presionados y debemos hacer el cambio de aplicaciones Web a IIS 7.0, para ayer, la opción altamente recomendable es usar el modo clásico (configurar el Application pool). Tenemos que tener permiso para administrar el servidor, nos vamos a Application Pools, y verificamos que por lo menos uno de ellos o creamos uno nuevo, tenga la propiedad Managed Pipeline Mode, en Classic. Con esta configuración si nuestra aplicación Web funcionaba bien en un servidor IIS 6.0, debería funcionar bien en un servidor IIS 7.0.

Application Pool - Advanced Settings

¿Qué pasa si a nivel de un Web Site, solo tengo un Application Pool?, y para no perjudicar a otras aplicaciones Web, debo mantener el modo integrado, que será para todas las Aplicaciones Web dentro del Web Site. Hay algunos cambios que debemos hacer, si estamos usando determinas features.

Por ejemplo si estamos usando modules o handlers, que están agregados en el web.config, al ejecutar la aplicación Web, obtendremos el siguiente error: HTTP Error 500.22 – Internal Server Error, “An ASP.NET setting has been detected that does not apply in Integrated managed pipeline mode“.

Y el problema es que en el modo integrado, los modules y handlres, deben ser colocados dentro de las secciones <modules>, y <handlres>, de la sección <system.webServer>. Este último nos permite hacer configuraciones a nivel de IIS, y llevárnosla en la aplicación dentro del web.config, y no tener que replicarlas en un nuevo servidor.

La solución para este escenario es sencilla, podemos usar el siguiente comando, AppCmd.Exe, que hará la migración de las secciones en el web.config:

> %windir%system32inetsrvAppcmd migrate config “<ApplicationPath>”

Donde:

  • “<ApplicationPath>” = “Default Web Site/”  o
  • “<ApplicationPath>” = “Default Web Site/WebApplication/”

Si todo salió bien, nos deberá salir un mensaje: Successfully migrate section “system.web./httpModules” | “system.web/httpHandlers”.

Para mayores detalles sobre los cambios o features, en las cuales debemos tener cuidado, revisar: ASP.NET 2.0 Breaking Changes on IIS 7.0.

Atención, si la migración al modo Integrado les esta dando mucha lata y necesitan la Aplicación Web, lo mejor será usar el modo clásico. Lo ideal debe ser probarlo localmente (no producción), si todas las features de nuestra Aplicación funcionan correctamente en el modo integrado, antes de subirla a producción.

Saludos,

[Demo] Usando el nuevo control ListView de ASP.NET con VS2008

Llegando un poco tarde, pero aquí están las demos del evento pasado: Descargar demo.

Es un sitio Web, para el Upload y Search de productos. Las páginas implementadas son el Upload Manual:

Upload Manual

Y la página search:

 Search Products

Para el diseño de la aplicación usa la plantilla Commerce, de los Templates for ASP.NET. Estos son algunas entradas relacionadas al tema: VS2008 – CSS for Developer (Dummies Designers), e Instalar un ASP.NET Starter Kit, paso a paso.

Es una aplicación en capas simple, creada usando Visual Studio 2008, puedes descargarse un trial de Visual Studio 2008 Professional, para revisar la aplicación. Para la generación de la capa de acceso a datos use el Web Service Software Factory, no es necesario tenerlo instalado para ejecutar la aplicación, revisar la personalización realizada para agregar nuevos métodos a los que soporte por defecto, ya que el ObjectDataSource que vamos a usar más adelante necesita un método contar, par la paginación personalizada.

En la primera demo puede ver el uso de ListView+ObjectDatasSurce, habilitado con la función para insertar registros (lo que falta al gridView, ya que sólo permite update, y delete). Se ve también como manejar eventos de inserción (agregar parámetros antes de que se produzca la inserción, o realizar tareas después de la inserción como el manejo de errores). Además como buscar controles en el ListView, y como agregar comandos adicionales a un ListView.

En la segunda demo hay un search de products, y se hace paginación personalizada tanto de SQL como de ASP.NET, usando el ObjectDataSource, además de soportar ordenamiento. Y el ObjectDataSource te va de lujo cuando pasas Objetos y List<Objetos>, entre tus capas, un buen artículo relacionado a esto: Performance: Datos en Memoria con ADO.NET IV.

Y para los estilos (CSS) del ListView, los descargue desde la siguiente página: CSS Table Gallery. Ah dentro de la descarga se encuentra los scripts necesarios para generar la base de datos en SQL Server 2005.

Creo que eso es todo, nuevamente: Link de descarga.

Otros artículos sobre el ListView:

P.D.: Hay algunas tareas pendientes en el Sitio Web, que por cuestiones de tiempo ya no se pudo hacer, como el uso de configSections, en el web.config por ejemplo. En futuras entregas espero ponerle más cosas, que está será la nueva aplicación para demos :D.

Saludos,