Crear un punto de venta con ASP.NET y SQL Server (Parte 1)

Diseño de la base de datos
Será una base de datos relacional, llamada pventa, muy básica, con la siguiente estructura:
Base de Datos
Y el script para crear labase de datos seria:
USE [pventa]
GO
/****** Object:  Table [dbo].[users]    Script Date: 09/08/2011 17:27:43 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[users](
    [user_login] [nvarchar](50) NOT NULL,
    [user_password] [nvarchar](250) NULL,
    [nombre] [nvarchar](150) NULL,
    [activo] [bit] NOT NULL,
    [ventas] [bit] NOT NULL,
    [reportes] [bit] NOT NULL,
    [administrar] [bit] NOT NULL,
    [fecha_registro] [datetime] NOT NULL,
 CONSTRAINT [PK_users] PRIMARY KEY CLUSTERED 
(
    [user_login] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object:  Table [dbo].[unidad_medida]    Script Date: 09/08/2011 17:27:43 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[unidad_medida](
    [id_unidad_medida] [smallint] NOT NULL,
    [unidad_medida] [nvarchar](150) NULL,
 CONSTRAINT [PK_unidad_medida] PRIMARY KEY CLUSTERED 
(
    [id_unidad_medida] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object:  Table [dbo].[productos]    Script Date: 09/08/2011 17:27:43 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[productos](
    [id_producto] [nvarchar](50) NOT NULL,
    [producto] [nvarchar](250) NULL,
    [id_unidad_medida] [smallint] NULL,
    [p_compra] [float] NULL,
    [p_venta] [float] NULL,
    [existencia] [float] NULL,
 CONSTRAINT [PK_productos] PRIMARY KEY CLUSTERED 
(
    [id_producto] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object:  Table [dbo].[venta]    Script Date: 09/08/2011 17:27:43 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[venta](
    [id_venta] [int] IDENTITY(1,1) NOT NULL,
    [fecha_registro] [datetime] NOT NULL,
    [user_login] [nvarchar](50) NOT NULL,
 CONSTRAINT [PK_venta] PRIMARY KEY CLUSTERED 
(
    [id_venta] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object:  Table [dbo].[venta_detalle_tmp]    Script Date: 09/08/2011 17:27:43 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[venta_detalle_tmp](
    [id_venta_detalle_tmp] [int] IDENTITY(1,1) NOT NULL,
    [id_producto] [nvarchar](50) NOT NULL,
    [cantidad] [float] NOT NULL,
    [user_login] [nvarchar](50) NOT NULL,
    [p_venta] [float] NOT NULL,
 CONSTRAINT [PK_venta_detalle_tmp] PRIMARY KEY CLUSTERED 
(
    [id_venta_detalle_tmp] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object:  Table [dbo].[venta_detalle]    Script Date: 09/08/2011 17:27:43 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[venta_detalle](
    [id_venta_detalle] [int] IDENTITY(1,1) NOT NULL,
    [id_venta] [int] NOT NULL,
    [id_producto] [nvarchar](50) NOT NULL,
    [cantidad] [float] NOT NULL,
    [p_venta] [float] NOT NULL,
 CONSTRAINT [PK_venta_detalle] PRIMARY KEY CLUSTERED 
(
    [id_venta_detalle] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object:  Default [DF_users_fecha_registro]    Script Date: 09/08/2011 17:27:43 ******/
