miércoles, 17 de octubre de 2007

Nuestras reglas de programación NET

Archivos básicos de un proyecto:
  1. Un archivo master general en el sitio. Tendrá llamados a los archivos js y css. También puede contener funciones javascript específicas (dentro de la etiqueta <script language="JavaScript">) y clases para modificar el diseño del sitio (dentro de las etiquetas <style>). Alguien deberá estar encargado de este archivo y cualquier cambio que se requiera deberá modificarlo.

  2. Un archivo JS y un archivo CSS

  3. Un archivo en App_Code llamado Routines.vb. Alguien estará encargado de este archivo y todas las rutinas que se quieran incluir deben ser enviadas al encargado con una explicación del funcionamiento de las rutinas. Posteriormente el encargado indicará en qué Namespace y en qué Clase estará contenida la rutina. El encargado también debe realizar un compendio de estas rutinas colocando la explicación de cada una de ellas y los parámetros que reciben (colocando si se reciben por valor o por referencia).

  4. Un archivo Utilerias.dll en la carpeta Bin del proyecto.


Archivo master:
  1. Debe contener al menos dos ContentPlaceHolder: 1) Para mensajes y 2) Para contenido general.

  2. Debe tener un label específico para el título que se utilizará en cada página o sección y el contenido de este label debe cambiar dinámicamente dependiendo de la página donde se encuentre el usuario.

  3. Debe validar la sesión de todas y cada una de las páginas que contendrán este archivo master. Debe existir un arreglo tipo string en el que se especifique cuáles páginas NO serán validadas por sesión (página de inicio de sesión, página para recuperar contraseña, etc.)

  4. Debe contener el menú general del sistema y los links de este menú también pueden requerir validación de sesión o cualquier otra validación necesaria para ser mostrados.

  5. Puede también contener validaciones generales que a veces es conveniente realizar en todas las páginas, pero hay que tener en cuenta que conexiones a la base de datos pueden afectar el performance del sitio. Así mismo se pueden manipular todos los objetos de diseño en la master, de modo que se pueden ocultar ciertos elementos como Header, ContentPlaceHolder, Footer, etc. que no se requieran en cierto momento.


Archivo Routines.vb
  1. Contiene funciones muy específicas de la aplicación. Para la administración de usuario habría funciones como: GuardarUsuario(ByVal StrUsuario As String, ByVal StrPassword As String, ByVal StrNombre As String, ByVal BlnActivo As Boolean), GuardarUsuario(ByVal StrNombre As String, ByVal BlnActivo As Boolean, ByVal IdUsuario As Integer), ActivarUsuario(ByVal BlnActivo As Boolean, ByVal IdUsuario As Integer) y BorrarUsuario(IdUsuario). De modo que GuardarUsuario nos servirá para crear nuevos usuarios, o bien, actualizar la información de los usuarios; ActivarUsuario para activar usuarios y BorrarUsuarios para borrar usuarios.

  2. Los nombres de las funciones deben ser muy descriptivos.

  3. Las funciones deben ser acomodadas o clasificadas mediante Namespaces y Clases. En general Routines.vb tendrá un solo namespace que será el nombre del proyecto como tal. Las clases deben ser específicas para englobar funciones relacionadas entre sí, por ejemplo, la clase Ventas podría contener funciones como GuardarVenta, LimpiarCarrito, CuentaElementosCarrito, etc.

  4. Es obvio que este archivo no contiene controles web de modo que todas las funciones deben arrojar las excepciones mediante el Throw Exception, de este modo, cualquier página que las utilice podrá obtener el error que se haya generado y procesar el error (mostrarlo en pantalla, enviar un correo, etc.)


Utilerias.dll
Esta librería ya contiene funciones muy específicas que podrán ser utilizadas en cualquier parte de la aplicación. Existen validadores, modificadores de strings, conexiones a la base de datos, entre muchas otras funciones.

