Archivo categoría ASP.NET 2.0 / 3.5

Cómo agregar el salto de línea a los caracteres válidos de un FilteredTextBoxExtender

En el Ajax Control Toolkit de ASP.NET, hay un control llamado FilteredTextBoxExtender que sirve para filtrar los caracteres que se pueden ingresar en un TextBox. Esto es útil, por ejemplo, para permitir únicamente el ingreso de números si estamos capturando un código postal mexicano.

Bueno, estaba usándolo en un TextBox con la propiedad TextMode establecida en MultiLine, lo que en HTML se despliega como un textArea, una caja de texto con múltiples líneas.

Esta es la definición de mi caja de texto y el control de filtrado:

ASP:
  1. <asp:TextBox ID="Tags" runat="server" TextMode="MultiLine" Width="200px"
  2.             Height="150px"></asp:TextBox>
  3.         <cc1:FilteredTextBoxExtender ID="Tags_FilteredTextBoxExtender" runat="server"
  4.             Enabled="True" TargetControlID="Tags"
  5.             ValidChars="abcdefghijklmnopqrstuvwxyz1234567890 ABCDEFGHIJKLMNOPQRSTUVWXYZ">
  6.         </cc1:FilteredTextBoxExtender>

Como puedes ver, estoy permitiendo la entrada de letras mayúsculas, minúsculas, números y espacios. Pero como se trata de una caja de texto con múltiples líneas, obviamente quiero que se permita teclear saltos de línea cuando el individuo presione la tecla enter o intro.

Este caso es truculento, porque no puedes hacerlo en la página aspx, lo tienes que hacer en el código de servidor, de esta forma:

VB.NET:
  1. Tags_FilteredTextBoxExtender.ValidChars = Tags_FilteredTextBoxExtender.ValidChars & vbCrLf

Como sabrás, vbCrLf significa un salto de línea en Visual Basic, y lo que hace esa línea es añadirlo a los caracteres válidos.

Medio truculento pero funciona!

No hay Comentarios

Cómo pasar el nombre del usuario logueado como parámetro a un ObjectDataSource

Los ObjectDataSource soportan por default diferentes tipos de parámetros, como controles, cookies, Form, QueryString, Profile y Session. Sin embargo si quieres pasar como parámetro el UserName del usuario logueado no lo puedes hacer con ninguno de los tipos antes mencionados.

Para hacerlo debes utilizar el evento Selecting del ObjectDataSource.

Esto funciona así, aquí tenemos el ObjectDataSource:

ASP:
  1. <asp:ObjectDataSource ID="ODSEjemplo" runat="server"
  2.         OldValuesParameterFormatString="original_{0}" SelectMethod="GetData"
  3.         TypeName="BLLObtenerDatos">
  4.     </asp:ObjectDataSource>

Fíjate como no hemos incluido ningún parámetro. Éste lo generamos en el code-behind:

VB.NET:
  1. Protected Sub ODSEjemplo_Selecting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ObjectDataSourceSelectingEventArgs) Handles ODSEjemplo.Selecting
  2.         e.InputParameters("MiParametro") = User.Identity.Name
  3.     End Sub

Nótese que en el ejemplo, el método GetData recibe un sólo parámetro de tipo String, mismo que coincide con el tipo de User.Identity.Name

Así de sencillo.

No hay Comentarios

Cómo leer un ConnectionString del web.config mediante código

En nuestro web.config guardamos los ConnectionStrings de nuestras bases de datos.

Ejemplo:

ASP:
  1. <connectionStrings>
  2.     <add name="MiConnectionString" connectionString="Data Source=Servidor\INSTANCIASQL;Initial Catalog=MiBaseDeDatos;Persist Security Info=True;User ID=NombreDeusuario;Password=xxxxxxxxxx" providerName="System.Data.SqlClient" />
  3.   </connectionStrings>

Es posible leer estos valores desde code-behind, de la siguiente forma:

VB.NET:
  1. Dim SuperSecreto As String = System.Web.Configuration.WebConfigurationManager.ConnectionStrings("MiConnectionString").ConnectionString

1 Comentario

Utilizar un DataPager haciendo el DataBind en Code-Behind

Como expliqué en mi post anterior:
http://www.viale.com.mx/2009/06/09/como-utilizar-un-control-datapager-con-listview-para-crear-paginas-de-registros/