ALTER TABLE [dbo].[users] ADD  CONSTRAINT [DF_users_fecha_registro]  DEFAULT (getdate()) FOR [fecha_registro]
GO
/****** Object:  Default [DF_venta_fecha_registro]    Script Date: 09/08/2011 17:27:43 ******/
ALTER TABLE [dbo].[venta] ADD  CONSTRAINT [DF_venta_fecha_registro]  DEFAULT (getdate()) FOR [fecha_registro]
GO
/****** Object:  ForeignKey [FK_productos_unidad_medida]    Script Date: 09/08/2011 17:27:43 ******/
ALTER TABLE [dbo].[productos]  WITH CHECK ADD  CONSTRAINT [FK_productos_unidad_medida] FOREIGN KEY([id_unidad_medida])
REFERENCES [dbo].[unidad_medida] ([id_unidad_medida])
GO
ALTER TABLE [dbo].[productos] CHECK CONSTRAINT [FK_productos_unidad_medida]
GO
/****** Object:  ForeignKey [FK_venta_users]    Script Date: 09/08/2011 17:27:43 ******/
ALTER TABLE [dbo].[venta]  WITH CHECK ADD  CONSTRAINT [FK_venta_users] FOREIGN KEY([user_login])
REFERENCES [dbo].[users] ([user_login])
GO
ALTER TABLE [dbo].[venta] CHECK CONSTRAINT [FK_venta_users]
GO
/****** Object:  ForeignKey [FK_venta_detalle_productos]    Script Date: 09/08/2011 17:27:43 ******/
ALTER TABLE [dbo].[venta_detalle]  WITH CHECK ADD  CONSTRAINT [FK_venta_detalle_productos] FOREIGN KEY([id_producto])
REFERENCES [dbo].[productos] ([id_producto])
GO
ALTER TABLE [dbo].[venta_detalle] CHECK CONSTRAINT [FK_venta_detalle_productos]
GO
/****** Object:  ForeignKey [FK_venta_detalle_venta]    Script Date: 09/08/2011 17:27:43 ******/
ALTER TABLE [dbo].[venta_detalle]  WITH CHECK ADD  CONSTRAINT [FK_venta_detalle_venta] FOREIGN KEY([id_venta])
REFERENCES [dbo].[venta] ([id_venta])
GO
ALTER TABLE [dbo].[venta_detalle] CHECK CONSTRAINT [FK_venta_detalle_venta]
GO
/****** Object:  ForeignKey [FK_venta_detalle_tmp_productos]    Script Date: 09/08/2011 17:27:43 ******/
ALTER TABLE [dbo].[venta_detalle_tmp]  WITH CHECK ADD  CONSTRAINT [FK_venta_detalle_tmp_productos] FOREIGN KEY([id_producto])
REFERENCES [dbo].[productos] ([id_producto])
GO
ALTER TABLE [dbo].[venta_detalle_tmp] CHECK CONSTRAINT [FK_venta_detalle_tmp_productos]
GO
/****** Object:  ForeignKey [FK_venta_detalle_tmp_users]    Script Date: 09/08/2011 17:27:43 ******/
ALTER TABLE [dbo].[venta_detalle_tmp]  WITH CHECK ADD  CONSTRAINT [FK_venta_detalle_tmp_users] FOREIGN KEY([user_login])
REFERENCES [dbo].[users] ([user_login])
GO
ALTER TABLE [dbo].[venta_detalle_tmp] CHECK CONSTRAINT [FK_venta_detalle_tmp_users]
GO
Creamos elproyecto:



En la imagen se muestran las opciones que debemos seleccionar.
Se mostrará el explorador de soluciones como se muestra en la imagen:

Nuestro proyecto está vacío, por ahora crearemos varios objetos que describimos a continuación.
Creación de la Página Maestra (main.master)




Modificamos el código HTMLpara que quede asi:

<%@ Master Language="C#" AutoEventWireup="true" CodeFile="main.master.cs" Inherits="main" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Punto de Venta Web</title>
</head>
<body>
    <form id="frmMain" runat="server">
        <h1>SISTEMA PUNTO DE VENTA</h1>
        <div style=" width:800px;">
        <div id="menuh">
            <ul>
                <li><a href="default.aspx">Inicio</a></li>
                <asp:Label ID="lblOpciones" runat="server" Text=""></asp:Label>
                <li><asp:LinkButton ID="btnCerrarSesion" runat="server" 
                        onclick="btnCerrarSesion_Click">Cerrar Sesión</asp:LinkButton></li>
            </ul>
        </div>
        <br />
        <asp:ContentPlaceHolder id="cphMain" runat="server">
        
        </asp:ContentPlaceHolder>
        <h4>DESARROLLADO POR TYRODEVELOPER</h4>
    </div>
    </form>
</body>
</html>

Luego agregamos la página principal (default.aspx)



El código HTML quedaría:
<%@ Page Title="" Language="C#" MasterPageFile="~/main.master" AutoEventWireup="true" CodeFile="default.aspx.cs" Inherits="_default" %>

<asp:Content ID="cntMain" ContentPlaceHolderID="cphMain" Runat="Server">
<h1>VENTAS</h1>
</asp:Content>

Para ejecutar nuestro sistema, nos vamos presionamos la combinación de teclas Windows + R, y se muestra la siguiente pantalla:

Y al ejecutarlo, se verá lo siguiente en el explorador de Internet:

Ahora le daremos un poco de forma
Agregamos un documento CSS, como se muestra:



Al nuevo elemento le agregamos el siguiente código:

body {
    font-family:Verdana
}
img{ border:0px;}
#menuh {
        font: 80% "Trebuchet MS", Arial, Helvetica, sans-serif;
        margin-top: 20px;
}

#menuh ul, li {
        list-style-type: none;
}

#menuh ul {
        margin: 0;
        padding: 0;
}

#menuh li {
        float: left;
}