Consideraciones generales
  1. Utilización de Try donde sea necesario.

  2. Nombres mnemónicos para las variables y funciones. Los nombres de los elementos deben ser entendibles y descriptivos para cualquier persona. El nombre "x" o "VarTKm20" no son descriptivos.

  3. Toda página debe contener un label llamado "lblMensajes" en el cual se mostrará cualquier mensaje de error.

  4. Toda página debe tener su atributo AutoEventWireup en True y la función Page_Load no debe recibir parámetros ni manejar eventos (Handles...). Esto es importante para quien esta acostumbrado a manejar todo desde diseño en Visual y que al dar doble clic en la página automáticamente se crea la función Page_Load.

  5. Los ID's de los controles deben indicar el tipo de control mediante un prefijo establecido. Lo mismo para los tipos de variables.

  6. Todos los acentos y caracteres especiales incluidos en los mensajes, deben ser manejados mediante código HTML, por ejemplo: "La conexi&oacute;n experimenta problemas. Por favor intente de nuevo m&as tarde."

  7. Los títulos y mensajes en general comienzan con mayúscula, siendo que las palabras restantes deben comenzar con minúscula. Un título no aceptable sería "Sección de Datos Personales", el cual deberá ser "Sección de datos personales".

  8. Las variables de sesión deben ser utilizadas únicamente para manejar la sesión de los usuarios. No deben ser utilizados para guardar información que será manipulada entre distintos controles. Por ejemplo una variable de sesión no se utiliza para guardar algo que nos indique si un botón fue presionado o no, etc.

  9. Hay dos formas de obtener información de la base de datos: la síncrona (DataReader) y la asíncrona (DataSet). Un DataReader debe ser utilizado cuando no se están manipulando más de 100 registros. Un DataSet debe ser utilizado cuando se manipula gran cantidad de información, incluso tablas completas.

  10. En todo formulario el botón de Aceptar estará a la izquierda del botón Cancelar.

  11. Definir claramente las variables de conexión a la base de datos en el archivo web.config, así como una página para CustomErrors.

  12. Definir documento de variables de sesión existentes y el tiempo de sesión. Las variables de sesión no indican el tipo de dato ya que todas son de tipo string. Por ejemplo, los nombres de las variables de sesión no serán "strNombre" sino "Nombre", ni strFechaNac sino FechaNac.

  13. Todo User Control (ASCX) creado e incorporado en un ASPX debe tener el prefijo UserControl de modo que se debe encontrar en el ASPX algo como <UserControl:MiControl id="IdMiControl" runat="server" />


Prefijos para controles más comunes
  • lbl = label

  • txt = textbox

  • btn = button

  • ddl = dropdownlist

  • lbx = listbox

  • cbx = checkbox

  • rbtn = radiobutton

  • cbl = checkboxlist

  • rbl = radiobuttonlist

  • bll = bulletedlist

  • dg = datagrid

  • gv = gridview

  • mv = multiview

  • dv = detailsview

  • tv = treeview



Prefijos para tipos de variables más comunes
  • str = string

  • int = integer

  • lng = long

  • bln = boolean

  • dt = datetime

lunes, 17 de septiembre de 2007

Recuperar ID de un registro que recién se insertó

Ejemplo para recuerar un id de una registro que recién se insertó en la BD. Normalmente se requiere ese id para insertar un segundo registro, muy usado en transacciones de SQL.


Private Sub ExecuteSqlTransaction(ByVal connectionString As String)
Using connection As New SqlConnection(connectionString)
connection.Open()
Dim intRegionID As Integer
Dim command As SqlCommand = connection.CreateCommand()
Dim transaction As SqlTransaction

' Start a local transaction
transaction = connection.BeginTransaction("SampleTransaction")

' Must assign both transaction object and connection
' to Command object for a pending local transaction.
command.Connection = connection
command.Transaction = transaction

Try
command.CommandText = _
"Insert into Region (RegionName, RegionDescription) VALUES (100, 'Description');SELECT @@Identity"
'Get the Region ID in the intRegionID variable
'Very important to use ExecuteScalar in order to get the
'numeric value of the ID
intRegionID = command.ExecuteScalar()

'Now we can use that id to our next SQL statement
command.CommandText = _
"Insert into RegionGroup (RegionID, RegionName) VALUES (" & RegionID & ", 'Description')"