es posible utilizar un DataPager con un ListView de la siguiente manera:

ASP:
  1. <asp:ListView ID="LVRegistros" runat="server" DataKeyNames="IdRegistro"
  2.         ItemPlaceholderID="AquiVanLosItems">
  3.     <LayoutTemplate>
  4.         <table width="100%" border="0" cellpadding="5" cellspacing="0">
  5.             <tr>
  6.                 <td class="tdDatosTitulo">
  7.                     Nombre
  8.                 </td>
  9.             </tr>
  10.             <asp:PlaceHolder ID="AquiVanLosItems" runat="server"></asp:PlaceHolder>
  11.             <tr>
  12.                 <td colspan="7" class="TdPie">Páginas:
  13.                     <asp:DataPager ID="Pager1" runat="server" PageSize="30">
  14.                         <Fields>
  15.                             <asp:NumericPagerField ButtonCount="50" />
  16.                         </Fields>
  17.                     </asp:DataPager>
  18.                 </td>
  19.             </tr>
  20.         </table>
  21.     </LayoutTemplate>
  22.     <ItemTemplate>
  23.         <tr>
  24.             <td>
  25.                 <%#Eval("IdCarpeta")%>
  26.             </td>
  27.         </tr>
  28.     </ItemTemplate>
  29.     <EmptyDataTemplate>
  30.         No existen registros.
  31.     </EmptyDataTemplate>
  32. </asp:ListView>

Ahora bien, si haces el Bind con un ObjectDataSource o algún control similar en el archivo .aspx, todo funciona perfectamente.

Sin embargo, si estás haciendo el DataBind en el código de servidor (code-behind), entonces te darás cuenta de que al hacer clic en la página número 2 (por ejemplo) del paginador, no ocurre nada, se sigue mostrando la primera página.

Esto es debido a que estás llenando el ListView en el código de servidor.

Para solucionarlo, debes colocar el siguiente procedimiento en tu archivo .aspx.vb:

VB.NET:
  1. Protected Sub LVRegistros_PagePropertiesChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.PagePropertiesChangingEventArgs) Handles LVRegistros.PagePropertiesChanging
  2.         Pager1.SetPageProperties(e.StartRowIndex, e.MaximumRows, False)
  3.         LVReflexiones.DataBind()
  4.     End Sub

Ahora pruébalo y verás como todo funciona como debe.

8 Comentarios

Cómo utilizar un control DataPager con ListView para crear páginas de registros

Supongamos que tenemos el siguiente ListView que toma datos de una tabla de la base de datos:

ASP:
  1. <asp:ListView ID="LVRegistros" runat="server" DataKeyNames="IdRegistro"
  2.         ItemPlaceholderID="AquiVanLosItems">
  3.     <LayoutTemplate>
  4.         <table width="100%" border="0" cellpadding="5" cellspacing="0">
  5.             <tr>
  6.                 <td class="tdDatosTitulo">
  7.                     Nombre
  8.                 </td>
  9.             </tr>
  10.             <asp:PlaceHolder ID="AquiVanLosItems" runat="server"></asp:PlaceHolder>
  11.         </table>
  12.     </LayoutTemplate>
  13.     <ItemTemplate>
  14.         <tr>
  15.             <td>
  16.                 <%#Eval("IdRegistro")%>
  17.             </td>                               
  18.         </tr>
  19.     </ItemTemplate>
  20.     <EmptyDataTemplate>
  21.         No existen registros.
  22.     </EmptyDataTemplate>
  23. </asp:ListView>

Como puedes ver el primer renglón de la tabla contendrá el texto "Nombre" y los siguientes renglones se llenarán a partir de la información que exista en la base de datos.

Ahora bien, si existieran 50,000 registros, todos ellos aparecerían en la página, lo cual está lejos de ser óptimo.

Lo ideal es mostrar los primeros "n" registros y que después exista un paginador (o pager en inglés) tipo Google, que nos permita ir desplazándonos a través de las diferentes páginas de registros.

Con ASP.NET esto es muy sencillo. Basta incluir un control llamado DataPager dentro del LayoutTemplate del ListView.

El código quedaría así:

ASP:
  1. <asp:ListView ID="LVRegistros" runat="server" DataKeyNames="IdRegistro"
  2.         ItemPlaceholderID="AquiVanLosItems">
  3.     <LayoutTemplate>
  4.         <table width="100%" border="0" cellpadding="5" cellspacing="0">
  5.             <tr>
  6.                 <td class="tdDatosTitulo">
  7.                     Nombre
  8.                 </td>
  9.             </tr>
  10.             <asp:PlaceHolder ID="AquiVanLosItems" runat="server"></asp:PlaceHolder>
  11.             <tr>
  12.                 <td colspan="7" class="TdPie">Páginas:
  13.                     <asp:DataPager ID="Pager1" runat="server" PageSize="30">
  14.                         <Fields>
  15.                             <asp:NumericPagerField ButtonCount="50" />
  16.                         </Fields>
  17.                     </asp:DataPager>
  18.                 </td>
  19.             </tr>
  20.         </table>
  21.     </LayoutTemplate>
  22.     <ItemTemplate>
  23.         <tr>
  24.             <td>
  25.                 <%#Eval("IdCarpeta")%>
  26.             </td>                               
  27.         </tr>
  28.     </ItemTemplate>
  29.     <EmptyDataTemplate>
  30.         No existen registros.
  31.     </EmptyDataTemplate>
  32. </asp:ListView>

El código anterior coloca una lista de números del 1 en adelante que se pueden cliquear para moverse a las diferentes páginas de registros. Si quieres, por ejemplo, que el paginador aparezca arriba y abajo de los registros, simplemente coloca otro DataPager donde lo necesites.

En este caso utilicé dentro de Fields un control llamado NumericPagerField, pero también puedes utilizar NextPreviousPagerField y TemplatePagerField.

Aquí encontrarás la referencia a toda la clase DataPager con la explicación completa de cada uno de sus componentes:
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.datapager.aspx

Nota Si estás haciendo el DataBind en código de servidor (code-behind), lee tambíen este post:
http://www.viale.com.mx/2009/06/09/utilizar-un-datapager-haciendo-el-databind-en-code-behind/

Suerte!

3 Comentarios

Cómo generar automáticamente un archivo ZIP con ASP.NET

En un proyecto en el que estoy trabajando tenía la necesidad de crear un archivo zip que tuviera varios archivos que estaban en un directorio en el servidor. Para no estar generando el zip manualmente cada vez que se pusiera un archivo nuevo y subirlo por FTP, pensé que sería bueno crearlo dinámicamente con código ASP.NET.

Buscando en Google, encontré esta excelente librería:

DotNetZip

Es muy sencilla de usar y los archivos generados se abren correctamente con la herramienta de carpetas comprimidas integrada en Windows y con Winzip.

Instrucciones para generar un archivo zip dinámicamente:

En la página antes mencionada haz clic en Releases y descarga el archivo llamado DotNetZipLib-Runtime-v1.7.zip. Cuando lo descargues, busca una carpeta llamada DotNetZip-v1.7 y dentro de ella encontrarás un archivo llamado Ionic.Zip.dll.

Copia ese archivo a la carpeta Bin de tu aplicación.

Para crear un archivo zip, usa el siguiente código que coloqué en el evento Click de un Button, pero que puedes usar donde te convenga.

Primero especifica que vas a utilizar la librería:

VB.NET:
  1. Imports Ionic.Zip

Después úsalo así:

VB.NET:
  1. Protected Sub CrearZip_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles CrearZip.Click
  2.         Response.Clear()
  3.         Dim ElZip As ZipFile = New ZipFile()
  4.         Using ElZip
  5.             ElZip.AddDirectory("C:\inetpub\wwwroot\App\ArchivosAComprimir\", "Documentos\")
  6.             ElZip.AddFile("C:\inetpub\wwwroot\App\OtrosArchivos\MiArchivo.pdf", "Documentos\")
  7.             ElZip.Save(Response.OutputStream)
  8.         End Using
  9.         Response.AddHeader("Content-Disposition", "attachment; filename=MisDocumentos.zip")
  10.         Response.ContentType = "application/octet-stream"
  11.         Response.End()
  12.     End Sub

Como podrás deducir, AddDirectory añade un directorio completo, incluyendo todos los archivos y carpetas que contenga, recursivamente. AddFile añade un archivo específico.

El segundo parámetro de ambas funciones define el directorio raíz propio del archivo zip generado. No tiene que coincidir con la ruta física donde están ubicados los archivos, este valor lo puedes definir tú. En mi ejemplo, el directorio raíz del archivo zip tendrá un único directorio llamado "Documentos", y bajo él estará MiArchivo.pdf y toda la carpeta ArchivosAComprimir.

Cabe mencionar que en mi ejemplo el archivo será enviado al navegador como si se tratara de una descarga, pero también lo podrías almacenar en el disco duro.

Esta librería permite muchas más funciones, como:

  • Crear archivo zip y agregarle archivos o directorios
  • Listar los archivos dentro de un zip, y extraerlos
  • Modificar un archivo zip existente, con la capacidad de renombrar, remover o agregar nuevos elementos
  • Crear, guardar (como en mi ejemplo), extraer y leer de un stream

Se puede usar con cualquier lenguaje de .NET y cuenta, incluso, con una GUI que puedes usar en Windows.

Ni la librería ni la GUI tienen costo.

Para descargar la librería, la GUI, y el manual de usuario, ve a la página que puse al principio.

No hay Comentarios

Cómo terminar la sesión de un usuario del Membership provider de asp.net

Para terminar la sesión de un usuario logueado mediante el Membership provider de asp.net, utiliza el siguiente código:

VB.NET:
  1. FormsAuthentication.SignOut()
  2. Response.Redirect(FormsAuthentication.LoginUrl)

La segunda línea simplemente redirige a la página establecida como inicio de sesión en el archivo web.config de la aplicación.

Otra manera simple de hacerlo es simplemente colocar el tag LoginStatus que automáticamente añade un vínculo para cerrar la sesión.

Suerte!

No hay Comentarios

Genera un delay en una aplicación ASP.NET

En ocasiones (muy raras tal vez) necesitarás generar un delay. Un tiempo de espera. Simplemente unos segundos en los que la aplicación duerma.

Te preguntarás para qué querría alguien esto. Bueno, uno de los casos en los que puede ser útil es si necesitas simular un tiempo de respuesta lento de la conexión a internet. Por ejemplo, si tienes un UpdateProgress de Ajax que estás probando en un servidor local, el procesamiento puede ser tan rápido que quizás nunca veas tu gif animado girar. En estos casos, puedes colocar un delay que te permita simular que el servidor y/o la conexión tardan un rato en reaccionar.

Para hacerlo, utiliza este código:

VB.NET:
  1. Threading.Thread.Sleep(3000)

Donde el 3000 que pongo son milisegundos, en este caso el tiempo de espera sería de 3 segundos.

2 Comentarios

IE=EmulateIE7 no funciona cuando se coloca en un Master Page

Si estás desarrollando un sitio web en ASP.NET y quieres forzar que se despliegue con compatibilidad de Internet Explorer 7 cuando los usuarios lo visiten en Internet Explorer 8, utiliza el siguiente tag:

HTML:
  1. <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />

Esto es equivalente a visualizar el sitio web en Internet Explorer 8 y oprimir el botón de Vista de Compatibilidad que aparece al lado del botón Actualizar.

Importante:

Si colocas el tag de compatibilidad después de algún tag de hoja de estilos (link href="estilo.css"), no funcionará.

Debe ir antes que cualquier otro, ponlo justo abajo de <head>.

2 Comentarios

Cómo mostrar las fechas en español

Es muy común que tengas que desplegar fechas en una aplicación ASP.NET.
Existen varias funciones para crear, y hacer operaciones con fechas.
En algunos casos, dependiendo de la configuración regional del servidor, tus fechas pueden aparecer en inglés, como:

Friday, January 02, 2009

Para asegurarte de que aparezcan en español utiliza el siguiente código:

VB.NET:
  1. Dim FechaI As String = FechaInicio.ToString("D", System.Globalization.CultureInfo.CreateSpecificCulture("es-MX"))

La variable FechaInicio en el ejemplo es de tipo DateTime ya sea que provenga de algún valor tomado de una base de datos o generado mediante DateTime.Now

Haciéndolo así la fecha aparecerá como:

Viernes, 02 de enero de 2009

El string D indica el formato en el que aparecerá la fecha. Para más opciones visita la documentación de MSDN.

No hay Comentarios