#menuh a {
        text-decoration: none;
        color: #3366CC;
        background: #F0F7FC;
        display: block;
        padding: 3px 10px;
        text-align: center;
        border: 1px solid #ACCFE8;
        border-width: 1px 1px 1px 0;
}

Luego, arrastramos el archivo a la página maestra, así:

Si ejecutamos de nuevo el sistema, se vería así:

Nuestro sistema ya va agarrando fuerza.
Pantalla de Inicio de Sesión (login.aspx)

Ahora, tenemos que agregar un registro a la base de datos, en la tabla users:

Agregamos una nueva página llamada login.aspx



Aquí debemos poner un poco de atención, porque hay que empezar a programar, debemos tener abierto SQL Server Management Studio porque escribiremos procedimientos almacenados al mismo tiempo que programamos.
Este es el código HTML de login.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="login.aspx.cs" Inherits="login" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Iniciar Sesión</title>
    <link href="StyleSheet.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <form id="form1" runat="server">
    <div>
    <table class="verde" >
        <tr>
            <td colspan="2" align="center"  >               
            <h3> Inicio de Sesión </h3>   
            </td>
        </tr>
        <tr>
            <td align="left"  >Usuario:</td>
            <td >
                <asp:TextBox ID="txtUSER_LOGIN" runat="server" ToolTip="Usuario" Width="150px"></asp:TextBox>
                <asp:RequiredFieldValidator ID="reqUSER_LOGIN" runat="server" ControlToValidate="txtUSER_LOGIN"
                    ErrorMessage="Debe introducir un nombre de usuario">*</asp:RequiredFieldValidator>
            </td>
        </tr>
        <tr>
            <td align="left" >Contraseña:</td>
            <td align="left">
                    <asp:TextBox ID="txtPASSWORD" runat="server" TextMode="Password" 
                    ToolTip="Contraseña" Width="150px"></asp:TextBox>
            </td>
        </tr>
        <tr>
            <td colspan="2" align="left"> 
                <asp:CheckBox ID="chkPersist" runat="server" Text="Recordar usuario" />
            </td>
        </tr>
        <tr>
            <td colspan="2" align="center" >    
                <asp:Button ID="btnSubmit" runat="server" 
                OnClick="btnSubmit_Click" Text="Entrar" Font-Bold="True" Width="100px" />        
            </td>
        </tr>            
    </table>
        <asp:Label ID="lblMensaje" runat="server" Text=""></asp:Label>
    </div>
    </form>
</body>
</html>


