Feb 8

Encontré un caso truculento el día de hoy. Tengo un ListView que tiene un ItemTemplate dentro del cual estoy poniendo controles de tipo CheckBox. El usuario puede elegir varios de éstos, y cuando se oprime un botón necesito validar la cantidad de casillas que seleccionó.

Aquí está mi ListView y el botón.

ASP:
  1. <asp:ListView ID="ListadoPlanes" runat="server"
  2.         ItemPlaceholderID="AquiVanItems" DataSourceID="ODSPlanes">
  3.     <LayoutTemplate>
  4.   <table width="100%" border="0" cellspacing="0" cellpadding="3">
  5.     <tr>
  6.       <td class="TdDegra">Seleccione hasta 4 opciones</td>
  7.       <td class="TdDegra">Nombre</td>
  8.     </tr>
  9.     <asp:PlaceHolder ID="AquiVanItems" runat="server"></asp:PlaceHolder>
  10.    </table>                           
  11.     </LayoutTemplate>
  12.     <ItemTemplate>
  13.     <tr>
  14.       <td>
  15.         <asp:CheckBox ID="Plan" runat="server" />
  16.         <asp:HiddenField ID="PlanId" runat="server" Value='<%#Eval("idplan")%>' />
  17.       </td>
  18.       <td><%#Eval("Nombre")%></td>
  19.  </tr>
  20.     </ItemTemplate>
  21. </asp:ListView>
  22. <asp:Button ID="Button1" runat="server" Text="Button" />

En la línea 15 estoy creando el CheckBox con el ID igual a "Plan". Necesito guardar, en cada renglón, el ID de mi tabla, que se llama "idplan", por lo que en la línea 16 creo un HiddenField y establezco su valor con mi id. Ahora en cada renglón tendré una casilla de verificación y un campo con el id de mi tabla.

Ahora bien, para iterar en los renglones del ListView e ir checando cada CheckBox, usa el siguiente código:

VB.NET:
  1. Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
  2.  
  3.     Dim CuentaCtrl As Int16 = 0
  4.     Dim i As Integer
  5.     Dim ElCheckBox As CheckBox
  6.     Dim ElHidden As HiddenField
  7.     For i = 0 To ListadoPlanes.Items.Count - 1
  8.         ElCheckBox = CType(ListadoPlanes.Items(i).FindControl("Plan"), CheckBox)
  9.         ElHidden = CType(ListadoPlanes.Items(i).FindControl("PlanId"), HiddenField)
  10.         If ElCheckBox.Checked = True Then
  11.             CuentaCtrl = CuentaCtrl + 1
  12.             'Si necesitas hacer algo con tu id en este ciclo,
  13.             'accedelo usando ElHidden.Value
  14.         End If
  15.     Next
  16.  
  17.     If CuentaCtrl> 2 Or CuentaCtrl = 0 Then
  18.         'Hacer algo
  19.  
  20.     Else
  21.         'Hacer algo
  22.     End If
  23.  
  24. End Sub

En la iteración estoy revisando las opciones seleccionadas y al final solamente tomo una decisión dependiendo de cuántas casillas están marcadas.

Suerte!

Feb 7

En ocasiones puedes tener muchos CheckBoxes desplegados de tal manera que no te permite crear un CheckBoxList (por ejemplo, en tablas), y requieres validar que el visitante no ha marcado más de n número de casillas.

Para hacerlo necesitas colocar todos tus CheckBoxes dentro de un control Panel para poder iterarlos e ir contando. Puedes implementar la validación con un CustomValidator.

La página ASP.NET debe tener lo siguiente:

ASP:
  1. <asp:Panel ID="MiPanel" runat="server">
  2.     <asp:CheckBox ID="Op1" runat="server" />
  3.     <asp:CheckBox ID="Op2" runat="server" />
  4.     <asp:CheckBox ID="Op3" runat="server" />
  5.     <asp:CheckBox ID="Op4" runat="server" />
  6. </asp:Panel>
  7. <asp:CustomValidator ID="CustomValidator1"
  8.                                   runat="server" CssClass="validador" Display="Static"
  9.                                   ErrorMessage="Por favor seleccione un máximo de 2 opciones."
  10.                                   ForeColor="" OnServerValidate="ValidaCheckboxes"></asp:CustomValidator>

Ahí están tus cuatro opciones y tu validador, nota que la función a la que manda llamar el validador se llama ValidaCheckboxes, la cual debe aparecer en tu código de servidor:

VB.NET:
  1. Sub ValidaCheckboxes(ByVal sender As Object, ByVal args As ServerValidateEventArgs)
  2.  
  3.     Dim Ctrl As Control
  4.     Dim Chk As CheckBox
  5.     Dim CuentaCtrl As Int16 = 0
  6.     For Each Ctrl In MiPanel.Controls
  7.         If TypeOf (Ctrl) Is CheckBox Then
  8.             Chk = CType(Ctrl, CheckBox)
  9.             If Chk.Checked = True Then
  10.                 CuentaCtrl = CuentaCtrl + 1
  11.             End If
  12.         End If
  13.     Next
  14.  
  15.     If CuentaCtrl > 2 Then
  16.         args.IsValid = False
  17.     Else
  18.         args.IsValid = True
  19.     End If
  20.  
  21. End Sub

Listo, es todo lo que necesitas. Suerte!

Feb 3

Es importante establecer los tipos de datos correctos en las variables de ASP.NET que utilizas para realizar operaciones con datos que provienen de una base de datos de SQL Server. Pero ¿qué tipos de datos cuando estás programando en ASP.NET corresponden a cada tipo de datos definido en SQL Server?

Aquí esta la lista de equivalencias:

SQL Server data type

CLR data type (.NET Framework)

varbinary

Byte[]

binary

Byte[]

varbinary(1), binary(1)

byte, Byte[]

image

None

varchar

None

char

None

nvarchar(1), nchar(1)

Char, String, Char[]

nvarchar

String, Char[]

nchar

String, Char[]

text

None

ntext

None

uniqueidentifier

Guid

rowversion

Byte[]

bit

Boolean

tinyint

Byte

smallint

Int16

int

Int32

bigint

Int64

smallmoney

Decimal

money

Decimal

numeric

Decimal

decimal

Decimal

real

Single

float

Double

smalldatetime

DateTime

datetime

DateTime

sql_variant

Object

User-defined type(UDT)

Same class that is bound to the user-defined type in the same assembly or a dependent assembly.

table

None

cursor

None

timestamp

None

xml

None

Encontrarás la lista completa en esta página.

Feb 2

Si creas una página en ASP.NET y en su evento Load pones lo siguiente:

VB.NET:
  1. Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
  2.         Label1.Text = Session.SessionID & " " & Session("idsesion")
  3.         Response.Write(Session.SessionID)
  4.     End Sub

notarás que cada vez que oprimes Refresh o Actualizar en tu navegador, la variable de sesión se modifica. Definitivamente es raro porque uno siempre ha sabido que la variable de sesión debe ser la misma durante todo el tiempo que el visitante permanece visitando la aplicación.

Bueno, la variable de sesión permanece igual siempre y cuando se coloque algún valor en el estado de la sesión. (yo tampoco entiendo muy bien la razón).

El caso es que para solucionar el problema "de raíz", creé una variable de sesión en el código del archivo Global.asax, justo cuando se crea la sesión (checa la línea 21):

VB.NET:
  1. <%@ Application Language="VB" %>
  2.  
  3. <script runat="server">
  4.  
  5.     Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
  6.         ' Code that runs on application startup
  7.     End Sub
  8.    
  9.     Sub Application_End(ByVal sender As Object, ByVal e As EventArgs)
  10.         ' Code that runs on application shutdown
  11.     End Sub
  12.        
  13.     Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
  14.         ' Code that runs when an unhandled error occurs
  15.     End Sub
  16.  
  17.     Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
  18.         ' Code that runs when a new session is started
  19.         'La siguiente linea evita que session.sessionid se modifique cada
  20.         'vez que se oprime Refresh en el navegador
  21.         Session("idsesion") = Session.SessionID
  22.     End Sub
  23.  
  24.     Sub Session_End(ByVal sender As Object, ByVal e As EventArgs)
  25.         ' Code that runs when a session ends.
  26.         ' Note: The Session_End event is raised only when the sessionstate mode
  27.         ' is set to InProc in the Web.config file. If session mode is set to StateServer
  28.         ' or SQLServer, the event is not raised.
  29.     End Sub
  30.        
  31. </script>

Esto hace que el estado de la sesión permanezca sin modificarse y ahora el código del Response.Write(Session.SessionID) citado anteriormente regresa siempre el mismo valor. =)

Ene 28

¿Estás buscando tu propio icono (indicador) de espera para Ajax?

Esta página es muy buena, te permite crear el tuyo personalizado con los colores que desees, tiene una amplia variedad y los diseños están atractivos. La salida es un gif animado que puedes descargar.

http://www.ajaxload.info/

Ene 18
Deshacerse del archivo thumbs.db
icon1 Recursos Web | icon2 General | icon4 01 18th, 2008| icon3No Comments »

Windows XP genera un archivo oculto llamado thumbs.db en cada carpeta. Este archivo guarda las vistas previas (thumbnails) de las fotografías que hay en esa carpeta. Esto sirve para acelerar la visualización de vistas previas la próxima vez que entras a esa carpeta.

