在這篇文章中,將討論一下表示層的實現方法。
表示層是一個系統的 “門臉”,不論你的系統設計的多麼優秀,代碼多麼漂亮,系統的可 擴展性多麼高,但是最終用戶接觸到的大多是表示層的東西。所以,表示層的優 劣對於用戶最終對系統的評價至關重要。一般來說,表示層的優劣有一下兩個評 價指標:
1.美觀。即外觀設計漂亮,能給人美的感覺。
2.易用。 即具有良好的用戶體驗,用戶用起來舒服、順手。
表示層的設計牽扯到很 多非技術性問題,如美工、用戶心理學等問題,但是在這篇文章中,將不過多涉 及這些問題,一來是我的水平有限,二來是這些內容和本系列文章的關系不是很 密切。這裡將主要從技術實現的角度討論表示層的設計。
一般來說,表示 層的職責有以下兩點:
1.接受用戶的輸入。
2.向用戶呈現信息。
總體來說,就是與用戶的交互。
而表示層的實現技術也是多種多 樣的,如C/S架構下一般使用Windows窗體技術(甚至是命令行窗體),而B/S架構 下主要是使用Web頁的形式實現。而且在Ajax技術出現以後,又分出了同步模型的 B/S架構實現和異步模型的B/S架構實現。在這篇文章中,將主要討論同步模型下 B/S架構的表示層實現,而基於Ajax技術的異步模型將在下一篇中討論。
另外,提到表示層的實現,大家一定會想到MVC這個詞,不錯MVC已經成為表示層 設計的經典模式。J2EE平台上的Struts和最近微軟推出的ASP.NET MVC都是實現 MVC模式的框架。但是為了突出本系列文章的的重點——分層,而且也 為了照顧初學者。這裡將不設計MVC模式,而是用傳統的ASP.NET編程模型來完成 表示層的設計。
一下的所有討論,將圍繞“管理員登錄”這個 用例展開。下面我們來逐步實現管理員登錄的表示層設計。
1.設計界面
為實現這個功能,我們首先要有一個Web頁面。設計好的頁面如下圖所示 :(時間所迫,制作過於簡陋,各位見諒)
首先,我們要在“Web”工程下建立一個新的aspx文件,叫做 Login.aspx,這就是管理員登錄的Web頁面。完成後這個文件的代碼如下:
Login.aspx:
1<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Login.aspx.cs" Inherits="Login" %>
2
3<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1- transitional.dtd">
4
5<html xmlns="http://www.w3.org/1999/xhtml" >
6<head runat="server">
7 <title>NGuestBook-管理員登錄</title>
8 <link href="Styles/Common.css" rel="stylesheet" type="text/css" />
9 <link href="Styles/Login.aspx.css" rel="stylesheet" type="text/css" />
10</head>
11<body>
12 <form id="form1" runat="server">
13 <div id="container">
14 <div id="box">
15 <h1>NGuestBook管理員登 錄</h1>
16 <table id="forms" cellpadding="0" cellspacing="0">
17 <tr>
18 <td>用戶名: </td>
19 <td><asp:TextBox ID="Name" TextMode="SingleLine" runat="server"></asp:TextBox></td>
20 </tr>
21 <tr>
22 <td>密 碼: </td>
23 <td><asp:TextBox ID="Password" TextMode="Password" runat="server"></asp:TextBox></td>
24 </tr>
25 </table>
26 <div id="buttons">
27 <asp:Button ID="Submit" runat="server" Text="登錄" OnClick="Submit_Click" />
28 <asp:Button ID="Cancel" runat="server" Text="重填" OnClick="Cancel_Click" />
29 </div>
30 </div>
31 </div>
32 </form>
33</body>
34</html>
35
可以看到,在這個文件裡,主要是各種頁面元素的結構,但 是他們的外觀卻沒有定義。我們注意到,在這個文件的開頭引用了兩個外部的CSS 文件,那裡才是定義外觀的地方。其中Common.css是全局通用外觀,而 Login.aspx.css是這個頁面的專用外觀。
這是我提倡的一種表示層設計的 方法。即將結構與表現分離,其思想很類似目前的“標准化網頁設計 ”(有人稱之為DIV+CSS布局),其核心思想是一樣的,只不過我這裡沒那 麼嚴格,並且適當的地方可以考慮使用Table布局。我的一般方法是這樣的:aspx 文件中只存儲頁面結構,不存在任何與外觀有關的代碼。在工程中可以有一個專 門的文件夾放置CSS文件,除了通用樣式外,每個文件有與自己同名的CSS文件, 如Login.asxp配套的就是Login.aspx.css,這樣,就可以使得結構與表現相分離 。
在我的工程中,有一個Styles文件夾,專門存放CSS文件。下面把 Common.css和Login.aspx.css文件的代碼附上:
Common.css
1*{}{
2 margin:0;
3 padding:0;
4}
5
6h1,h2,h3,h4,h5,h6{}{
7 font- size:12px;
8}
9
10#container{}{
11 width:100%;
12}
Login.aspx.css
1#box{} {
2 width:40%;
3 margin:200px auto auto auto;
4 border:3px solid #036;
5}
6
7h1{}{
8 margin:1px;
9 padding:5px 0;
10 font-size:14px;
11 color:#FFF;
12 background:#036;
13 text- align:center;
14}
15
16#forms{}{
17 margin:20px auto;
18 font-size:12px;
19 color:#036;
20}
21
22#forms input{}{
23 margin:10px;
24 border:0;
25 border-bottom:1px solid #036;
26 width:160px;
27}
28
29#buttons{}{
30 margin- bottom:20px;
31 text-align:center;
32}
33
34#buttons input{}{
35 margin:0 10px;
36}
2.表示邏輯
頁面搞定了,但是要想頁面發揮作用,還要有 表示邏輯才行。我們登錄的表示邏輯是這樣的:首先根據用戶輸入的用戶名和密 碼,檢查是否是系統管理員(系統管理員只有一個,其用戶名和密碼定義在 Web.config中,系統管理員可以添加、修改和刪除普通管理員),如果是,則在 Session中存儲相應信息,並以系統管理員的身份登錄後台管理頁面。如果不是, 則檢查是否是普通管理員,如果是,則將此管理員的信息存儲到Session中,以普 通管理員身份返回主頁。如果不是,則顯示登錄失敗的提示。
當然,這裡 身份的控制還需要在後台頁面和主頁那邊有Session檢查才能完成。例如,當請求 後台頁時,要檢查Session中相應信息是否完整,如果不完整則是非法請求,不允 許訪問此頁面。而在主頁也是,如果Session相應項中有普通管理員的信息,表明 當前用戶是管理員,要顯示修改、回復、刪除等按鈕,否則是游客,則不顯示這 些按鈕。
我們首先要配置系統管理員的用戶名和密碼,打開Web.config, 在<appSettings>節點下添加如下項:
<add key="AdministartorName" value="admin"/>
<add key="AdministartorPassword" value="123456"/>
這裡很明顯,前一個是系統管理 員的用戶名,這裡設為“admin”,而後一項為密碼,設為 “123456”
由於一般情況下Web.config是不允許請求的,所以 這裡不用擔心密碼洩露。
普通管理員登錄的業務已經在業務邏輯層實現了 ,表示層可以直接調用。而系統管理員的判斷、Session的操作檢查及頁面跳轉都 放在表示層裡。而這一套邏輯,都放在“Submit”這個button控件的 Click事件中,具體代碼參考如下:
Login.aspx.cs:
1using System;
2using System.Data;
3using System.Configuration;
4using System.Collections;
5using System.Web;
6using System.Web.Security;
7using System.Web.UI;
8using System.Web.UI.WebControls;
9using System.Web.UI.WebControls.WebParts;
10using System.Web.UI.HtmlControls;
11using NGuestBook.Entity;
12using NGuestBook.IBLL;
13using NGuestBook.Factory;
14
15public partial class Login : System.Web.UI.Page
16{
17 protected void Page_Load(object sender, EventArgs e)
18 {
19
20 }
21 protected void Cancel_Click(object sender, EventArgs e)
22 {
23 this.Name.Text = "";
24 this.Password.Text = "";
25 }
26 protected void Submit_Click(object sender, EventArgs e)
27 {
28 string administratorName = ConfigurationManager.AppSettings["AdministartorName"];
29 string administratorPassword = ConfigurationManager.AppSettings["AdministartorPassword"];
30
31 //如果是系統管理員,則以系統管理員身份登錄到後台
32 if (this.Name.Text == administratorName && this.Password.Text == administratorPassword)
33 {
34 Session["Administrator"] = "Administrator";
35 Response.Redirect ("~/Manage.aspx");
36 return;
37 }
38
39 //判斷是否為普通管理員,如果是,則以管理員身份 登錄到留言本,否則顯示登錄失敗
40 AdminInfo admin = BLLFactory.CreateAdminBLL().Login(this.Name.Text, this.Password.Text);
41 if (admin != null)
42 {
43 Session["Admin"] = admin;
44 Response.Redirect("~/Default.aspx");
45 }
46 else
47 {
48 Response.Redirect("~/Error.aspx?errMsg=登錄失敗");
49 }
50 }
51}