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