En ocasiones este archivo nos estorba, por ejemplo cuando vas a hacer un archivo zip o subir una carpeta completa por FTP, el archivo thumbs.db es incluído, ocupando espacio y tiempo innecesario.

He llegado a notar que en una carpeta que tiene 1MB ocupado en varias imágenes, el archivo thumbs.db ocupa otro MB.

Para deshacerte de este archivo, entra al Panel de Control y haz clic en Opciones de Carpeta.

Panel de control

A continuación marca la casilla que dice No alojar en caché las vistas en miniatura.

Thumbs.db

Esto hará que ya no aparezca el archivo thumbs.db y si ya existe en alguna carpeta y lo borras, no regresará. La única desventaja será que cuando entres nuevamente a una carpeta con imágenes, el proceso de creación de vistas previas será un poco más lento porque ya no habrá caché. Esto no debe ser un problema si tienes una cantidad moderada de imágenes en cada carpeta.

Dic 27

Prodigy Infinitum es el proveedor más grande de Internet en México. Recientemente tomaron la determinación de bloquear el puerto 25 para combatir el SPAM o correo basura.

Para los proveedores de hosting esto es un problema, porque los clientes utilizan principalmente Infinitum y perdieron la capacidad de enviar mensajes desde sus oficinas usando Outlook o Thunderbird. Sí los pueden descargar porque el puerto de POP que es el 110 no fue bloqueado.

¿Cómo solucionarlo?

Si eres un proveedor de hosting, esta es la mejor solución:

Antes que nada, no cambies tu servidor de e-mail a un puerto diferente. Déjalo en el puerto 25 porque todos los servidores de mail externos (hotmail, gmail, yahoo, etc) intentarán conectarse con tu servidor de mail usando el puerto 25. Si pones a tu servidor de mail a escuchar en otro puerto, los correos de servidores externos no lo encontrarán y tus clientes no recibirán mails.

Ok, con ese asunto aclarado, tienes que hacer lo siguiente:

Al seleccionar un nuevo puerto, no puedes elegir el que se te venga a la mente, busca en Internet información sobre los diferentes puertos porque hay varios números que ya están reservados para otros servicios, como FTP, bases de datos, etc. El 26 está libre y lo puedes usar sin problemas.

1. Redirigir el tráfico del puerto 26 al 25

Si tu servidor de mail lo soporta, indícale que escuche en el puerto 25 y en el 26 (u otro número de tu elección) y sáltate toda la explicación siguiente del paso 1. Si no soporta múltiples puertos, entonces deberás redirigir todo el tráfico del puerto externo 26 (u otro número de tu elección) al puerto interno 25.

Esto también se puede llamar "port mapping". Estas son dos herramientas que me recomendaron para hacerlo, aunque no las he probado:

  1. Greyware Detour - http://www.greyware.com/software/detour/index.asp
  2. Port mapper, v1.40 - http://www.kmint21.com/free/port-map.zip

Una tercera opción y que sí he probado, es utilizar el Windows Firewall/Internet Connection Sharing (ICS). Para hacerlo, primero asegúrate que el servicio esté encendido y marcado como automático.

Firewall de Windows

Puedes abrir el Firewall de Windows desde el panel de control:

Panel de Control

Si no está encendido, enciéndelo:

Enciende el Firewall

Haz clic en la pestaña Advanced, selecciona Public bajo Network Connection Settings y oprime el botón Settings....

Pestaña Advanced

En la ventana que aparece, oprime Add... para dar de alta una nueva entrada y realizar la redirección o mapeo de puertos. Notarás que yo ya lo he hecho, mi entrada se llama Programa de mail.

Dar de alta la entrada de la redirección

Esta es la configuración de dicha entrada, he puesto una dirección IP ficticia, modifícala por tu IP pública:

Configuración de redirección

Acepta los cambios y la redirección ha sido realizada. Ahora, todo el tráfico que llegue a tu servidor solicitando el puerto 26 será reenviado al puerto 25. De esta manera es como si tu servidor de mail estuviera escuchando por ambos puertos.

Solamente ten en cuenta que si no tenías habilitado tu Firewall y lo acabas de habilitar, tienes que abrir los puertos para los demás servicios, como FTP, Web, etc. Esto lo haces desde la misma ventana, pero en la pestaña Exceptions. Haz clic en Add Port... y configura el puerto que deseas abrir:

Abrir otros puertos

Busca una lista de puertos en Internet para saber cuáles debes abrir.