Creamos un procedimiento almacenado en SQL Server:
USE pventa
GO
IF EXISTS (SELECT 1 FROM sys.objects WHERE name='proc_USER_LOGIN)
    DROP PROCEDURE proc_USER_LOGIN
GO
CREATE PROCEDURE [dbo].[proc_USER_LOGIN]
    @USER_LOGIN NVARCHAR(50),
    @USER_PASSWORD NVARCHAR(1000)
    WITH ENCRYPTION
AS
    DECLARE @FECHA_LIMITE DATETIME,
            @DIA NVARCHAR(2),
            @MES NVARCHAR(2),
            @ANO NVARCHAR(4)
    ---FECHA---
    SET @DIA=CAST(DAY(GETDATE()) AS NVARCHAR(2))
    SET @MES=CAST(MONTH(GETDATE()) AS NVARCHAR(2))
    SET @ANO=CAST(YEAR(GETDATE()) AS NVARCHAR(4))
    IF LEN(@DIA) = 1
        SET @DIA='0+@DIA
    IF LEN(@MES) = 1
        SET @MES='0+@MES
    ---TERMINA FECHA---
    SET @FECHA_LIMITE='20161231--LIMITE 31 dic 2016
    IF(GETDATE()>@FECHA_LIMITE)
    GOTO ERROR
    SELECT  U.nombre
    FROM USERS U
    WHERE U.[USER_LOGIN]=@USER_LOGIN AND USER_PASSWORD=@USER_PASSWORD
    AND U.ACTIVO=1
RETURN
ERROR:
    RAISERROR('<br /><b>ERROR DE INICIO DE SESIÓN, CADUCO SU PERIODO DE PRUEBA</b><br />,16,1)
    GOTO FIN
RETURN
FIN:
GO
Luego, en login.aspx.cs

Modificamos las directivas using,para que queden asi:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Security;
Agregamos el siguiente codigo (OJO, SI SE COLOCA MAL, HABRÁ ERRORES):
private bool fnLogin(string prmUserLogin, string prmPassword)
{
    bool _return = false;
    try
    {
        SqlConnection cnnLogin = new SqlConnection(clsMain.CnnStr);
        cnnLogin.Open();
        string varSQL = "EXECUTE proc_USER_LOGIN @USER_LOGIN, @USER_PASSWORD";
        SqlCommand cmdLogin = new SqlCommand(varSQL, cnnLogin);
        SqlParameter paramUserLogin = cmdLogin.
            Parameters.Add("@USER_LOGIN", SqlDbType.NVarChar, 50);
        paramUserLogin.Value = prmUserLogin;
        SqlParameter paramPassword = cmdLogin.
            Parameters.Add("@USER_PASSWORD", SqlDbType.NVarChar, 50);
        paramPassword.Value = prmPassword;
        SqlDataReader drLogin = cmdLogin.ExecuteReader();

        if (drLogin.Read()) {
            Session.Add("USER_NAME", drLogin["nombre"].ToString());
            _return = true;
        }
        else{
            lblMensaje.Text = "Nombre de usuario o contraseña incorrectos";
            _return = false;
        }
        drLogin.Close();
        cnnLogin.Close();
        return (_return);
            
    }
    catch (Exception ex)
    {
        lblMensaje.Text = ex.Message;
        return (false);
    }
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
    lblMensaje.Text = "";
    if (fnLogin(txtUSER_LOGIN.Text,txtPASSWORD.Text))
    {
        //correcto           
        FormsAuthentication.
            RedirectFromLoginPage(txtUSER_LOGIN.Text, chkPersist.Checked);
    }
}
Hasta aquí todo debe ir bien, solamente que es necesario agregar código adicional.
Luego, agregamos la carpeta App_Code, de la siguiente manera:

Y agregamos una clase llamada clsMain, asi:

Y le ponemos el siguiente código a clsMain.cs:
using System;
using System.Configuration;

/// <summary>
/// Clase Main
/// </summary>
public class clsMain
{
    public clsMain(){}
    /// <summary>
    /// Regresa la cadena de conexión
    /// </summary>
    public static string CnnStr
    {
        get
        {
            return (ConfigurationManager.
                ConnectionStrings["dbCnnStr"].
                ConnectionString);
        }
    }
    /// <summary>
    /// Lee el archivo de configuración
    /// </summary>
    /// <param name=prmKey">Llave a Leer</param>"
    /// <returns></returns>
    public static string WebConfig(string prmKey)
    {
        try
        {
            string value = ConfigurationManager.AppSettings[prmKey];
            return (value);
        }
        catch
        {
            return ("");
        }
    }
}
Luego agregamos una clase llamada ISODates, y el código es el siguiente:
//TYRODEVELOPER
//SEPTIEMBRE 2011
using System;

namespace ISODates{
    public class Dates{
        /// <summary>
        /// Devuelve una Fecha ISO para SQLServer
        /// </summary>
        /// <param name=prmDate">Fecha a convertir</param>"
        /// <returns>Fecha ISO para SQL Server</returns>
        /// <example>10 Abril 1980 10:25 a.m.= 19800410 10:25:00</example>
        public static string SQLServerDate(DateTime prmDate){
            string varYear = "1900";
            string varMonth = "01";
            string varDay = "01";
            string varHour = "00";
            string varMin = "00";
            string varSec = "00";
            varYear = prmDate.Year.ToString();
            varMonth = prmDate.Month.ToString();
            if (varMonth.Length == 1){
                varMonth = "0" + varMonth;
            }
            varDay = prmDate.Day.ToString();
            if (varDay.Length == 1){
                varDay = "0" + varDay;
            }
            varHour = prmDate.Hour.ToString();
            if (varHour.Length == 1){
                varHour = "0" + varHour;
            }
            varMin = prmDate.Minute.ToString();
            if (varMin.Length == 1){
                varMin = "0" + varMin;
            }
            varSec = prmDate.Second.ToString();
            if (varSec.Length == 1){
                varSec = "0" + varSec;
            }
            return (varYear + varMonth + varDay +
                " " + varHour + ":" + varMin + ":" + varSec);
        }

        /// <summary>
        /// Devuelve una Fecha ISO para SQLServer
        /// </summary>
        /// <param name=prmDate">Fecha a convertir</param>"
        /// <returns>Fecha ISO para SQL Server</returns>
        /// <example>10 Abril 1980 = 19800410 00:00:00</example>
        public static  string SQLServerDateINI(DateTime prmDate){
            string varYear = "1900";
            string varMonth = "01";
            string varDay = "01";
            varYear = prmDate.Year.ToString();
            varMonth = prmDate.Month.ToString();
            if (varMonth.Length == 1){
                varMonth = "0" + varMonth;
            }
            varDay = prmDate.Day.ToString();
            if (varDay.Length == 1){
                varDay = "0" + varDay;
            }
            return (varYear + varMonth + varDay +
                " 00:00:00");
        }

        /// <summary>
        /// Devuelve una Fecha ISO para SQLServer
        /// </summary>
        /// <param name=prmDate">Fecha a convertir</param>"
        /// <returns>Fecha ISO para SQL Server</returns>
        /// <example>10 Abril 1980 = 19800410 23:59:59</example>
        public static string SQLServerDateFIN(DateTime prmDate){
            string varYear = "1900";
            string varMonth = "01";
            string varDay = "01";
            varYear = prmDate.Year.ToString();
            varMonth = prmDate.Month.ToString();
            if (varMonth.Length == 1){
                varMonth = "0" + varMonth;
            }
            varDay = prmDate.Day.ToString();
            if (varDay.Length == 1){
                varDay = "0" + varDay;
            }
            return (varYear + varMonth + varDay +
                " 23:59:59");
        }
    }
}

Después modificaremos el Web.config, para que quede asi:
<?xml version="1.0"?>
<!-- 
    Nota: como alternativa para editar manualmente este archivo puede utilizar la 
    herramienta Administración de sitios web para configurar los valores de la aplicación. Utilice
    la opción Sitio web->Configuración de Asp.Net en Visual Studio.
    Encontrará una lista completa de valores de configuración y comentarios en 
    machine.config.comments, que se encuentra generalmente en 
    \Windows\Microsoft.Net\Framework\v2.x\Config 
-->
<configuration>
  <connectionStrings>
    <add name="dbCnnStr" connectionString="Data Source=.;Initial Catalog=pventa;User ID=webuser;Password=;" providerName="System.Data.SqlClient"/>
  </connectionStrings>
  <system.web>
    <customErrors mode="Off"></customErrors>
    <!-- 
            Establezca debug="true" en la compilación para insertar símbolos 
            de depuración en la página compilada. Dado que este 
            proceso afecta al rendimiento, debe establecer este valor como true 
            durante la depuración.
        -->
    <compilation debug="false" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
        <add assembly="System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add assembly="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
      </assemblies>
    </compilation>
    <!--
            La sección <authentication> habilita la configuración
            del modo de autenticación de seguridad utilizado por 
            ASP.NET para identificar a un usuario entrante. 
        -->
    <authentication mode="Forms">
      <forms name=".VENTASYS" loginUrl="login.aspx" defaultUrl="default.aspx" protection="All" timeout="20" path="/" requireSSL="false" slidingExpiration="true" cookieless="UseDeviceProfile" domain="" enableCrossAppRedirects="false">
        <credentials passwordFormat="SHA1"/>
      </forms>
    </authentication>
    <authorization>
      <deny users="?"/>
    </authorization>
    <!--
            La sección <customErrors> habilita la configuración de 
            las acciones que se deben realizar si un error no controlado tiene lugar
            durante la ejecución de una solicitud. Específicamente, 
            permite a los desarrolladores configurar páginas de error html 
            que se mostrarán en lugar de un seguimiento de pila de errores.

        <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
            <error statusCode="403" redirect="NoAccess.htm" />
            <error statusCode="404" redirect="FileNotFound.htm" />
        </customErrors>
        -->
    <pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
    </pages>
    <httpHandlers>
      <add path="ChartImg.axd" verb="GET,HEAD" 
           type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 
           validate="false"/>
    </httpHandlers>
  </system.web>
  <!-- 
        La sección system.webServer es necesaria para ejecutar ASPN.NET AJAX en Internet
        Information Services 7.0. No es necesaria para la versión anterior de IIS.
    -->
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
    <handlers>
      <add name="ChartImageHandler" preCondition="integratedMode" verb="GET,HEAD" 
           path="ChartImg.axd" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
    </handlers>
  </system.webServer>
  <appSettings>
    <add key="ChartImageHandler" value="Storage=file;Timeout=20;Url=~/rpt/;"/>
    <add key="TICKET_HEADER_01" value="VENTAS S.A DE CV"/>
    <add key="TICKET_HEADER_02" value="ENCABEZADO 02"/>
    <add key="TICKET_HEADER_03" value="ENCABEZADO 03"/>
    <add key="TICKET_HEADER_04" value="ENCABEZADO 04"/>
    <add key="TICKET_FOOTER_01" value="GRACIAS POR SU COMPRA"/>
    <add key="TICKET_FOOTER_02" value="PIÉ 02"/>
    <add key="TICKET_FOOTER_03" value="PIÉ 03"/>
    <add key="TICKET_FOOTER_04" value="PIÉ 04"/>
    <add key="PROGRAMADOR_NOMBRE" value="JUAN GABRIEL CASTILLO"/>
    <add key="PROGRAMADOR_MAIL" value="tyrodeveloper@gmail.com"/>
    <add key="PROGRAMADOR_MENSAJE" value="Gracias por adquirir este sistema."/>
    <add key="GMAIL_USER" value=""/>
    <add key="GMAIL_PASSWORD" value=""/>
    <add key="GMAIL_HOST" value="smtp.gmail.com"/>
    <add key="GMAIL_PORT" value="587"/>
    <add key="GMAIL_URL" value="http://mail.google.com"/>
    <add key="DEVELOPER_URL" value=""/>
  </appSettings>
</configuration>
Poner especial atención a la llave “ConnectionStrings” ya que en esa sección deben poner la configuración de su SQL Server.
Ahora agregaremos el código para cerrar la sesión, nos vamos a la página main.master.cs y agregamos el siguiente código:

protected void btnCerrarSesion_Click(object sender, EventArgs e)
{
    FormsAuthentication.SignOut();
    Response.Redirect("default.aspx");
}
Ahora, si ejecutamos de nuevo el sistema, se mostrará la página de Login:

De acuerdo a los datos que introdujimos a la tabla users
Nombre de usuario: admin
Contraseña: admin
Luego, al introducir un nombre de usuario y contraseña correctos, veremos la siguiente pantalla:

Y al dar clic al botón “Cerrar sesión” el sistema nos regresa a lapantalla de Login.
Lo que haremos a continuación será el diseño de los permisos, es decir, dependiendo de los permisos que tenga el usuario que inició sesión, serán las opciones que podrá ver en el menu.

Siguiente

39 comentarios:

  1. Me aparece, Error al convertir una cadena de caracteres en fecha y/u hora.

    ResponderEliminar
  2. El error que aparece es este Conversion failed when converting date and/or time from character string.

    ResponderEliminar
  3. Hola disculpa una pregunta que diferencia existiria si a este proyecto expuesto lo quisiera implementar en Windows Forms, no se si ubiese alguna diferencia en el codigo.Grax

    ResponderEliminar
  4. Hola gente, tengo una duda, tengo instalado el visual 2010 y el sqlserver 2008. Pero el localhost con el puerto por defecto (80), no aparece nada: me sale este mensaje "HTTP Error 404. The requested resource is not found", y eso ocurre despues de instalar el sqlsever, alguien sabe porque y como solucionarlo.

    Por cierto mi nombre es juan carlos de peru, espero me puedan ayudar

    ResponderEliminar
  5. Saludos,
    Mi nombre es Luis, es la primera vez que intento programar con ASP, siempre he estado trabajando con cms (Joomla, WP, Nuke), entonces mi pregunta es la siguiente:

    Como puedo crear la base de datos. Fuese muy bueno que agregaran un pequeño tutorial dentro de este para los que no conocemos y queremos aprender esto desde cero.

    nota: intenté crearla por sql server 2008, que se instaló con el paquete de visual studio, pero al agregarla me daba error.


    Si alguien pudiese ayudarme se lo agradecería inmensamente.

    ResponderEliminar
  6. HOLA BUENAS NOCHES. TENGO UN PROBLEMA CON EL STORE PROCEDURE, ME MARCA UN ERROR DE SINTAXIS:
    Msg 102, Level 15, State 1, Procedure proc_USER_LOGIN, Line 28
    Incorrect syntax near ')'.

    ResponderEliminar
  7. Hola, estoy probando este tutorial me gusto mucho lo unico que ocurre es que cuando ejecuto la aplicación el usuario no puede iniciar sesión me marca Error de inicio de sesión del usuario 'webuser'. cual es el error que puede tener me puedes enviar el codigo de esta aplicación mi correo es hola_amigo2@hotmail.com te lo agradeceria. Para ver cual es mi error gracias.

    ResponderEliminar
  8. Ayuda El nombre LoginFormsAuthentication.SignOut' no existe en el contexto actual

    ResponderEliminar
    Respuestas
    1. "using System.Web.Security;" en main.master.cs

      Eliminar
  9. Introduzco todo el procedimiento almacenado, si lo copio tal cual esta aqui, me coloca todo esto:
    DROP PROCEDURE proc_USER_LOGIN
    GO
    CREATE PROCEDURE [dbo].[proc_USER_LOGIN]
    @USER_LOGIN NVARCHAR(50),
    @USER_PASSWORD NVARCHAR(1000)
    WITH ENCRYPTION
    AS
    DECLARE @FECHA_LIMITE DATETIME,
    @DIA NVARCHAR(2),
    @MES NVARCHAR(2),
    @ANO NVARCHAR(4)
    ---FECHA---
    SET @DIA=CAST(DAY(GETDATE()) AS NVARCHAR(2))
    SET @MES=CAST(MONTH(GETDATE()) AS NVARCHAR(2))
    SET @ANO=CAST(YEAR(GETDATE()) AS NVARCHAR(4))
    IF LEN(@DIA) = 1
    SET @DIA='0+@DIA
    IF LEN(@MES) = 1
    SET @MES='0+@MES
    ---TERMINA FECHA---
    SET @FECHA_LIMITE='
    en rojo y por ende varios errores
    pero si quito: IF EXISTS (SELECT 1 FROM sys.objects WHERE name='proc_USER_LOGIN) lo que me coloca en rojo es lo siguiente:
    '20161231--LIMITE 31 dic 2016
    IF(GETDATE()>@FECHA_LIMITE)
    GOTO ERROR
    SELECT U.nombre
    FROM USERS U
    WHERE U.[USER_LOGIN]=@USER_LOGIN AND USER_PASSWORD=@USER_PASSWORD
    AND U.ACTIVO=1
    RETURN
    ERROR:
    RAISERROR('
    ERROR DE INICIO DE SESIÓN, CADUCO SU PERIODO DE PRUEBA
    ,16,1)
    GOTO FIN
    RETURN
    FIN:
    GO
    Aparte me dice errorr de sintaxis ecerca de "0" esto en la parte de mes y tmb en en el raiserror "<" Ayuda es la primera vez que uso ASP

    ResponderEliminar
  10. Ya logre quitar lo de las partes que se me ponían en rojo, todo esta en una ' antes de proc_USER_LOGIN, pero ahora me dice que esa columna no es valida, osea la columna proc_USER_LOGIN, que debo hacer, ayuda por favor

    ResponderEliminar
  11. Soy estudiante de Lic. en Informatica, puse tu proyecto en visual estudio 2010, todo bien hasta el momento de correrlo y hacer login, me sale este error
    "A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)"

    Ya estuve revisando y buscando posibles errores y soluciones, pero nada hasta el momento. No se si me puedas/tengas tiempo de ayudar a resolver ese error.
    Gracias.
    Mi correo yanaltas@hotmail.com

    ResponderEliminar
  12. Saludos, yo he estado siguiendo el tutorial pero me salen trabas a cada rato, por ejemplo ahorita me salio esto :
    Line 9: private bool fnLogin(string prmUserLogin, string prmPassword)

    me podrias mandar tus archivos para ver en que estoy mal, gracias

    ResponderEliminar
  13. CORRECCION PARA SQL SERVER 2008 EN ADELANTE


    USE pventa
    GO
    IF EXISTS (SELECT 1 FROM sys.objects WHERE name= 'proc_USER_LOGIN')
    DROP PROCEDURE proc_USER_LOGIN
    GO
    CREATE PROCEDURE dbo.proc_USER_LOGIN
    @USER_LOGIN NVARCHAR(50),
    @USER_PASSWORD NVARCHAR(1000)
    WITH ENCRYPTION
    AS
    DECLARE @FECHA_LIMITE DATETIME,
    @DIA NVARCHAR(2),
    @MES NVARCHAR(2),
    @ANO NVARCHAR(4)

    SET @DIA=CAST(DAY(GETDATE()) AS NVARCHAR(2))
    SET @MES=CAST(MONTH(GETDATE()) AS NVARCHAR(2))
    SET @ANO=CAST(YEAR(GETDATE()) AS NVARCHAR(4))
    IF LEN(@DIA) = 1
    SET @DIA='0+@DIA'
    IF LEN(@MES) = 1
    SET @MES='0+@MES'

    SET @FECHA_LIMITE='20161231--LIMITE 31 dic 2016'
    IF(GETDATE()>@FECHA_LIMITE)
    GOTO ERROR
    SELECT U.nombre
    FROM USERS U
    WHERE U.[USER_LOGIN]=@USER_LOGIN AND USER_PASSWORD=@USER_PASSWORD
    AND U.ACTIVO=1
    RETURN
    ERROR:
    RAISERROR('
    ERROR DE INICIO DE SESIÓN, CADUCO SU PERIODO DE PRUEBA
    ,16,1',1,1);
    GOTO FIN
    RETURN
    FIN:
    GO

    ResponderEliminar
  14. como quedaria el codigo en la clase clsMain si fuera en VB, lo estos haciendo pero en VB y al pasar esta clase no se que hice mal que me marca un erro, por favor si alguien me pudiera ayudar.

    mi correo es jagarciardz@hotmail.com

    de antemano gracias

    ResponderEliminar
  15. Que tal gente, a mi me aparece el siguiente error:
    No se puede encontrar 'principal' de ContentPlaceHolder en la página maestra '/pventaweb/main.master', compruebe el atributo ContentPlaceHolderID del control de contenido en la página de contenido.
    Descripción: Excepción no controlada al ejecutar la solicitud Web actual. Revise el seguimiento de la pila para obtener más información acerca del error y dónde se originó en el código.

    Detalles de la excepción: System.Web.HttpException: No se puede encontrar 'principal' de ContentPlaceHolder en la página maestra '/pventaweb/main.master', compruebe el atributo ContentPlaceHolderID del control de contenido en la página de contenido.
    En mi pagina main.master tengo lo siguiente:

    Y en mi pagina default.aspx:


    Agradeceria su ayuda para la solución de este error...

    ResponderEliminar
  16. Conversion failed when converting date and/or time from character string.

    ResponderEliminar
  17. wow si me mandaras el codigo fuente te lo agradeceria

    ResponderEliminar
  18. Buen día. Espero me puedas ayudar. Quiero saber como podría poner el nombre de mi usuario en la página web una vez ya me haya autenticado. Gracias y espero tu pronta respuesta. Hasta luego.

    ResponderEliminar
  19. tal vez algun dia contestes el por que del error Conversion failed when converting date and/or time from character string. Creo que esta el error se debe a algo en el procedimiento almacenado...

    ResponderEliminar
  20. Exactamente es en el procedimiento, lo solucione comentando las sig lineas,

    --SET @FECHA_LIMITE='20161231--LIMITE 31 dic 2016'
    --IF(GETDATE()>@FECHA_LIMITE)
    --GOTO ERROR

    si esta mal, comenten porfa

    ResponderEliminar
    Respuestas
    1. Esta mal, realmente debe quedar:

      SET @FECHA_LIMITE='20161231'--LIMITE 31 dic 2016

      donde --LIMITE 31 dic 2016 es únicamente un comentario

      Eliminar
  21. Me aparece el siguiente error Incorrect syntax near ','.

    ResponderEliminar
  22. Hola buenas noches, soy nuevo en el uso de ASP.NET agradezco tutoriales como estos; estoy siguiendo el ejemplo, al hacer clic en el botón Entrar me sale el siguiente error: Error de inicio de sesión del usuario 'webuser'.

    Alguien sabe como solicionarlo??

    Gracias.

    ResponderEliminar
    Respuestas
    1. Mandame un correo darthsolitude@gmail.com. con gusto te ayudare. Buen día.

      Eliminar
  23. Que tal al ejecutar hasta esta parte me sale este error:

    Error de desbordamiento aritmético al convertir expression al tipo de datos datetime.

    Puedes ayudarme

    ResponderEliminar
  24. Alguien que tenga el proyecto terminado me lo podria pasar se los agradeceria les dejo mi corre yotuel_my@hotmail.com

    ResponderEliminar
  25. Amigo todo esta bien, pero cuando ingreso al login no me ingresa, me sale que error de sintaxis, me podrias ayudar?

    ResponderEliminar
  26. Buenas, alguien tiene el código completo, tengo un proyecto de la U, y lo que necesito en el login con el código de validar usuarios y sus roles, les agradezco su ayuda, este es mi correo; ldanielm2@hotmail.com. Gracias.

    ResponderEliminar
  27. tengo el siguiente error

    "A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)"

    alguien me podria ayudar

    saludos
    de antemano gracias

    ResponderEliminar
  28. alguien que me ayude con el codigo correcto por favor ya que estoy en mi proyecto final este es mi correo y podemos negociar amendez1397@gmail.com

    ResponderEliminar
  29. holaaaaa, amigo sabes tengo el siguiente error
    <asp:LinkButton ID="btnCerrarSesion" runat="server"
    no cacho muy bien que es lo que le esta pasando :S espero que me ayudes porfavor, de ante mano mil gracias :D

    ResponderEliminar
    Respuestas
    1. Hola tengo el mismo error y aun no lo puedo solucionar

      Eliminar
  30. me sale error en el lblopciones y no accede mi login con usuario: admin contraseña:admin si me pueden enviar a mi correo rulmanthomas@gmail.com

    ResponderEliminar
  31. alguien tiene el código completo,me lo pueden enviar porfavor a mi correo fer4085@gmail.com se los agradeceria mucho

    ResponderEliminar
  32. Disculpa pongo los siguientes datos de mi sql y me sale el siguiente error:
    Error relacionado con la red o específico de la instancia mientras se establecía una conexión con el servidor SQL Server. No se encontró el servidor o éste no estaba accesible. Compruebe que el nombre de la instancia es correcto y que SQL Server está configurado para admitir conexiones remotas. (provider: Named Pipes Provider, error: 40 - No se pudo abrir una conexión con SQL Server)

    ResponderEliminar