command.ExecuteNonQuery()

' Attempt to commit the transaction.
transaction.Commit()
Console.WriteLine("Both records are written to database.")

Catch ex As Exception
Console.WriteLine("Commit Exception Type: {0}", ex.GetType())
Console.WriteLine(" Message: {0}", ex.Message)

' Attempt to roll back the transaction.
Try
transaction.Rollback()

Catch ex2 As Exception
' This catch block will handle any errors that may have occurred
' on the server that would cause the rollback to fail, such as
' a closed connection.
Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType())
Console.WriteLine(" Message: {0}", ex2.Message)
End Try
End Try
End Using
End Sub


Ejemplo de SqlTransaction

Aquí un ejemplo para realizar transacciones en SQL, muy util cuando se van a insertar más de 1 registro en una BD


Private Sub ExecuteSqlTransaction(ByVal connectionString As String)
Using connection As New SqlConnection(connectionString)
connection.Open()

Dim command As SqlCommand = connection.CreateCommand()
Dim transaction As SqlTransaction

' Start a local transaction
transaction = connection.BeginTransaction("SampleTransaction")

' Must assign both transaction object and connection
' to Command object for a pending local transaction.
command.Connection = connection
command.Transaction = transaction

Try
command.CommandText = _
"Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')"
command.ExecuteNonQuery()
command.CommandText = _
"Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')"

command.ExecuteNonQuery()

' Attempt to commit the transaction.
transaction.Commit()
Console.WriteLine("Both records are written to database.")

Catch ex As Exception
Console.WriteLine("Commit Exception Type: {0}", ex.GetType())
Console.WriteLine(" Message: {0}", ex.Message)

' Attempt to roll back the transaction.
Try
transaction.Rollback()

Catch ex2 As Exception
' This catch block will handle any errors that may have occurred
' on the server that would cause the rollback to fail, such as
' a closed connection.
Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType())
Console.WriteLine(" Message: {0}", ex2.Message)
End Try
End Try
End Using
End Sub

viernes, 14 de septiembre de 2007

Creación de trigger

Un trigger ayuda a gestionar de una mejor forma la información que se encuentra en la BD. De este modo cuando la información sea modificada, podrán ejecutarse acciones diversas. Ejemplos de ello pueden ser:
1. Al eliminar un registro se eliminen otros cuantos de otras tablas
2. Al insertar un registro se lleve a cabo una validación
3. Al actualizar un registro, actualizar otras tablas
4. Al insertar un registro, insertar otros cuantos en otras tablas

Para crear un trigger sólo hace falta ejecutar una sentencia como la siguiente, colocando los textos en negritas con sus valores correspondientes. En este caso el trigger aplica justo después de haber insertado un nuevo registro en MiTabla2.


SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE TRIGGER [NombreDelTrigger]
ON [dbo].[MiTabla2]
AFTER INSERT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

IF (SELECT COUNT(*) FROM MiTabla2, inserted WHERE (MiTabla2.IdUsuario = inserted.IdUsuario)) > 10
BEGIN
RAISERROR('No se pueden insertar mas de 10 registros para un usuario', 16, 1)
ROLLBACK TRANSACTION
END

END
GO

viernes, 7 de septiembre de 2007

ASCX dentro de DataGrid

Importante: Antes que todo deberás saber que esto no funciona con GridView, de modo que tendremos que recurrir al DataGrid que es más flexible.

Supongamos que tenemos en un archivo ASPX algo como lo siguiente:


<asp:DataGrid ID="dg1" AutoGenerateColumns="False" runat="server">
<Columns>
<asp:TemplateColumn>
<ItemTemplate>
   <asp:Label ID="lldld" Text='<%# DataBinder.Eval(Container.DataItem, "FechaNacimiento")%>' runat="server" /><br />
   <asp:Label ID="Label1" Text='<%# DataBinder.Eval(Container.DataItem, "Sexo")%>' runat="server" />
   <asp:Label ID="Label2" Text='<%# DataBinder.Eval(Container.DataItem, "Apellidos")%>' runat="server" />
   <asp:Label ID="Label3" Text='<%# DataBinder.Eval(Container.DataItem, "ClaveNivel")%>' runat="server" />
   <MisComponentes:Micontrol ID="control1" ValorAsignar='<%# DataBinder.Eval(Container.DataItem, "Nombres")%>' runat="server" />