Lo que me gusta de esta solución es que no hay que instalar nada adicional en el servidor, y el Firewall de Windows corre como un servicio, así que te aseguras de que siempre estará activo, aún después de reiniciar el servidor.

2. Pedir a tus clientes que modifiquen la configuración de su Outlook o Thunderbird

Suponiendo que seleccionaste el puerto 26, tendrás que pedirles a tus clientes que realicen la modificación del Servidor de Salida (SMTP) en sus clientes de e-mail (Outlook, Thunderbird, Eudora, etc), borrando el número 25 y colocando el 26.

SMTP

Los pasos para realizar esta configuración varían de programa a programa, busca información en Internet para saber cómo hacer este cambio.

Al usar el puerto 26, el Outlook de tus clientes se conectará a tu servidor por el puerto 26, tu servidor lo redireccionará al puerto 25, donde está escuchando tu servidor de mail. Tu cliente nunca utilizó el puerto 25, que ha sido bloqueado.

Si tienes otros clientes cuyo proveedor de Internet no ha bloqueado el puerto 25, entonces puedes pedirles que realicen el cambio al puerto 26 o que no hagan nada. De cualquiera de las dos formas podrán enviar y recibir correo sin problemas.

Dic 13

Para obtener el tamaño, ancho y alto de una imagen, usa el siguiente código:

Primero importa:

VB.NET:
  1. Imports System.IO
  2. Imports System.Drawing

Para obtener tamaño, ancho y alto de una imagen:

VB.NET:
  1. Dim fs As FileStream = New FileStream("c:\miruta\miimagen.jpg", FileMode.Open, FileAccess.Read, FileShare.Read)
  2. Dim LaImagen As System.Drawing.Image
  3. LaImagen = System.Drawing.Image.FromStream(fs)
  4. Label3.Text = "Tamaño: " & Convert.ToInt32(fs.Length) & "<br/>"
  5. Label3.Text = Label3.Text & "Ancho: " & LaImagen.Width & "<br/>"
  6. Label3.Text = Label3.Text & "Alto: " & LaImagen.Height & "<br/>"
  7. fs.Close()
  8. fs = Nothing

Para modificar su tamaño:

VB.NET:
  1. Dim fs As FileStream = New FileStream("c:\miruta\miimagen.jpg", FileMode.Open, FileAccess.Read, FileShare.Read)
  2. Dim LaImagen As System.Drawing.Image
  3. LaImagen = System.Drawing.Image.FromStream(fs)
  4.  
  5. Dim ancho, alto As Integer
  6. ancho = 100
  7. 'este calculo es para que la foto no pierda proporciones
  8. alto = Math.Floor((100 / LaImagen.Width) * LaImagen.Height)
  9.  
  10. Dim NuevoBitmap As Bitmap = New Bitmap(ancho, alto)
  11. Dim Graficos As Graphics = Graphics.FromImage(NuevoBitmap)
  12. Graficos.CompositingQuality = Drawing2D.CompositingQuality.HighQuality
  13. Graficos.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
  14. Graficos.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
  15. Dim Rectangulo As Rectangle = New Rectangle(0, 0, ancho, alto)
  16. Graficos.DrawImage(LaImagen, Rectangulo)
  17. NuevoBitmap.Save("c:\miruta\thumb.jpg", NuevoBitmap.RawFormat)
  18. fs.Close()
  19. fs = Nothing

Este código es muy útil para crear vistas previas de nuestras imágenes (o thumbnails) automáticamente.

Dic 13

Para subir un archivo al servidor mediante una aplicación web ASP.NET 2, usa el siguiente código:

ASP:
  1. <asp:FileUpload ID="FileUpload1" runat="server" /><br />
  2. <asp:Button ID="Subir" runat="server" Text="Subir foto" />

VB.NET:
  1. If FileUpload1.HasFile Then
  2.    FileUpload1.SaveAs("c:\miruta\" & FileUpload1.Filename)
  3. End If

Asegúrate de que el fólder en el que vas a grabar tus archivos tenga permisos de escritura por parte del usuario ASPNET y/o NETWORK SERVICE.

Dic 12

Para añadir metatags al elemento head utilizando programación (ASP.NET 2), primero asegúrate de que el elemento head tenga su propiedad runat=server.

En el código de la página coloca lo siguiente:

VB.NET:
  1. Dim cabeza As HtmlHead
  2. cabeza = DirectCast(Header, HtmlHead)
  3. Dim meta As HtmlMeta = New HtmlMeta()
  4. meta.Attributes.Add("cache-control", "no-store, must-revalidate, private")
  5. meta.Attributes.Add("Pragma", "no-cache")
  6. cabeza.Controls.Add(meta)

Funciona aunque la página esté ligada a un master page.

« Previous Entries Next Entries »