c#开发电子商务网站—我的笔记

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

   

电子商务网站(C#版)

通过一个在线的电子商务网站(网上书店销售系统)的实例,来讲述如何采用ASP.NET 3.5+SQL Server 2010的模式定制一个小型的电子商务平台。系统采用了模块化的设计方法,根据用户的需求及程序的应用与维护的易用性,将系统各个部分置于不同的模块当中,方便了程序的扩展与维护,同时建立了程序功能复用的基础。

本章介绍的系统–网上书店销售平台属于B2C电子商务网站,它能够绕过中介(如批发商、销售商或经销商)建立与客户的直接关系。该网站可以为用户提供商品(书籍)的详细信息,支持用户在线购买商品(书籍),并提交自己的订单。同时,用户可以提交商品评论和网站建议。网上书店销售平台使购买书籍变得更方便、更容易。

通过学习,读者还可以完成网上手机销售系统、网上音像店、在线首饰、网上购物等类似系统的设计。

通过阅读,读者可以学习到:

购物车的实现机制。

LINQ查询技术。

数据库操作的O/R映射机制。

网站中的搜索技术。

实现GridView控件的多种应用。

 系统总体设计

本章设计的是一个简单的网上书店销售系统,使用ASP.NET 3.5技术开发,结构是浏览器/服务器(B/S)的网络数据库应用系统。  需求分析

网上书店销售平台是一个完整的B2C电子商务网站。在本系统中,主要包括用户登录和注册功能、图书搜索功能、书籍信息管理功能、新书推荐和本站新闻模块、用户留言功能、购物车和订单管理功能等。

用户登录和注册功能:包括用户登录和注册,管理员登录和用户管理等。

图书搜索功能:通过图书类别搜索图书。

书籍信息管理功能:包括所有书籍的浏览和单本图书详细信息的浏览等。如果是管理员,还可在后台对书籍进行添加、修改、删除等操作。

新书推荐和本站新闻模块:首页的两大功能,支持管理员在后台编辑这两项功能。

用户留言功能:用于用户与管理员的交互,当用户需要某本书但网站中没有时,用户可以通过留言告诉管理员。用户有什么好的提议,也可以用此方法告诉管理员。管理员可以在后台对用户留言进行浏览、编辑和删除。

购物车和订单管理功能:当用户选择书籍后,可放入购物车,然后通过订单管理功能实现最终付款。购物车和订单管理功能主要包括添加书籍到购物车、浏览购物车中的书籍,以及提交订单。如果是管理员,还可在后台查看用户的订单。

系统功能结构

按照本网站的系统功能设计,可以把系统划分为用户管理模块、用户搜索模块、书籍信息管理模块、新书推荐与本站新闻模块、用户留言模块以及购物车和订单管理模块。系统功能如图

构建开发环境

前面提到过本系统使用ASP.NET 3.5构建B/S系统的项目。ASP.NET 3.5是基础.NET 3.5框架上的Web应用开发技术,其开发工具是VS 2008,所以本例要用到的开发工具及数据库如下:

基于.NET Framework 3.5版的Visual Studio 2010。

Microsoft SQL Server 2010数据库。

数据库操作使用LINQ技术。

系统预览

系统最大的特点是分为普通用户和管理员两个操作入口,默认登录页是Default.aspx,在浏览器中的效果如图11.2所示。首页会显示网站的新闻和新书推荐,默认只推荐一本新书。用户可以通过单击图书名链接打开图书的详细信息页面,如图

说明:网站最上面的一行菜单,使用Menu控件完成,起到网站的导航作用,一般称为导航菜单。

如果是用户登录,直接在导航菜单下的用户名和密码处输入注册信息,单击"登录"按钮就可以登录。如果是新用户,则单击"注册"链接,转到注册页面,注册时需要填写如图11.4所示的各个字段。如果是管理员登录,则需要单击导航菜单栏中的"管理员登录"链接,打开管理员登录界面,如图11.5所示。登录后的效果与普通用户显示的界面不同,仔细查看它的导航菜单,如图

系统数据库设计

数据库用来存储和管理网上书店销售平台所需的数据,对整个系统的实现起着极其重要的作用。下面介绍一下系统数据库的设计。

 数据表设计(1)

考虑网上书店销售平台的实际需要,本系统至少需要的数据包括用户数据、书籍数据、用户留言、订单数据、新书推荐。

(1)用户表(UserInfo):用来存储用户的数据,如用户ID、用户名、用户密码、用户地址、E-mail等。表的字段说明如表11.1所示。

表1  用户表(UserInfo)

字段名称

数据类型

字段大小

是否主键

是否为空

说明

UserName

nchar

50

用户ID

Name

nchar

50

用户名

Password

nchar

30

用户密码

Email

nchar

50

电子邮件

Address

nchar

50

地址

DateTime

DateTime

N/A

注册时间

(2)图书信息表(BookInfo):用来存储图书信息,如用图书名、图书ID、图书价格、图书出版社等。字段说明如表11.2所示。

表2  图书信息表(BookInfo)

字段名称

数据类型

字段大小

是否主键

是否为空

说明

BookID

nchar

30

书籍ID

BookName

nchar

30

书籍名

BookAddress

nchar

30

出版社

BookPrice

int

N/A

价格

BookDate

DateTime

N/A

出版日期

BookPeople

nchar

30

作者

BookSay

nchar

300

对书籍的简介

BookPhoto

nchar

50

图书的封面

数据表设计(2)

(3)新书推荐表(NewBook):用来存储推荐图书的图书名、图书ID、图书价格等。字段说明如表11.3所示。

表3  新书推荐表(NewBook)

字段名称

数据类型

字段大小

是否主键

是否为空

说明

NewBookID

int

N/A

新书ID

BookID

nchar

30

与书ID关联

NewBookName

nchar

50

新书名

NewBookSay

nchar

300

新书描述

NewBookPhoto

nchar

50

新书封面

(4)图书订单表BookOrder:用来存储用户购买图书的图书名,图书价格,图书数量,订单用户的姓名等,字段说明如表11.4所示。

表4  图书订单表(BookOrder)

字段名称

数据类型

字段大小

是否主键

是否为空

说明

OrderID

int

N/A

订单ID

BookName

nchar

50

书籍名

BookID

nchar

30

书籍的ID

BookPrice

int

N/A

价格

UserName

nchar

50

用户名

DateTime

DateTime

N/A

下订单的时间

BookNum

int

N/A

购买数量

(5)用户留言表(UserMessage):用来存储用户留言内容、留言主题、留言的用户名等,字段说明如表11.5所示。

表5  用户留言表(UserMessage)

字段名称

数据类型

字段大小

是否主键

是否为空

说明

MessageID

int

N/A

留言ID

Title

nchar

50

留言主题

Email

nchar

50

留言者邮箱

MsContent

nchar

300

留言内容

Name

nchar

50

用户名

DateTime

DateTime

N/A

留言时间

表关系设计

在本系统数据库中,各个表之间的关系比较简单,表之间的引用关系也比较简单,用户留言表为单独的一张表。最终的表关系设计如图

表实体映射–O/R

本章使用LINQ查询数据库,并实现完全面向对象的操作。所以需要把数据库中的所有表都映射到应用程序中。映射步骤如下。

选择"视图"|"服务器资源管理器"命令,打开服务器资源管理器窗口。

右键单击"数据连接"节点,在弹出的快捷菜单中选择"添加连接"命令,要连接的就是本例需要的数据库BookManager。添加完毕后,单击"确定"按钮回到服务器资源管理器。

从表Tables节点中可以看到当前数据库下的所有表。

在网站根目录下添加一个LINQ to SQL Classes类,会自动打开设计视图,如图11.8所示。

把Tables节点下的所有表拖放到设计视图,单击"保存"按钮,保存所有的映射类。

本例使用的拖放方式直接生成了数据表到数据类的映射。这些映射关系以XML的形式保存在应用程序下,如下面的代码所示。而类文件保存在BookManagerDataClasses.designer.cs中。

代码位置:见光盘中本章源代码的BookShopMarket/App_Code/ BookManagerDataClasses. dbml.layout文件。

01  <?xml version="1.0" encoding="utf-8"?>   02  <ordesignerObjectsDiagram dslVersion="1.0.0.0"  absoluteBounds="0, 0, 11, 8.5"    03  name="BookManagerDataClasses">   04    <DataContextMoniker Name="/BookManagerDataClassesDataContext" />   05    <nestedChildShapes>   06      <classShape Id="71ae7541-73b7-4f69-8f4e- 14dca9b99636" absoluteBounds= "4.75, 3, 2, 07   2.1228255208333335">   08        <DataClassMoniker Name="/BookManagerData ClassesDataContext/BookInfo" />   09        <nestedChildShapes>   10          <elementListCompartment Id="e8ad1c7f- 4011-44ed-9c09-b7e480f7ffcd"    11  absoluteBounds="4.7650000000000006, 3.46,  1.9700000000000002, 1.56282552083 33335"    12  name="DataPropertiesCompartment" titleTextColor=" Black" itemTextColor= "Black" />   13        </nestedChildShapes>   14      </classShape>   15      …………………………………   16    </nestedChildShapes>   17  </ordesignerObjectsDiagram> 

类文件BookManagerDataClasses.designer.cs,部分代码如下所示。

1   #pragma warning disable 1591   2   using System.Reflection;   3   [System.Data.Linq.Mapping.BookDataBase Attribute(Name="BookManager")]                    //定义数据库   4      5   public partial class BookManagerDataClassesDataContext : System.Data.Linq. DataContext   6   {   7       [Table(Name="dbo.BookInfo")]                        //定义表   8       public partial class BookInfo :  INotifyPropertyChanging, InotifyProperty Changed   9       {   10          private static PropertyChangingEventArgs  emptyChangingEventArgs =   11            new  PropertyChangingEventArgs(String.Empty);   12          private string _BookID;   13      }   14      ……………………   15  } 

开发前准备工作

本例使用了母版页设计,普通用户登录和管理员登录后各使用了两种母版。为了统一操作的方便,在开发前,就需要把母版及母版内容设计好。

在当前项目中添加一个母版页MasterPage.master,让其为管理员的页面服务。在母版页中添加一个Menu导航控件和一个XmlDataSource数据源组件。母版页的设计代码如下所示。这里的代码一定要把table表格设计好,否则母版页的嵌套很可能失败。

代码位置:见光盘中本章源代码的BookShopMarket/MasterPage.master。

01  <table height="237" cellSpacing="0" borderColorDark= "#cccccc" cellPadding="5"    02  width="95%" align="center" borderColorLight="#000000" border="1">   03          <tr bgColor="#cccccc">   04              <td vAlign="center" bgColor="#cccccc"  colSpan="2" height="5%">   05                  <asp:Menu ID="Menu1"  runat="server"         06               DataSourceID="XmlDataSource1"  BackColor=" #E3EAEB"    07               DynamicHorizontalOffset="2" Font-Names=" Verdana"  Font-Size="1.2em"    08               ForeColor="#666666" Height="16px" Orientation="Horizontal"     09               StaticSubMenuIndent="10px" Width="563px">   10                  <StaticSelectedStyle BackColor="#1C5E55" />   11                  <StaticMenuItemStyle HorizontalPadding ="5px" VerticalPadding= "2px" />   12                 <DynamicHoverStyle BackColor="#666666" ForeColor="White" />   13                 <DynamicMenuStyle BackColor="#E3EAEB" />   14                 <DynamicSelectedStyle BackColor="#1C5E55" />   15                 <DynamicMenuItemStyle HorizontalPadding="5px"    16  VerticalPadding="2px" />   17                     <DataBindings>   18                         <asp:MenuItemBinding DataMember ="siteMapNode"    19                               NavigateUrlField="url"    TextField="title" />   20                        </DataBindings>   21                        <StaticHoverStyle BackColor="#666666"  ForeColor="White" />   22                  </asp:Menu>         </tr>   23          <tr bgColor="#cccccc">   24              <td height="5%" colSpan="2" align="left" valign="top">   25                  <uc1:Login ID="Login1" runat="server" />   26          </tr><tr> <td height="90%" colSpan="2">   27        <asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server">           28        </asp:ContentPlaceHolder></td> </tr>   29    </table>    30      <asp:XmlDataSource ID="XmlDataSource1" runat="server"            31         DataFile="~/AdminMenu.xml" XPath="siteMapNodes/siteMapNode">   32      </asp:XmlDataSource> 

第5~22行代码是一个Menu菜单控件,用来设计页面的布局。

第30~32行代码使用了XmlDataSource控件,数据源来自XML文件AdminMenu.xml。在获取数据时使用了XPath="siteMapNodes/siteMapNode",来获取内容节点。

用户界面的母版由MasterPage2.master完成,数据来自UserMenu.xml,所采用的样式和方法都与MasterPage.master一样,所以这里不再给出代码。

会员管理模块实现

会员管理模块主要包括会员注册模块、会员登录模块、管理员登录模块、用户信息的编辑与删除。在网络销售系统中,只有注册后的用户才可以下订单买书。

  会员注册模块(1)

在项目BookManager中添加一个页面Register.aspx,打开该页面的设计视图。在设计视图中添加控件,包括登录名(UserName)、真实姓名(Name)、密码(PassWord)、确认密码(Psd)、邮箱(Email)和用户地址(Address),在对各个控件添加验证控件。用户注册页面Register.aspx的设计视图如图

该页面的HTML代码如下所示,关键数据要求必须填写,两次密码输入必须相同,所以这里添加了ASP.NET的验证控件RequiredFieldValidator(必填控件)和CompareValidator(比较控件)。

代码位置:见光盘中本章源代码的BookShopMarket/Register.aspx文件。

01  <td class="style4" colspan="2">用户注册</td>   02  <td class="style2">登录名*</td><td class="style3">   03      <asp:TextBox ID="UserName" runat=" server"></asp:TextBox>   04      <asp:Button ID="RepeatBtn" runat=" server" CausesValidation="False"    05          onclick="RepeatBtn_Click" Text="是否存在?" Width="80px" />   06      <asp:RequiredFieldValidator ID=" RequiredFieldValidator1" runat="server"    07          ControlToValidate="username" ErrorMessage="登录名不为空   08  "></asp:RequiredFieldValidator>   09   </td> <td class="style2">   10       真实姓名*</td>   11   <td class="style3">   12       <asp:TextBox ID="Name" runat="server"></asp:TextBox>   13       <asp:RequiredFieldValidator ID=" RequiredFieldValidator2" runat="server"    14      ControlToValidate="name" ErrorMessage="姓名不为空"> </asp:RequiredField Validator>   15  </td> <td class="style2"> 密码*</td>  <td class="style3">   16         <asp:TextBox ID="PassWord" runat="server"    17  TextMode="Password"></asp:TextBox>   18         <asp:RequiredFieldValidator ID=" RequiredFieldValidator3" runat="server"    19               ControlToValidate="password" ErrorMessage="密码不为空   20  "></asp:RequiredFieldValidator>   21  </td> <td class="style2"> 确认密码*</td> <td class="style3">   22        <asp:TextBox ID="Psd" runat="server" TextMode=" Password"></asp:TextBox>   23        <asp:CompareValidator ID="CompareValidator1" runat="server"    24             ControlToCompare="password" ControlToValidate="psd"  25              ErrorMessage="确认密码错误"></asp:CompareValidator>   26  </td> <td class="style2"> 邮箱*</td> <td class="style3">   27         <asp:TextBox ID="Email" runat="server"></asp:TextBox>   28         <asp:RegularExpressionValidator  ID="RegularExpressionValidator1" runat ="server"    29          ControlToValidate="email" ErrorMessage="邮箱输入有误"    30         ValidationExpression="w+ ([-+.']w+)*@w+([-.]w+)*.w+([-.]w+)*">   31         </asp:RegularExpressionValidator>   32  …………………… 

第6~8行代码是一个必填控件,如果它针对的username文本框没有任何输入,则验证无法通过。

第23~25行代码是一个比较控件,它对用户两次输入的密码进行对比,如果不相同,验证也无法功过。

会员注册时,包括两个功能:判断用户名是否存在;实现用户注册。这里我们分两部分讲解。

会员注册模块(2)

1.判断用户名是否存在

用户填写登录名后,需要先处理用户名重名的问题,在UserLogin.cs类中完成。打开UserLogin.cs,添加如下代码所示的方法。

说明:所有的处理类默认都放在App_Code文件夹下。

代码位置:见光盘中本章源代码的BookShopMarket/App_Code/UserLogin.cs文件。

01      //判断用户注册时,用户名是否存在,参数为登录名   02      public static int RepeatName(string name)   03      {   04          BookManagerDataClassesDataContext book =    05                  new BookManagerDataClassesDataContext();  //数据上下文   06          try   07          {//是否存在数据   08             UserInfo  user = book.UserInfos.Where  (u => u.UserName == name).First();   09              if (user !=null)   10                  return 1;       //返回1   11              else  12                  return 0;       //返回0   13          }   14          catch   15          {   16              return 0;       //返回0   17          }   18      } 

第8行代码使用LINQ查询实体类是否有符合条件的对象。

第16行代码表示如果查询过程中发生错误,则返回0,表示查询不到。

此代码的作用查看是该用户名是否存在,如果存在,则返回一个大于0的整数,打开Register.aspx.cx文件,添加"是否存在"按钮的事件处理函数,此处用了一个RepeatName()方法,因为在"提交"按钮中,也要对重名进行判断。实现代码如下所示。

代码位置:见光盘中本章源代码的BookShopMarket/Register.aspx.cs文件。

01   protected void RepeatBtn_Click(object sender, EventArgs e)   02   {   03       bool ReName = RepeatName();            //判断用户名是否存在   04   }   05   public bool RepeatName()   06   {   07        string name = UserName.Text;          //获取用户的输入   08       if (UserLogin.RepeatName(name) > 0)        //判断用户是否存在   09       {   10           Response.Write("<script>alert('用户名存在')</script>");   11           return false;   12       }   13       else  14       {   15           Response.Write("<script>alert('恭喜你,用户名不存在')</script>");   16           return true;   17       }   18   } 

第8行代码首先调用UserLogin类的RepeatName方法判断用户名是否存在。

第10行代码和第15行代码是Web中通用的弹出对话框方式,这和Windows程序不同,请读者一定注意。

会员注册模块(3)

2.实现用户注册

添加用户"提交"按钮的事件,提交前一定要先判断是否已经存在此用户,这里直接调用前面的方法就可以,然后再实现添加新用户功能。在UserLogin类中添加新用户的功能,代码如下所示。

代码位置:见光盘中本章源代码的BookShopMarket/App_Code/UserLogin.cs文件。

01  public static void Add(UserInfo user)   02  {   03          BookManagerDataClassesDataContext book =    04              new BookManagerDataClassesDataContext();   //数据上下文   05          book.UserInfos.InsertOnSubmit(user);    //插入数据   06          book.SubmitChanges();                  //提交更改   07  } 

打开Register.aspx.cs文件,添加"提交"按钮事件处理函数,代码如下所示。

代码位置:见光盘中本章源代码的BookShopMarket/Register.aspx.cs文件。

01  protected void Button1_Click(object sender, EventArgs e)   02  {   03      bool ReName = false;   04      ReName = RepeatName();                   //判断用户名是否存在   05      //如果用户名不存在与所有控件验证都通过的时候   06      if (Page.IsValid && ReName)   07      {   08          UserInfo user = new UserInfo();      //创建新用户对象   09          user.UserName = UserName.Text;       //获取登录名   10          user.Name = Name.Text;               //获取名称   11          user.Password = PassWord.Text;       //获取密码   12          user.Email = Email.Text;            //获取邮箱   13          user.Address = Address.Text;            //获取地址   14           user.DateTime = DateTime.Now.Date;    //获取当前日期   15           UserLogin.Add(user);                     //添加用户   16           Response.Redirect("Default.aspx");       //以用户登录身份跳到主页   17       }   18       else Response.Write("<script>alert('注册失败')</script>");   19   } 

第4行代码首先判断当前用户是否存在。

第8~14行代码创建一个新用户对象,并为其赋值。

第15行代码调用UserLogin类的Add方法实现添加用户的功能。

用户登录模块实现(1)

会员登录模块是会员进入会员管理系统的入口,只有登录的会员才有购物功能。由于在很多页面中都有用户登录模块和用户搜索模块,所以此处把用户登录模块和用户搜索模块做成一个用户控件。添加一个Web用户控件Login.ascx,用户搜索模块将在11.4.3节重点介绍。会员登录的设计页面如图11.10所示。

用户控件的HTML代码如下所示。这里必须特别注意的就是添加了一个注册链接,此链接会导航到前面创建的注册页面。

代码位置:见光盘中本章源代码的BookShopMarket/controls/Login.ascx文件。

01  <asp:Label ID="LbUsername" runat="server"  Text="用户名:"></asp:Label>   02      <asp:TextBox ID="UserName" runat="server"  Width="85px"></asp:TextBox>   03      <asp:Label ID="LbPassWord" runat="server"  Text="密码:"></asp:Label>   04      <asp:TextBox ID="PassWord" runat="server"  Width="85px"    05  TextMode="Password"></asp:TextBox>   06      &nbsp;<asp:Button ID="LoginBtn" runat="server"  Text="登录" Height="27px"    07          onclick="LoginBtn_Click" Width="46px" />   08  &nbsp;   09      <asp:LinkButton ID="Register" runat="server"  Font-Underline="False"    10          PostBackUrl="~/Register.aspx">注册</asp:LinkButton> 

在初始化页面时,登录面板是可见的。当用户登录成功后,登录面板是不可见的。这时用Session["UserName"]来判断用户是否登录。Session["UserName"]在Global.asax的Session_Start中定义,后面会介绍。此处判断用户是否已登录的代码如下所示。

代码位置:见光盘中本章源代码的BookShopMarket/controls/Login.ascx.cs文件。

01  protected void Page_Load(object sender, EventArgs e)   02  {   03      if (Session["UserName"].ToString() != "")    //判断用户是否已经登录   04      {   05          LoginUser();                          //如果用户登录成,执行此方法   06      }    07  }   08  void LoginUser()                            //用户登录成功   09  {   10      PassWord.Visible = false;                //密码框不可见   11      LbPassWord.Visible = false;               //密码不可见   12      UserName.Visible = false;                 //用户名框不可见   13      //把'用户名'改为'你好,(登录成功的用户名)'  14      LbUsername.Text = "你好," + Session["UserName"].ToString(); 15      LbUsername.ForeColor = System.Drawing.Color.Blue;    //把上面的文字变成蓝色   16      LbUsername.Font.Size = 18;             //字体大小改为18px   17      //把宽度变为395px,用来填充文本宽度, 使布局不变,否则搜索框会向左边移动   18      LbUsername.Width = 395;   19      LoginBtn.Visible = false;        //"登录"按钮不可见   20      Register.Visible = false;        //"注册"按钮不可见   21  } 

第3~6行代码通过Session来判断用户是否已经登录,Session类似于一个小型缓存器。

第10~20行代码设计界面的布局,设置哪些控件该显示,哪些不该显示。

用户身份验证是通过"登录"按钮的事件来实现的,需要对用户名和密码进行判断。这里用到了UserLogin类的login()方法,打开UserLogin.cs,添加代码如下所示的内容。

代码位置:见光盘中本章源代码的BookShopMarket/App_Code/UserLogin.cs文件。

01  //判断用户登录时,用户名与密码是否正确,如果正确返回true,否则返回false  02  public static bool login(string UserName, string PassWord)   03  {   04      BookManagerDataClassesDataContext book 、   05                   = new BookManagerDataClassesDataContext(); //数据上下文   06      try   07      {   08          UserInfo user = book.UserInfos.Where (u => u.UserName ==    09              UserName && u.Password == PassWord).First();   //是否存在数据   10          if (user !=null)   11              return true;                            //返回成功   12          else  13              return false;                    //返回失败   14      }   15      catch   16      {   17          return false;         //返回失败   18      }   19  } 

第4行代码是一个标准的上下文创建语句,后面会多次用到,要使用实体类,需要生成上下文。

第8~9行代码使用LINQ查询实体类中的数据。

在Login.ascx.cs中,添加"登录"事件的处理函数,代码如下所示。登录时判断用户的用户名和密码是否正确。如果正确,则调用LoginUser()方法显示登录面板。

用户登录模块实现(2)

代码位置:见光盘中本章源代码的BookShopMarket/controls/Login.ascx.cs文件。

01  protected void LoginBtn_Click(object sender, EventArgs e)   02  {   03      if (UserName.Text != "" && PassWord.Text != "")  //判断用户输入是否为空   04      {   05          if (UserLogin.login(UserName.Text, PassWord.Text))   //判断用户名和密码是否正确   06          {   07              //把登录后的名字保存在Session["UserName"]中   08              Session["UserName"] = UserName.Text;   09              LoginUser();                   //如果用户登录成功执行此方法   10          }   11          else Response.Write("<script>window.alert ('用户名或密码错误')</script>");   12      }   13      else Response.Write("<script>window.alert ('用户名和密码不为空')</script>");   14  } 

第3行代码首先判断用户是否已经输入了内容,也可以在客户端使用验证控件完成这个工作。

第5行代码调用UserLogin类的login方法判断输入是否正确。

第8行代码非常关键,用户登录成功后,通过Session保存其用户名,在后面的判断中会多次使用。

此处用了Session["UserName"],如果其没有在Global.asax的Session_Start中定义,就会报错。在Global.asax的Session_Start中定义的意义是:每当用户进入网站时,系统就会为用户初始化一个Session["UserName"]对象。初始化时,把此对象的值设为空。当用户登录为会员时,此对象的值就不为空了,此时Session["UserName"]就等于登录用户的用户名。关于Global.asax的Session_Start事件可以参考下面的代码。

代码位置:见光盘中本章源代码的BookShopMarket/Global.asax文件。

01  void Session_Start(object sender, EventArgs e)    02  {   03      //在新会话启动时运行的代码   04      Session["UserName"] = "";          //初始化用户名   05      Session["BookName"] = "";           //初始化书名   06      Session["BookNum"] = "0";           //初始化购买图书的数量   07      Session["BookPrice"] = "0";          //初始化购买图书的价格   08      Session["SearchBookType"] = "";        //用于查找功能,说明图书类型   09      Session["SearchKey"] = "";         //用于查找功能,说明图书关键字   10      //管理员用户名,防止用户不输入管 理员姓名和密码,直接跳到管理页   11      Session["AdminLogin"] = "";   12  } 

关于其他的Session对象,在以后用到时再详细介绍。如果网站根目录下没有Global.asax文件,可右键单击当前项目,在"添加新项"对话框中选中"全局应用程序类"项,将此文件添加到项目中。

管理员登录模块实现

登录分为两种登录情况:普通用户登录和管理员登录。管理员相当于网站的最高级别领导,管理员登录到后台可以对用户、书籍、订单等数据进行管理。管理员登录页面是AdminLogin.aspx,该页面设计视图如图11.11所示。

管理员登录的部分HTML如下代码所示,界面设计并没有特别之处。

代码位置:见光盘中本章源代码的BookShopMarket/admin/AdminLogin.ascx文件。

01  <table border="2" class="style1" style="text-align: center; height: 247px;">   02      <tr>   03          <td class="style2" colspan="2">   04              管理员登录</td>   05      </tr>   06      <tr>   07          <td>   08              用户名:</td>   09          <td>   10              <asp:TextBox ID="UserName"  runat="server" Width="145px"></asp:TextBox>   11          </td>   12      </tr>   13      <tr>   14          <td>   15              密码:</td>   16          <td>   17              <asp:TextBox ID="PassWord" runat=" server" TextMode="Password"    18                  Width="145px"></asp:TextBox>   19          </td>   20      </tr>   21      <tr>   22          <td colspan="2">   23              <asp:Button ID="LoginBtn" runat="server"  Text="登录" Height="28px"    24                  onclick="LoginBtn_Click" Width="56px" />   25          </td>   26      </tr>   27  </table

单击"登录"按钮时,需要对管理员的用户名和密码进行判断。如果用户名和密码正确,则进入管理页面,此处用到了一个UserLogin类的AdminLogin()方法。该主法返回的是一个bool值,如下面的代码所示。这里后台绑定了用户名和密码,而不是从数据库中读取。

代码位置:见光盘中本章源代码的BookShopMarket/App_Code/UserLogin.cs文件。

01  //判断管理员登录时,用户名与密码是否存在   02   public static bool AdminLogin(string UserName, string PassWord)   03   {   04       //如果管理员的用户名和密码是"admin",则返回true  05       if (UserName == "admin" && PassWord == "admin")   06       {   07           return true;   08       }   09       else return false;   10   } 

双击"登录"按钮,完善它的事件处理函数,如下面的代码所示。

代码位置:见光盘中本章源代码的BookShopMarket/admin/AdminLogin.ascx.cs文件。

01  //用于管理员登录   02  protected void LoginBtn_Click(object sender, EventArgs e)   03  {   04      //判断管理员登录时,用户名与密码是否正确   05      if (UserLogin.AdminLogin(UserName.Text, PassWord.Text))   06      {   07           //如果用户登录成功,给Session["AdminLogin"]传值   08           Session["AdminLogin"] = "AdminLogin";   09           Response.Redirect("~\admin\ adminpage.aspx");//跳转到管理员主页   10       }   11       else Response.Write("<script>alert ('管理员姓名或密码错误')</script>");   12  } 

第5行代码验证管理员的用户名和密码。

第8行代码非常关键,如果管理员登录成功,则用Session保存管理员信息,这样在进入管理员专用页面时,会先判断Session中是否有值,没有就不允许进入。

注意:这里管理员的用户名和密码都是admin。

用户管理模块实现

这是管理员的功能,管理员必须登录到后台,才能操作该页面。这个页面是AdminUserInfo.aspx。管理员可以在后台对用户进行编辑和删除,该页面的设计视图如图11.12所示。

该页面主要由一个GridView控件实现,不需要在后台写代码。AdminUserInfo.aspx的 HTML代码如下所示。

代码位置:见光盘中本章源代码的BookShopMarket/admin/AdminUserInfo.ascx文件。

01        <asp:GridView ID="GridView1" runat="server" AllowPaging="True"    02            AllowSorting="True" AutoGenerateColumns="False"  CellPadding="4"    03            DataKeyNames="UserName"  DataSourceID="SqlDataSource1"    04  ForeColor="#333333"    05            GridLines="None" Height="18px"  PageSize="8" Width="787px">   06            <PagerSettings FirstPageText="首页"  LastPageText="尾页"    07                Mode="NextPreviousFirstLast"  NextPageText=" 下一页" PreviousPage Text="   08  上一页" />   09            <FooterStyle BackColor="#507CD1"  Font-Bold="True" ForeColor="White" />   10            <RowStyle BackColor="#EFF3FB" />   11            <Columns>   12                <asp:CommandField ButtonType="Button"  HeaderText="用户名"    18  ReadOnly="True"    19                    SortExpression="UserName">   20                    <ControlStyle Width="60px" />   21                </asp:BoundField>   22                <asp:BoundField DataField="Name"  HeaderText="真实姓名"    23  SortExpression="Name">   24                    <ControlStyle Width="60px" />   25                </asp:BoundField>   26                <asp:BoundField DataField="PassWord"  HeaderText="密码"    27  SortExpression="PassWord">   28                    <ControlStyle Width="70px" />   29                </asp:BoundField>   30                <asp:BoundField DataField="Email"  HeaderText="邮箱"    31  SortExpression="Email">   32                    <ControlStyle Width="100px" />   33                </asp:BoundField>   34                <asp:BoundField DataField="Address"  HeaderText="地址"    35  SortExpression="Address">   36                    <ControlStyle Width="130px" />   37                </asp:BoundField>   38                <asp:BoundField DataField="Datetime"  HeaderText="注册时间"    39                    SortExpression="Datetime">   40                    <ControlStyle Width="130px" />   41                </asp:BoundField>   42            </Columns>   43            <PagerStyle BackColor="#2461BF" ForeColor=" White" HorizontalAlign= "Center" 44    />   45            <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True"    46  ForeColor="#333333" />   47            <HeaderStyle BackColor="#507CD1" Font-Bold=" True" ForeColor="White" />   48            <EditRowStyle BackColor="#2461BF" />   49            <AlternatingRowStyle BackColor="White" />   50        </asp:GridView>   51  …………………………………  至此,用户登录模块就已经实现了。浏览效果如图11.13所示。输入用户名和密码,单击登录按钮,成功后如图11.14所示。注意两个图的导航栏内容不同,一个是针对管理员的导航,一个是针对普通用户的导航。

书籍类别管理

书籍信息管理由浏览图书、浏览图书详情、添加图书信息、图书信息的编辑与删除等模块组成。这些模块有的只允许管理员操作,所以编写代码时要注意条件的判断。

  浏览图书模块实现

在项目中添加一个AllBook.aspx窗体,继承自母版页:MasterPage.master,浏览图书功能主要由GirdView控件来实现,因为通过其浏览,可以用尽量少的代码完成图书浏览功能。该页面的HTML代码如下所示,给出这段代码的目的是让读者了解,在绑定字段中添加了一个按钮,CommandName属性设置为info,通过其可以访问所选书的详细信息。

代码位置:见光盘中本章源代码的BookShopMarket/AllBook.aspx文件。

01  <asp:GridView ID="GridView1" runat="server"  AllowPaging="True"    02          AllowSorting="True" AutoGenerateColumns=" False" CellPadding="4"    03          DataKeyNames="bookid" DataSourceID=" SqlDataSource1" ForeColor="#333333"    04          GridLines="None" Height="44px" Width="796px" PageSize="8"    05          onrowcommand="GridView1_RowCommand">   06          <PagerSettings FirstPageText="首页" LastPageText="尾页"    07           Mode="NextPreviousFirstLast" NextPageText=" 下一页" PreviousPageText="上一页   08  " />   09          <FooterStyle BackColor="#1C5E55" Font-Bold=" True" ForeColor="White" />   10          <RowStyle BackColor="#E3EAEB" />   11          <Columns>   12             <asp:BoundField DataField="bookname"  HeaderText="图书名"    13                 SortExpression="bookname"  ApplyFormatInEditMode="True" />   14             <asp:BoundField DataField="bookid"  HeaderText="图书ID" ReadOnly= "True"    15               SortExpression="bookid" />   16             <asp:BoundField DataField="bookprice"  DataFormatString="{0:c}"    17                  HeaderText="价格"  SortExpression="bookprice" />   18              <asp:BoundField DataField="bookaddress"  HeaderText="出版社"    19                  SortExpression="bookaddress" />   20              <asp:BoundField DataField="bookpeople" HeaderText="作者"    21                  SortExpression="bookpeople" />   22            <asp:ButtonField ButtonType="Button"    23                  CommandName="info" HeaderText="详细信息"    24                  ShowHeader="True" Text="详细信息" />   25              <asp:TemplateField HeaderText="加入购物篮">   26                  <EditItemTemplate>   27                      <asp:CheckBox ID="CheckBox1" runat="server" />   28                  </EditItemTemplate>   29                  <ItemTemplate>   30                      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   31                      <asp:CheckBox ID="CheckBox1"  runat="server" AutoPostBack= "True"    32                          oncheckedchanged="CheckBox1_CheckedChanged" />   33                  </ItemTemplate>   34                  <ControlStyle Width="20px" />   35              </asp:TemplateField>   36          </Columns>   37  ……………………………………   38      </asp:GridView> 

当用户单击"详细信息"按钮后,可以浏览图书的详细信息,这是通过后台的GridView1_ RowCommand事件完成的。一定要在设计端把"详细信息"按钮的CommandName设为info。"详细信息"按钮的事件处理函数如下代码所示。

代码位置:见光盘中本章源代码的BookShopMarket/AllBook.aspx.cs文件。

01  protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)   02   {   03       if (e.CommandName == "info")           //判断用户单击的是哪个按钮   04       {   05           int index = Convert.ToInt32(e.CommandArgument);  //获取用户单击按钮的行   06           //把单击按钮行的图书ID传给Session["bookname"]   07           Session["BookName"] = GridView1.Rows[index]. Cells[1].Text.ToString();   08           Response.Redirect("~/BookInfo.aspx");       //跳转到BookInfo页面中   09       }   10   } 

图书详细信息模块实现

图书详细信息模块显示图书的详细信息(如出版日期、出版社等),该模块通过BookInfo.aspx窗体来实现,页面的设计效果如图11.15所示。该页面主要由控件DataList实现。其中,DataList控件的HMTL代码如下所示。读者要关注的是DataList并不自己生成模板,而需要读者手动设计,设计的内容一定要在"ItemTemplate"模板内。

代码位置:见光盘中本章源代码的BookShopMarket/BookInfo.aspx文件。

01  <asp:DataList ID="DataList1" runat="server"  DataKeyField="bookid"    02              DataSourceID="SqlDataSource1"  CellPadding="4" ForeColor="#333333"    03          Width="799px" RepeatColumns="2">   04                  <FooterStyle BackColor="#1C5E55"  Font-Bold="True" ForeColor= "White"    05  />   06                  <AlternatingItemStyle BackColor="White" />   07                  <ItemStyle BackColor="#E3EAEB" />   08                  <SelectedItemStyle BackColor="# C5BBAF" Font-Bold="True"    09  ForeColor="#333333" />   10                  <HeaderStyle BackColor="#1C5E55"  Font-Bold="True" ForeColor= "White"    11  />   12                  <ItemTemplate>   13                      <table><tr><td rowspan="6">   14                      <asp:Image ID="BookImage"  runat="server" Height="243px"    15  Width="172px" />   16                      </td><td >书名</td><td>   17                  <asp:Label ID="BookName"  runat="server" Text='<%# Eval ("bookname")    18  %>' />   ………………… 

具体功能的实现比较简单,Session["BookName"]保存的是图书ID,Session["BookName"]在Global.asax的Session_Start中定义。这里的Session["BookName"]与用户登录模块的Session["UserName"]用法基本相同,此处不再详细介绍。图书的详细信息通过Session["BookName"]传递过来的值判断,然后绑定到DataList模板中,具体实现功能的代码如下所示。

代码位置:见光盘中本章源代码的BookShopMarket/BookInfo.aspx.cs文件。

01  protected void Page_Load(object sender, EventArgs e)   02  {   03      //如果用户没有选择图书,而直接跳到该页,则返回到主页   04      if (Session["BookName"].ToString() != "")   05      {   06          //改变datalist的查询方式,查询用户所需的图书信息。   07          SqlDataSource1.SelectCommand = "select *  from BookInfo where BookID='"    08             + Session["BookName"].ToString() + "'";   09          for (int i = 0; i < DataList1.Items.Count; i++)   10          {   11              //用户所需图书的图片   12              ((Image)DataList1.Items[i].FindControl ("BookImage")).ImageUrl =    13         "~\UploadImage\" + ((Label)DataList1.Items[i]. FindControl("Image Url")).Text;   14          }   15      }   16      else Response.Redirect("~/Default.aspx");   17  } 

第4行代码通过读取Session的值来判断用户的选择。

第7行代码通过设置SqlDataSource1控件的选择命令来更改查询条件。

第12~13行代码加载图书的封面图片,这非常关键,是网站中图片加载的主要方式。

【责任编辑: 云霞 TEL:(010)68476606】

图书添加模块实现

图书添加只有后台管理员可以操作,操作的页面是AdminAddBook.aspx。该页的界面设计效,果

该页面的部分HTML代码如下所示,设计页面时主要考虑上传图片这一难点,这里使用了FileUpload上传控件,读者一定要知道,此处数据库中保存的不是图片,而是图片的名称,因为图片会保存在服务器上,通过名称来获取。

代码位置:见光盘中本章源代码的BookShopMarket/admin/AdminAddBook.aspx文件。

01  <table  style="text-align: left; height: 470px; font-size: large; width: 731px;"    02          border="2"><tr> <td class="style4" colspan="2" >   03                      &lt;&lt;图书添加</td></tr> <tr>   04                  <td class="style1" > 图书名*</td><td>   05    <asp:TextBox ID="BookName" runat="server" Height="22px"    06  Width="188px"></asp:TextBox>   07    <asp:RequiredFieldValidator ID=" RequiredFieldValidator1" runat="server"    08    ControlToValidate="BookName" ErrorMessage="图书名不为空   09  "></asp:RequiredFieldValidator>   10                  </td></tr><tr><td class="style1" > 图书ID*</td><td>   11               <asp:TextBox ID="BookID" runat="server"  Width="188px"></asp: TextBox>   12              <asp:RequiredFieldValidator ID=" RequiredFieldValidator2" runat= "server"    13      ControlToValidate="BookID" ErrorMessage="图书ID不为空   14  "></asp:RequiredFieldValidator>   15                  </td> </tr>   16    ………………………………………………………   17              <tr><td class="style1" >上传图片:</td> <td>   18                      <asp:FileUpload ID="UploadImage"  runat="server" Width="241px" />   19                      <asp:Label ID="Label3" runat=" server" Text="(小于2M的jpg或bmp   20  图片)" Font-Bold="False"    21                          Font-Size="Medium"></asp:Label>   22                  </td> </tr><tr>   23                  <td class="style1" colspan="2" >   24                      <asp:Button ID="AddBookBtn"  runat="server" Text="确定"    25                          onclick="AddBookBtn_Click"  style="height: 26px" Height= "59px"    26                          Width="86px" />   27                  </td></tr></table>   28  <asp:Label ID="ShowMessage" runat="server" Width="128px"></asp:Label> 

双击"确定"按钮,在其事件处理函数中添加如下面的代码所示的内容。使用上传功能前,先在当前项目中创建一个名为UploadImage的文件夹,用来保存图片。这些图片一般都是图书的封面信息。

代码位置:见光盘中本章源代码的BookShopMarket/admin/AdminAddBook.aspx.cs文件。

01  protected void AddBookBtn_Click(object sender, EventArgs e)   02      {   03          string Path = Server.MapPath("~/UploadImage/");    //上传文件的路径   04          string FileName = UploadImage.PostedFile.FileName;   05          if (UploadImage.HasFile)                       //判断文件是否存在   06          {   07              //判断文件的大小与格式   08              if (UploadImage.PostedFile.ContentLength  < 2048000 &&    09  ((FileName.Substring(FileName.LastIndexOf(".") + 1). ToString().ToLower()) == "jpg" ||    10  (FileName.Substring(FileName.LastIndexOf(".") + 1). ToString().ToLower()) == "bmp"))   11              {   12                  UploadImage.SaveAs(Path +  UploadImage.FileName); //把图片保存起来   13              }   14              else  15              {   16                  ShowMessage.Text = "图片上传失败";   17                  return;   18              }   19          }   20          BookInfo bookinfo=new BookInfo{   21              BookID=BookID.Text,   22              BookName=BookName.Text,   23              BookAddress=BookAddress.Text,   24              BookPrice=int.Parse(BookPrice.Text),   25              BookDate=DateTime.Parse(BookDate.Text),   26              BookPeople=BookPeople.Text,   27              BookSay=BookSay.Text,   28              BookPhoto=UploadImage.FileName   29          };                                  //创建一个图书对象   30          try   31          {   32                 33              BookBookDataBase.add(bookinfo); //把上面信息插到数据库中   34              ShowMessage.Text = "上传成功";   35          }   36          catch   37          {   38              //如果发生异常,返回到管理员主页   39              Response.Redirect("~\Admin\AdminPage.aspx");   40          }     41      } 

第7~10行代码用来判断上传文件的大小和格式,大小不能多于2MB,文件类型必须是JPG或BMP。

第20~29行代码用来创建一个新的图书对象,并且为其赋值。

第33行代码调用BookBookDataBase类的add()方法添加数据到数据库。

在把信息插入到数据库时,调用了BookBookDataBase类的add()方法,此方法在会员注册模块中已经说明,这里不再介绍,BookDataBase类add()方法的代码如下所示。

代码位置:见光盘中本章源代码的BookShopMarket/App_Code/BookBookDataBase.cs文件。

01   public static void add(string add)   02   {   03       BookManagerDataClassesDataContext book =    04               new BookManagerDataClassesDataContext();   //数据上下文   05       book.BookInfos.InsertOnSubmit(bookinfo);      //插入数据   06       book.SubmitChanges();                     //提交更改   07   } 

图书编辑与删除模块(1)

图书编辑与删除是系统管理员的功能,管理员必须登录到后台后,才能操作该页面,该页面是AdminBookInfo.aspx。页面功能主要由一个GridView来实现,界面设计如图11.17所示。

该页面的功能全部由GridView控件方法实现,没有功能代码,部分HTML代码如下所示。

代码位置:见光盘中本章源代码的BookShopMarket/admin/AdminBookInfo.aspx文件。

01  <asp:GridView ID="GridView1" runat="server" AllowPaging="True"    02      AllowSorting="True" AutoGenerateColumns="False" CellPadding="4"    03      DataKeyNames="BookID" DataSourceID="SqlDataSource1"  ForeColor="#333333"    04      GridLines="None" Height="16px" PageSize="7" Width="791px">   05      <PagerSettings FirstPageText="首页" LastPageText="尾页"    06     Mode="NextPreviousFirstLast" NextPageText="下一页"  PreviousPageText="上一页" />   07      <FooterStyle BackColor="#507CD1" Font-Bold="True"  ForeColor="White" />   08      <RowStyle BackColor="#EFF3FB" />   09      <Columns>   10          <asp:CommandField ButtonType="Button" HeaderText="编辑"    11  ShowDeleteButton="True"    12               ShowEditButton="True">   13               <ControlStyle Width="50px" />   14           </asp:CommandField>   15           <asp:BoundField DataField="BookID" HeaderText=" 图书ID" ReadOnly="True"    16               SortExpression="BookID">   17               <ControlStyle Width="100px" />   18           </asp:BoundField>   19  …………………………………………………………………   20     </Columns>   21     <PagerStyle BackColor="#2461BF" ForeColor="White"  HorizontalAlign="Center" />   22     <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True"  ForeColor="#333333" />   23       <HeaderStyle BackColor="#507CD1" Font-Bold="True"  ForeColor="White" />   24       <EditRowStyle BackColor="#2461BF" />   25       <AlternatingRowStyle BackColor="White" />   26   </asp:GridView> 

到此,图书管理模块就实现了,用户可以浏览图书、查看图书详细信息,而管理员可以实现添加图书、删除图书、编辑图书等功能。

测试上述实现的页面,单击"浏览图书"菜单,浏览效果如图11.18所示。单击网格中"详细信息"列的"详细信息"按钮,会弹出该书的详细信息页

转载于:https://my.oschina.net/bigfool007139/blog/552035

Published by

风君子

独自遨游何稽首 揭天掀地慰生平