</ItemTemplate>
</asp:TemplateColumn>
</Columns>
</asp:DataGrid>


Tomar en cuenta que "control1" ya fue registrado en el aspx mediante la directiva @Register.

Ahora veamos cómo está conformado el ASCX.


<%@ Control Language="vb" AutoEventWireup="true" %>

<asp:Label ID="lblUsuario" runat="server" />

<script runat="server">

   Public Property ValorAsignar() As String
      Get
         Return lblUsuario.Text
      End Get
      Set(ByVal value As String)
         lblUsuario.Text = value
      End Set
      End Property

</script>


En este caso existe una propiedad llamada "ValorAsignar" que permite colocar y/o obtener el valor del label.

jueves, 6 de septiembre de 2007

Abrir un pop-up


<SCRIPT>
function fn_open_Window()
{
window.open('MiArchivo.html','Titulo de la pagina','width=850,height=650,top=100,left=150,resizable=yes');
}
</SCRIPT>

<a href="javascript:fn_open_Window()" >
<img src="MiImagen.gif" border=0>
</a>

lunes, 3 de septiembre de 2007

Utilización de un DropDownList en un GridView (modo editar)

En éste caso el siguiente código lo que hace al darle editar al GridView es que automaticamente muestra el drop cargado y seleccionado en un valor, por ejemplo:



<DropDownList runat="server" ID="DropEjemplo" selectedValue='<%# Bind("Estado")%>' DataSourceID="DSDDL" DataTextField="Estado" DataValueField="IDEstado" />
<asp:SqlDataSource ID="DSDDL"" runat="server" ConnectionString="<%$ ConnectionStrings:NombreBD %>"
SelectCommand="SELECT * FROM Estados order by Estado"/>


Notas:
DataSourceID="" se refiere al Id del DataSource declarado para el Drop.
DataTextField="" se refiere al texto que C/elemento mostrará en el Drop.
DataValueField="" se refiere al valor con el que el C/elemento será identificado en el Drop.
selectedValue='<%# Bind("Estado") %>', se refiere al valor que trae el Gridview.
Los valores especificados deben llamarse igual que como se traen en el Query.

Al dar clic en Update se tomara automaticamente el valor que en ese momento este seleccionado

Ñau

jueves, 30 de agosto de 2007

Algunas Expresiones Regulares
Aqui les dejo algunas de las expresiones que comunmente utilizamos para validar y que luego se nos andan olvidando.

Validation para RFC= "^[a-zA-Z]{3,4}(\d{6})((\D|\d){3})?$"
Validation para Email= "^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$"
Validation admite sólo números= "^/d*"


Y su uso puede variar, la que yo uso a veces es la siguiente:

Dim expr As New Regex("^\d*")
Dim val As Match = expr.Match(tbxTelefono.Text)
If Not val.Success Then
LabelMensaje.Text = "-El teléfono no es válido
"
End if


Ñau!
Impresion rapida de variables de Sesion

Espero les sea de utilidad este pequeño procedimiento, lo que hace es imprimir las variables se sesion y sus valores (si es que contiene algun valor).



For i As Integer = 0 To Session.Contents.Count - 1
Response.Write("
" & Session.Keys(i))
Response.Write(" = " & Session.Item(i))
Next

El resultado de esto seria por ejemplo:

ID = 1245
Variable = Si
Direccion = Calle_21

Nau!
Algunas funciones VB.NET útiles para el manejo de BD

Esta función recibe como parámetro una sentencia SQL de tipo INSERT, UPDATE o DELETE y la ejecuta:

Sub RunSQLBD(ByVal StrSQL As String)
Dim dbConnection As New SqlConnection(ConfigurationManager.AppSettings("MyDataBase"))
Dim dbCommand As New SqlCommand(StrSQL, dbConnection)
Try
dbConnection.Open()
dbCommand.ExecuteNonQuery()
Finally
dbConnection.Close()
End Try
End Sub


Recordemos que:

ConfigurationManager.AppSettings("MyDataBase")

Hace referencia a la siguiente línea creada en el web.config:

<appSettings>
<add key="MyDataBase" value="server=SERVER_NAME;database=DATABASE_NAME;UID=sa;PWD=xxxxx;/>
</appSettings>


2. GetDataSetBD

La siguiente función regresa un DataSet a partir de una sentencia SQL de tipo SELECT

Function GetDataSetBD(ByVal StrSQL As String) As DataSet
 Dim dbConnection As New SqlConnection(ConfigurationManager.AppSettings("MyDataBase"))
  Dim objAdapter As New SqlDataAdapter(StrSQL, dbConnection)
  Dim ds As New DataSet()
  Try
    objAdapter.Fill(ds)
  Catch ex As Exception
    Throw New Exception(ex.Message, ex.InnerException)
  Finally
  objAdapter.Dispose()
  If dbConnection.State = ConnectionState.Open Then dbConnection.Close()
  dbConnection.Dispose()
  End Try
  Return ds
End Function


La instrucción throw nos permitirá arrojar el error en caso de que lo haya. De ese modo cuando llamemos esta función podremos hacer algo como lo siguiente.


  Try
    Dim ds As New DataSet
    ds = GetDataSetBD("SELECT * FROM Usuarios")
    'AQUÍ PROCESAMOS EL DATASET COMO QUERAMOS
  Catch ex As Exception
    'AQUÍ OBTENEMOS EL ERROR GENERADO Y REALIZAMOS ALGUNA ACCIÓN PERTINENTE
  End Try

¿Cómo vincular dos BD's en una sentencia SQL?


En términos sencillos, la idea aquí es juntar en una sola sentencia dos tablas que pertenezcan a distintas bases de datos SQL.

Algunas veces requerimos accesar a dos bases de datos para obtener cierta información. Por ejemplo, supongamos que en una BD tenemos los datos personales de todos los clientes y queremos "pegarle" a esta información otro dato existente en otra BD. Este dato podría ser, por ejemplo, cuánto ha consumido de nuestros productos. De ese modo tenemos algo así:


SELECT * FROM BdPrincipal..Clientes
INNER JOIN BdDetalles..Consumos
ON (BdPrincipal..Clientes.IdCliente = BdDetalles..Consumos.IdCliente)


Ambas bases deberán estar funcionando bajo el mismo lenguaje, de otro modo nuestra sentencia será algo como:


SELECT * FROM BdPrincipal..Clientes
INNER JOIN BdDetalles..Consumos
ON (
BdPrincipal..Clientes.IdCliente COLLATE SQL_Latin1_General_CP1253_CS_AS
=
BdDetalles..Consumos.IdCliente COLLATE SQL_Latin1_General_CP1253_CS_AS
)


El idioma lo podemos verificar en la configuración de cada base (SQL Manager)
Un query para paginar a nuestro antojo.

Veamos este primer ejemplo que tomará los primeros 10 registros encontrados en la tabla Clientes:

SELECT TOP 10 * FROM Clientes
WHERE IdCliente NOT IN
(
SELECT TOP 0 IdCliente FROM Clientes
ORDER BY IdCliente
)
ORDER BY IdCliente


Ahora tomando los siguientes 10 registros:

SELECT TOP 10 * FROM Clientes
WHERE IdCliente NOT IN
(
SELECT TOP 10 IdCliente FROM Clientes
ORDER BY IdCliente
)
ORDER BY IdCliente


Ahora tomando el tercer grupo (TOP 20) de 10 registros (TOP 10):

SELECT TOP 10 * FROM Clientes
WHERE IdCliente NOT IN
(
SELECT TOP 20 IdCliente FROM Clientes
ORDER BY IdCliente
)
ORDER BY IdCliente


Obsérvese la aplicación de filtros al ejemplo anterior.

SELECT TOP 10 * FROM Clientes
WHERE IdCliente NOT IN
(
SELECT TOP 20 IdCliente FROM Clientes
WHERE Vigencia > GetDate()
ORDER BY IdCliente
)
AND WHERE Vigencia > GetDate()
ORDER BY IdCliente
Manejando llaves primarias en un DataSet

Supongamos que requerimos una tabla que tenga dos columnas: ID y Nombre. La primera columna (ID) deberá ser llave primaria y además será de tipo "UniqueIdentifier" de modo que nos permita almacenar valores alfanuméricos y que no se repitan.

Dim dsProcesadas As New DataSet("MiDataSet")
Dim newTable1 As New DataTable("MiTabla1")
dsProcesadas.Tables.Add(newTable1)

newTable1.Columns.Add("ID", Type.GetType("System.Guid"), "")
newTable1.Columns.Add("Nombre", Type.GetType("System.String"), "")

Dim key(0) As DataColumn
key(0) = newTable1.Columns("ID")
newTable1.PrimaryKey = key


¿Cómo añado registros?

Es muy fácil, podemos crear una rutina muy aparte que lo haga y que reciba como parámetros los valores de las columnas. No nos confundamos, veamos el ejemplo:

Sub CreaRegistro(ByVal GuidID As Guid,ByVal StrNombre As String, ByRef ds As DataSet)
   Dim row As DataRow
   row = ds.Tables("MiTabla1").NewRow
   ds.Tables("MiTabla1").Rows.Add(row)
   row("ID") = GuidID
   row("Nombre") = StrNombre
End Sub


Juntemos todo el código en la siguiente función:

<script runat="server">

Sub Page_Load()
   Dim ds As new DataSet
   ds = GetDataSetPrincipal()
   '# A PARTIR DE AQUI PODEMOS HACER Y DESHACER
   '# EN EL DATASET
End Sub

Function GetDataSetPrincipal() As DataSet
   Dim ds As New DataSet("MiDataSet")
   Dim newTable1 As New DataTable("MiTabla1")
   ds.Tables.Add(newTable1)

   newTable1.Columns.Add("ID", Type.GetType("System.Guid"), "")
   newTable1.Columns.Add("Nombre", Type.GetType("System.String"), "")

   Dim key(0) As DataColumn
   key(0) = newTable1.Columns("ID")
   newTable1.PrimaryKey = key

   Dim GuidJuan As Guid = New Guid("9CD8769C-7DEB-40A0-828E-DBB03556B451")
   Dim GuidPedro As Guid = New Guid("9CD8769C-7DEB-40A0-828E-DBB03556B452")
   Dim GuidAna As Guid = New Guid("9CD8769C-7DEB-40A0-828E-DBB03556B453")
   CreaRegistro(GuidJuan, "Juan" , ds)
   CreaRegistro(GuidPedro, "Pedro" , ds)
   CreaRegistro(GuidAna, "Ana" , ds)

   Return ds
End Function

Sub CreaRegistro(ByVal GuidID As Guid,ByVal StrNombre As String, ByRef ds As DataSet)
   Dim row As DataRow
   row = ds.Tables("MiTabla1").NewRow
   ds.Tables("MiTabla1").Rows.Add(row)
   row("ID") = GuidID
   row("Nombre") = StrNombre
End Sub

</script>
Ejecutar sentencias SQL de modo práctico

Para ello utilizaremos una función llamada RunSQLBD que puede llamarse de dos formas: una es simplemente enviándole como parámetro una sentencia SQL y la otra es enviándole la sentencia más los parámetros SQL que deseemos utilizar.

En ambos casos las sentencias deben ser de tipo INSERT, UPDATE o DELETE. Los parámetros SQL evitan que alguien realice el famoso SQL Injection, modificando nuestras sentencias a su antojo y realizando estragos en nuestra base de datos.

Recordemos que .NET es un lenguaje que permite la abstracción, así que veamos primero cómo utilizar la función RunSQLBD para mostrar lo sencillo que es. Supongamos que tenemos una aplicación que manipula una libreta de direcciones y el usuario ha proporcionado los datos necesarios y es momento de guardar un nuevo registro. La siguiente función recibe la información (que previamente hemos validado) y realiza la inserción.


Sub GuardarLibretaDireccion(ByVal StrNombre As String, ByVal StrCorreo As String, ByVal StrNotas As String, ByVal BlnActivo As Boolean)
Dim StrSQL As String = ""
StrSQL &= " INSERT INTO LibretaDirecciones(Nombre, Correo, Notas, Activo)"
StrSQL &= " VALUES(@Titulo, @Correo, @Notas, @Activo)"
Try
Dim Parametros(3) As OleDbParameter
Parametros(0) = New OleDbParameter("@Nombre", OleDbType.VarChar, 255)
Parametros(1) = New OleDbParameter("@Correo", OleDbType.VarChar, 100)
Parametros(2) = New OleDbParameter("@Notas", OleDbType.LongVarChar, 8000)
Parametros(3) = New OleDbParameter("@Activo", OleDbType.Boolean)
Parametros(0).Value = StrNombre
Parametros(1).Value = StrCorreo
Parametros(2).Value = StrNotas
Parametros(3).Value = BlnActivo
RunSQLBD(StrSQL, Parametros)
Catch ex As Exception
'AQUÍ REALIZAMOS ALGUNA ACCIÓN SI ALGO FALLA (QUIZÁ QUIERAS RECIBIR POR CORREO EL DETALLE DEL ERROR.
End Try
End Sub


Ahora veamos el mismo ejemplo pero sin utilizar parámetros SQL:


Sub GuardarLibretaDireccion(ByVal StrNombre As String, ByVal StrCorreo As String, ByVal StrNotas As String, ByVal BlnActivo As Boolean)
Dim StrSQL As String = ""
StrSQL &= " INSERT INTO LibretaDirecciones(Nombre, Correo, Notas, Activo)"
StrSQL &= " VALUES('" & StrNombre & "', '" & StrCorreo & "', '" & StrNotas & "', '" & BlnActivo & "')"
Try
RunSQLBD(StrSQL, Parametros)
Catch ex As Exception
'AQUÍ REALIZAMOS ALGUNA ACCIÓN SI ALGO FALLA (QUIZÁ QUIERAS RECIBIR POR CORREO EL DETALLE DEL ERROR.
End Try
End Sub


Fácil, ¿no?

Ahora sí! Aquí están las dos funciones que lo hacen todo. Hemos colocado Overloads para que se entienda que ambas tendrán el mismo nombre. Si al llamar a RunSQLBD le colocamos un solo parámetro se ejecutará la primera, si por otro lado colocamos 2 parámetros entonces simplemente se ejecutará la segunda.


Public Overloads Sub RunSQLBD(ByVal StrSQL As String)
Dim dbConnection As New OleDbConnection(System.Web.Configuration.WebConfigurationManager.AppSettings(GetBDKey()))
Dim dbCommand As New OleDbCommand(StrSQL, dbConnection)
Try
dbConnection.Open()
dbCommand.ExecuteNonQuery()
Catch ex As Exception
Throw New Exception(ex.Message, ex.InnerException)
'THROW NOS PERMITIRÁ CACHAR EL ERROR EN CUALQUIER LUGAR DONDE SE MANDE LLAMAR ESTA RUTINA
Finally
dbConnection.Close()
End Try
End Sub

Public Overloads Sub RunSQLBD(ByVal StrSQL As String, ByVal SqlParametros As OleDbParameter())
Dim dbConnection As New OleDbConnection(System.Web.Configuration.WebConfigurationManager.AppSettings(GetBDKey()))
Dim dbCommand As New OleDbCommand(StrSQL, dbConnection)
For Each objpar As OleDbParameter In SqlParametros
dbCommand.Parameters.Add(objpar)
Next

Try
dbConnection.Open()
dbCommand.ExecuteNonQuery()
dbConnection.Close()
Catch ex As Exception
Throw New Exception(ex.Message, ex.InnerException)
'THROW NOS PERMITIRÁ CACHAR EL ERROR EN CUALQUIER LUGAR DONDE SE MANDE LLAMAR ESTA RUTINA
Finally
dbConnection.Close()
End Try
End Sub


Es bastante código para estas dos funciones. Pero de esta forma se ejecutarán sentencias de un modo seguro y no tendremos que escribir todo este código cada vez que queramos realizar una acción en la base de datos.

Ah! Eso de "MiBasedeDatos" significa que hemos creado en el archivo web.config una etiqueta de tipo:

<appSettings>
<add key="MiBasedeDatos" value="Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\...\Northwind.mdb"/>
</appSettings>


Este ejemplo se basa en Access; si estás utilizando SQL tendrás que cambiar los objetos OleDb a SQL, por ejemplo OleDbParameter por SqlParameter. Y claro, el "value" que aparece en el código perteneciente al web.config cambiará por una cadena de conexión que sea correcta para tu base de datos SQL.
Confirmación javascript para botones NET

Teniendo el botón:
<asp:Button id="btnEliminar" onClick="EliminaElemento" runat="server" />

procedemos a aplicar la función javascript que mostrará la ventana de confirmación:
btnEliminar.Attributes("onClick") = "return confirm('¿Esta seguro de querer eliminar este elemento?');"

también se puede realizar así:
btnEliminar.Attributes.Add("onClick", "return confirm('¿Esta seguro de querer eliminar este elemento?');")

Observar que el botón tiene su evento OnClick propio de servidor (manda llamar una función que, en nuestro caso, se llama EliminaElemento) y aparte estamos añadiendo otro evento onClick para que se ejecute en modo cliente (javascript). Hay que tener en cuenta que javascript en sensible al uso de mayúsculas por lo que "onclick" no es lo mismo que "onClick".

miércoles, 29 de agosto de 2007

Para redirigir una pagina a otra que no este por defaul en la master:
esto va en el boton, link o de donde se quiera rediriguir:

Protected Sub btnRegistrarse_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnRegistrarse.Click
Dim strDoLoginURL As String = "registrousuario.aspx?redirect=" & Server.UrlEncode(Request.ServerVariables("Script_Name").Substring(Request.ServerVariables("Script_Name").LastIndexOf("/") + 1))
If Len(Request.QueryString.ToString()) > 0 Then
strDoLoginURL += "?" & Server.UrlEncode(Request.QueryString.ToString())
End If

If Session("strusuario") = Nothing Then Response.Redirect(strDoLoginURL)
End Sub


y en la pagina a donde se envio se pone esto, para q se vaya con las variables de session ya cargadas:


If Len(Request("redirect")) > 0 Then
Dim StrRedirect As String = ""
StrRedirect = Server.UrlEncode(Request("redirect"))
Session("strusuario") = struser
Session("strCorreo") = StrCorreo
Response.Redirect(StrRedirect)
End If
Validando sesión mediante archivo master

El siguiente código nos permite que todos los archivos que estén relacionados con nuestro archivo master, estén validados por sesión. Y cuando queramos que sólo algunos archivos no estén validados por sesión entonces utilizaremos un array especificando qué archivos no se validarán.

El siguiente código deberá estar contenido en el archivo master que estemos utilizando.



Sub Page_Init()
   Dim BlnValidarSesion As Boolean = True
   Dim StrPagesNotToValidateSession() As String = {"login.aspx", "recuperarpassword.aspx", "registro.aspx"}
   For Each StrPage As String In StrPagesNotToValidateSession
      If StrPage = StrPageName Then BlnValidarSesion = False
   Next
   If BlnValidarSesion Then
    ValidateSession()
   End If
End Sub

Sub ValidateSession()
   Dim strDoLoginURL As String = "login.aspx?redirect=" & Server.UrlEncode(Request.ServerVariables("Script_Name").Substring(Request.ServerVariables("Script_Name").LastIndexOf("/") + 1))
   If Len(Request.QueryString.ToString()) > 0 Then
      strDoLoginURL += "?" & Server.UrlEncode(Request.QueryString.ToString())
   End If
   If Session("Usuario") = Nothing Then Response.Redirect(strDoLoginURL)
End Sub