官术网_书友最值得收藏!

第1章 ASP.NET應用開發概覽

ASP.NET是下一代的活動服務頁面框架。ASP.NET是.NET框架中的固有部分,利用ASP.NET提供的服務,可以開發出新一代的Web應用。

本章將介紹下面內容:

● HTML、ASP應用和ASP.NET應用的比較

● ASP.NET應用開發前的準備工作

● 用Visual Studio.NET開發第一個ASP.NET應用

1.1 HTML、ASP和ASP.NET

在開始ASP.NET介紹之前,我們先簡單追述一下Web應用開發的歷史。最初的Web應用是基于靜態的HTML文本。利用一些預定義的標志,諸如FrontPage等工具就可以產生這樣的文本。HTML較好地解決了信息的顯示問題,但這些信息和控制顯示格式的標志在服務器端是編碼存儲的,這時應用程序的執行模式為:客戶請求某一個靜態HTML文本,服務器返回該文本。下面是一個典型的HTML文本的示例:

    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
    <meta http-equiv="Content-Language" content="zh-cn">
    <title>主頁</title>
    <meta name="GENERATOR" content="Microsoft FrontPage 4.0">
    <meta name="ProgId" content="FrontPage.Editor.Document">
    <meta name="Microsoft Theme" content="strtedge 011, default">
    <meta name="Microsoft Border" content="tl, default">
    </head>
    <body>
        <p><font size="4">歡迎光顧我的站點!</font></p>
        <p>主頁是讓到訪者了解本站點主旨的最佳場所。主頁向到訪者展示了您站點的風格。
</p>
        <p>  </p>
        <p>此網頁最近更新于<!--webbot bot="Timestamp" s-type="REGENERATED" s-format=
"%y年%m月%d日" -->。</p>
        <p        align="right"><a        ><img
src="images/frontpag.gif" border="0" width="88" height="44"></a></p>
    </body>
    </html>
上述HTML文本是用FrontPage工具創建的。文本的結構大致如下:
    <html>
    <head>
      <title>主頁</title>
    </head>
    <body>
    </body>
    </html>

標志<html></html>之間的是HTML文件的內容。<html>標志指示上述文件為一個HTML文檔,<title></title>標志指示文本的標題,<bod></body>之間的是HTML文件的正文。

提示

IE瀏覽器能夠解釋結構不完整的HTML文件,所以上述文件中去掉第一行的<html>和最后一行的</html>,也能在瀏覽器中正確地顯示。但建議讀者在設計HTML文件時,保證其結構的完整性,因為這樣可以增強代碼的可讀性。

觀察上述HTML文件,會發現每個標志都有若干屬性,例如,<font size="4">中的font標志有size屬性,表示size字體為4號字。格式信息正是通過標志和標志屬性設置的。在IE瀏覽器下,上述HTML文件的瀏覽效果如圖1-1所示。

圖1-1 瀏覽器下查看HTML

從瀏覽效果來看,HTML文件提供了比較豐富的界面元素。其外觀效果遠非文本效果可以比擬。但HTML的內容都是靜態準備好的,如果打算制作網頁反映股票信息,實現這樣的任務幾乎是不可能的,因為股票信息時刻在變,而為了反映這種變化,就必須時刻重新編寫HTML。為了解決動態信息的發布問題,活動服務頁面ASP誕生了。

活動服務頁面在HTML的基礎上引入了一些額外的標志,這些標志指示服務器在返回用戶請求的頁面之前進行進一步的處理。對客戶而言,它最終仍然會得到一個HTML文件,但該HTML文件是在服務器端動態生成的。對服務器而言,它要根據用戶的請求把活動頁面中的內容翻譯成HTML代碼,開發ASP應用工具有InterDev等。下面是一個ASP文件(demo.asp)的示例:

    <html>
    <head>
    <title>演示ASP</title>
    </head>
    <body>
        <% Response.Write("Hello," +Request("user")) %>
    </body>
    </html>

ASP文件跟HTML文件類似,也可以包括<html>等標志,但其中有一種特殊的<% %>標志,該標志指示期間的代碼要在服務器上執行,執行的結果將作為HTML文件的一部分返回給客戶。

其中Response對象是ASP內置的對象之一,表示對用戶的回應,Response.Write方法用以向客戶端寫入回應消息。Request對象是另一個內置對象,表示用戶的請求,例如通過該對象可以獲得用戶獲取的Form表單(如果通過Post方法提交)或者通過Get方法提交請求時的參數。代碼Request(“user”)表示獲得Get參數列表中的user參數。

下面的命令用以請求demo.asp,并指定user參數為“曉華”:

http://localhost/demo.asp?user=曉華

瀏覽器的顯示結果如圖1-2所示。

圖1-2 客戶端瀏覽器顯示請求響應

提示

響應返回的是HTML文檔,該文檔是由服務器動態構造的,其內容如下:

                      <html>
                      <head>
                      <title>演示ASP</title>
                      </head>
                      <body>
                          Hello,曉華
                      </body>
                      </html>

活動服務頁面能根據用戶的請求動態產生HTML文件,這是相對于靜態HTML應用的一大進步。它即充分利用了HTML強大的顯示功能,又充分表達了動態的信息,但ASP仍存在下面的不足:

● 界面和代碼沒有分開

ASP應用中的代碼包含在界面元素之間,這樣導致程序結構不清晰,增加了維護代碼的難度。

● 解釋性的腳本語言

ASP中所用到的編程語言是解釋性的腳本語言,如VBScript或JScript。每次服務器響應客戶的請求,都要調用某種語言引擎解釋腳本代碼,這樣降低了程序的執行效率,會影響對客戶的響應。

ASP.NET克服了ASP上述不足,利用Visual Studio.NET集成開發工具,開發人員甚至可以像設計Visual Basic程序那樣開發ASP.NET應用。

通過一種所謂的隱藏代碼技術,徹底實現了界面和代碼分離。下面是一個利用Visual Studio.NET產生的空白頁面示例,它由兩部分組成,界面和代碼,兩部分都被保存為一個獨立的文件。界面文件以.aspx為后綴,下面是其內容:

    [Visual Basic]
    <%@   Page   Language="vb"   AutoEventWireup="false"   Codebehind="WebForm1.aspx.vb"
Inherits="CH1.WebForm1"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <html>
        <head>
            <title>WebForm1</title>
            <meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.0">
            <meta name="CODE_LANGUAGE" content="Visual Basic 7.0">
            <meta name="vs_defaultClientScript" content="JavaScript">
            <meta                                                name="vs_targetSchema"
content="http://schemas.microsoft.com/intellisense/ie5">
        </head>
        <body MS_POSITIONING="GridLayout">
            <form id="Form1" method="post" runat="server">
            </form>
        </body>
    </html>
    [C#]
    <%@   Page   language="c#"   Codebehind="WebForm1.aspx.cs"   AutoEventWireup="false"
Inherits="CSCH1.WebForm1" %>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
    <HTML>
        <HEAD>
            <title>WebForm1</title>
            <meta name="GENERATOR" Content="Microsoft Visual Studio 7.0">
            <meta name="CODE_LANGUAGE" Content="C#">
            <meta name="vs_defaultClientScript" content="JavaScript">
            <meta                                                name="vs_targetSchema"
content="http://schemas.microsoft.com/intellisense/ie5">
        </HEAD>
        <body MS_POSITIONING="GridLayout">
            <form id="Form1" method="post" runat="server">
    98      </form>
        </body>
    </HTML>

首先注意.aspx文件的第一行,該行是一個頁面Page指令。Language指示頁面的編程語言,可以為C#、Visual Basic或任意一種.NET平臺下的編程語言。Codebihand屬性指示于界面元素關聯的代碼文件,Inherits屬性用以指示當前頁面的父類,AutoEventWireup屬性指示是否在頁面加載時,自動調用頁面中定義的Page_Init和Page_Load方法。

提示

一個.aspx文件實際上隱含定義一個Page派生類,它們直接或間接地從Page類派生。

我們再看看代碼隱藏文件,隱藏代碼定義了一個頁面類,它直接從System.Web.UI.Page派生。下面是其具體內容:

    [Visual Basic]
    Public Class WebForm1
        Inherits System.Web.UI.Page
    #Region"Web 窗體設計器生成的代碼 "
        '該調用是 Web 窗體設計器所必需的。
        <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        End Sub
        Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
MyBase.Init
            'CODEGEN: 此方法調用是 Web 窗體設計器所必需的。
            '不要使用代碼編輯器修改它。
            InitializeComponent()
        End Sub
    #End Region
        Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles MyBase.Load
            '在此處放置初始化頁的用戶代碼
        End Sub
    End Class
    [C#]
    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Web;
    using System.Web.SessionState;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.HtmlControls;
    namespace CSCH1
    {
                /// <summary>
                ///WebForm1 的摘要說明。
                /// </summary>
                public class WebForm1 : System.Web.UI.Page
                {
                    private void Page_Load(object sender, System.EventArgs e)
                    {
                        // 在此處放置用戶代碼以初始化頁面
                        //Request.Form
                    }
                    #region Web Form Designer generated code
                    override protected void OnInit(EventArgs e)
                    {
                        //
                        //CODEGEN:該調用是 ASP.NET Web 窗體設計器所必需的。
                        //
                        InitializeComponent();
                        base.OnInit(e);
                    }
                    /// <summary>
                    /// 設計器支持所需的方法 - 不要使用代碼編輯器修改
                    /// 此方法的內容。
                    /// </summary>
                    private void InitializeComponent()
                    {
                        this.Load += new System.EventHandler(this.Page_Load);
                    }
                    #endregion
                }
    }

如果讀者有Visual Basic.NET或C#的編程經驗,讀懂上述代碼應該沒有任何問題。上述代碼的主題是重載父類的OnInit方法和為Load事件添加處理代碼。通過下面的方法掛鉤事件:

[Visual Basic]

方法后跟Handlers關鍵字指示處理的事件,上例中的Page_Load方法即是一例。

提示

為了保證該方法正確的處理事件,必須保證該方法的簽名符合事件類型。在Visual Basic中,事件類型用委托來定義,例如:Web窗體的Load事件由下面的委托定義:

                      <Serializable>
                      Public Delegate Sub EventHandler( _
                        ByVal sender As Object, _
                        ByVal e As EventArgs _
                      )

所以Page_Load方法的的第一個參數必須為Object類型,第二個參數必須為EventArgs類型,并且該方法無返回值(為過程)。

    [C#]

把委托實例跟事件直接掛鉤。把本例中掛鉤事件的處理代碼重寫如下:

                        this.Load += new System.EventHandler(this.Page_Load);

代碼右邊生成一個EventHandler委托實例。this.Page_Load方法的簽名必須符合該委托。代碼左邊是要處理的事件(實際上是一個委托變量),運算符+=將左邊的委托實例和右邊的事件關聯起來。

提示

C#中this關鍵字表示對象自身,而Visual Basic中對應的關鍵字是Me。

從上面的例子可以看出,ASP.NET真正實現了將代碼和內容分開,已有的開發其他.NET應用的經驗可以直接用到ASP.NET應用開發中來。

需要指出,代碼隱藏文件并不是必須的,但利用它,可以將代碼和界面分離,因此是一種值得推薦的做法。另外一種替換的編程方式跟傳統的ASP應用開發類似,即把所有的代碼和一些HTML標志元素混在一起,并保存為一個單獨的文件(這樣的文件仍以.aspx文為后綴)。下面是單文件的窗體示例:

    [Visual Basic]
    <html>
    <!--
      演示ASP.NET
    !-->
    <Script language="vb" runat="server">
        public sub Page_Load(sender as Object,  e as EventArgs)
            if not IsPostBack then
              Message.Text="Hello,World!"
            end if
        end sub
    </Script>
    <body>
      <h4><font face="verdana">
        <asp:Label id="Message" runat="server"/>
      </font></h4>
    </body>
    </html>
    [C#]
    <html>
    <!--
      演示ASP.NET
    !-->
    <Script language="C#" runat="server">
        public void Page_Load(Object sender, EventArgs e) {
            if(!IsPostBack)
              Message.Text="Hello,World!" ;
        }
    </Script>
    <body>
      <h4><font face="verdana">
        <asp:Label id="Message" runat="server"/>
      </font></h4>
    </body>
    </html>

觀察上述文件,讀者會注意到單文件的ASP.NET窗體跟以前的ASP非常類似,但仔細觀察,你會發現Label控件前有asp命名控件限制,它表示Label為Web控件。ASP.NET頁面引擎會根據Label控件的相關屬性(例如Text屬性)將它轉化為適當的HTML代碼。runat="server"表示該控件在服務端運行,也就是說由服務器將其翻譯成HTML代碼。

除了上述兩點顯而易見的好處之外,ASP.NET還增加了許多具有吸引力的新功能,大部分功能都是.NET框架特性的一部分。下面是列表是這些新功能的不完全清單:

● 狀態視圖

ASP.NET提供狀態視圖在頁面的一個往返行程之間保存頁面的狀態。這就為開發人員提供了更多的選擇:他們就可以使用傳統的Session或Application對象保存狀態或數據庫在服務端保持頁面狀態,還可以狀態視圖在客戶端保存頁面狀態。狀態視圖通過隱藏域實現,因此除了往返行程的流量開銷外幾乎沒有其他限制。

● 一致的事件模型

處理Web窗體的事件就跟處理傳統的Window窗體的事件類似。經過ASP.NET框架的精心包裝,客戶端(遠程的瀏覽器)引發的事件可以透明傳遞到服務器,開發人員像處理本地事件一樣處理這些事件。

Web窗體中的事件處理也是基于委托的,委托相當于一個智能的函數指針。Web窗體的事件和本機窗口事件都表示為委托,并通過實例化委托將事件和事件處理代碼掛鉤。

● 基于XML文件的配置

可以為任何ASP.NET應用編寫一個XML文件格式的配置文件。利用配置文件,可以方便地設置ASP.NET應用的安全性、進程模型、語言編碼等。

開發人員可以隨時添加或修改配置設置,但同時,ASP.NET框架可以保證這種修改對運作著的Web應用程序和服務器產生最小的影響。

● 靈活地使用任何組件

因為ASP.NET應用最終被編譯成程序集,所以可以使用.NET框架類庫中的任何組件。而程序員要做的只是添加對程序集的引用和引入命名空間。

以往的COM組件也可以繼續使用,但在使用之前,它們通過.NET框架提供的互操作服務轉化為互操作程序集。

提示

在使用COM組件的背后,會發生很多事情,但集成開發工具使得程序員可以通過添加引用的方式使用任何COM對象。

利用集成開發環境,可以向ASP.NETWeb應用中添加各種編程元素,例如窗體、類、樣式等,如圖1-3所示。

圖1-3 集成開發環境下向Web應用中添加各種編程元素

● 支持Web服務

Web服務是基于一系列開發標準之上的可通過Web調用的功能。它把整個網絡變成一個可編程的計算平臺。ASP.NET支持創建基于XML的Web服務,并可以方便地使用Web服務。

1.2 開發之前

在開始我們的第一個ASP.NET應用之前,筆者還希望讀者了解下面一些問題。

第一個問題是:選用何種編程語言。跟前期的ASP不同,現在的ASP.NET應用可以用任何適用于.NET框架的編程語言。這樣讀者可選擇的范圍就擴大了,例如C#、Visual Basic、托管C++、JScript等。本質上,這些語言只有語法上的差異,因為它們最終都編譯成微軟中間代碼,所以,選用何種語言完全取決于個人的愛好。如果讀者是一位新手,建議使用C#語言,該語言是.NET平臺下的標準編程語言。而對以往的VBScript程序員可能會選擇Visual Basic,因為以往的經驗可以縮短他們了解Visual Basic.NET語言所花的時間。

如果用集成開發環境開發ASP.NET應用,那么整個項目中的所有隱藏代碼只能采取同一種編程語言。因為同一個項目中的所有這些文件要被同一個編譯器編譯成一個程序集。

提示

配置文件中用下面的代碼來規定默認的編程語言。

                      <compilation defaultLanguage="vb" />

另外,每個頁面也可以用Page指令設定編程語言。例如:

    <%@ Page Language="vb" "%>

如果不指定Page的Language屬性,那么將采用在配置文件中的默認設置。

提示

利用Page指令的Language屬性,可以單獨設置.aspx文件中的編程語言,同一個頁面只能設置成一種編程語言,如下面的代碼:

                      <%@ Page Language="cs" AutoEventWireup="false" %>
                      <HTML>
                      <body MS_POSITIONING="GridLayout">
                      <form id="Form1" method="post" runat="server">
                        <FONT face="宋體">
                          <asp:Label id="Label1" style="Z-INDEX: 101; LEFT: 172px; POSITION:
                  absolute;       TOP:       90px"       runat="server"       Width="256px"
                  Height="53px">Label</asp:Label></FONT>
                          </form>
                          <Script language=vb  runat="server"id="Script1">
                              Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
                  System.EventArgs) Handles MyBase.Load
                                    '在此處放置初始化頁的用戶代碼
                                    if not IsPostBack then
                                        Label1.Text="Hello"
                                    end if
                                  End Sub
                          </Script>
                      </body>
                      </HTML>

把上述文件保存到wwwroot目錄下的demo2.aspx文件下,然后啟動瀏覽器執行http://localhost/demo2.aspx,執行結果如圖1-4所示。

圖1-4 執行結果

為了解決這個問題,請把第一行中的代碼修改為:

    <%@ Page Language="vb" AutoEventWireup="false" %>

第二個問題是:選用何種編程工具。目前開發ASP.NET應用最好的工具就是Visual Studio.NET,它提供了Web窗體設計器,并支持隱藏代碼模型。利用它可以快速地開發出ASP.NET應用,而不用關心實現的細節,但目前Visual Studio.NET對單文件的.aspx撰寫提供的支持還非常有限。例如,不支持.aspx文件中的代碼高亮度顯示,沒有智能提示等。

第三個問題是:關于學習ASP.NET應用開發的最佳方法是什么。一般而言,按照本書安排的學習順序,讀者將能完全掌握ASP.NET應用開發技術,但為了獲得更好的學習效果,下面的一些建議可能是有益的。

● 熟悉選用的編程語言

本書的目的不是向大家介紹編程語言。如果讀者決定用Visual Basic或C#等語言開發ASP.NET應用,那么就要花一些時間來熟悉這些語言,主要是屬性常見的語句,例如類型定義、變量聲明、循環、分支等。讀者可以參考本社已出版的《Visual Basic.NET編程指南》一書和《C#編程指南》中的第2章,從中獲得有關編程語言本身的知識。

● 熟悉常見.NET框架類庫

.NET框架類庫為所有的.NET應用共有,ASP.NET應用也不例外。了解常用的.NET框架類,例如集合、數組、字符串等,無疑可以提高ASP.NET應用開發水平,并能更好地理解本書中所有的范例。

1.3 第一個ASP.NET應用

將要開發的ASP.NET應用所演示的技術在開發實際站點時經常用到——用戶登錄,并驗證用戶的身份,以確保只有特定的用戶才能訪問本應用(本例設定為只有曉華輸入正確的口令“1234”時,才可訪問本應用)。下面將詳細描述該應用的實現步驟。

1.3.1 第一步:新建一個ASP.NET應用

將其位置設定為:

    [Visual Basic]
    http://localhost/DEMO/CH1
    [C#]
    http://localhost/DEMOCS/CH1

執行結果如圖1-5所示。

圖1-5 新建ASP.NET應用

1.3.2 第二步:檢查生成的文件

請切換到項目資源視圖,以查看項目下的所有文件,如圖1-6所示。

圖1-6 生成的文件

各個文件的功能和內容分別介紹如下:

● 應用配置文件

web.config文件是ASP.NET應用配置文件,其內容如下,其中的注釋說明了每個配置元素的含義。本書后續章節將對每個配置元素做詳細講解。

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <system.web>
        <!--        動態調試編譯
                    設置  compilation debug="true" 以啟用  .aspx 調試。否則,將此值設置為
false,將提高此應用程序的運行時性能。
                    設置 compilation debug="true" 以將調試符號(.pdb 信息)
                    插入到編譯頁中。因為這將創建執行起來
                    較慢的大文件,所以應該只在調試時將該值設置為 true,而在其他的時候都設置為
false。有關更多信息,請參考有關調試 ASP.NET 文件的文檔。
        -->
        <!--
                    設置默認的編程語言,如果選擇建立Visual Basic語言的ASP.NET應用,則
                    defaultLanguage="vb"
        -->
        <compilation
                    defaultLanguage="c#"
                    debug="true"
        />
        <!--        自定義錯誤信息
                    設置 customError 模式值可以控制應向
                    用戶顯示用戶友好錯誤信息而不是錯誤詳細信息:
                    “On”始終顯示自定義(友好的)信息。
                    “Off”始終顯示詳細的 ASP.NET 錯誤信息。
                    “RemoteOnly”只對不在本地 Web 服務器上運行的
                    用戶顯示自定義(友好的)信息。出于安全目的,建議使用此設置,以便
                    不向遠程客戶端顯示應用程序的詳細信息。
        -->
        <customErrors
        mode="RemoteOnly"
        />
        <!--        身份驗證
                    此節設置應用程序的身份驗證策略。可能的模式是“Windows”、“Forms”、
                    “Passport”和“None”
        -->
        <authentication mode="Windows" />
        <!--        應用程序級別跟蹤記錄
                    應用程序級別跟蹤在應用程序內為每一頁啟用跟蹤日志輸出。
                    設置 trace enabled="true" 以啟用應用程序跟蹤記錄。如果 pageOutput="true",則
                    跟蹤信息將顯示在每一頁的底部。否則,可以通過從 Web 應用程序
                    和瀏覽 "trace.axd" 頁來查看應用程序跟蹤日志。
        -->
        <trace
            enabled="false"
            requestLimit="10"
            pageOutput="false"
            traceMode="SortByTime"
                    localOnly="true"
        />
        <!--        會話狀態設置
                    默認情況下,ASP.NET 使用Cookie 標識哪些請求屬于特定的會話。
                    如果 Cookie 不可用,則可以通過將會話標識符添加到 URL_來跟蹤會話。
                    若要禁用 Cookie,請設置 sessionState Cookieless="true"。
        -->
        <sessionState
                      mode="InProc"
                      stateConnectionString="tcpip=127.0.0.1:42424"
                      sqlConnectionString="data source=127.0.0.1;user id=sa;password="
                      Cookieless="false"
                      timeout="20"
        />
        <!--        全球化
                    此節設置應用程序的全球化設置。
        -->
        <globalization
                      requestEncoding="utf-8"
                      responseEncoding="utf-8"
          />
      </system.web>
    </configuration>

● 窗體文件

窗體文件包括以.aspx為后綴的界面文件和代碼隱藏文件。

● Global.asax文件

它定義一些跟ASP.NET應用相關的全局變量。其典型用途是定義ASP.NET應用啟動和結束、一個會話啟動和結束時的響應函數。下面的代碼清單可以非常清楚地看出Global.asax文件的作用。

    [Visual Basic]
    Imports System.Web
    Imports System.Web.SessionState
    Public Class Global
        Inherits System.Web.HTTPApplication
    #Region" 組件設計器生成的代碼 "
        Public Sub New()
            MyBase.New()
            '該調用是組件設計器所必需的。
            InitializeComponent()
            '在 InitializeComponent() 調用之后添加任何初始化
        End Sub
        '組件設計器所必需的
        Private components As System.ComponentModel.IContainer
        '注意:以下過程是組件設計器所必需的
        '可以使用組件設計器修改此過程。
        '不要使用代碼編輯器修改它。
        <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
            components = New System.ComponentModel.Container()
        End Sub
    #End Region
        Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
            ' 在應用程序啟動時激發
        End Sub
        Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
            ' 在會話啟動時激發
        End Sub
        Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
            ' 在每個請求開始時激發
        End Sub
        Sub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As EventArgs)
            ' 嘗試對使用進行身份驗證時激發
        End Sub
        Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
            ' 在發生錯誤時激發
        End Sub
        Sub Session_End(ByVal sender As Object, ByVal e As EventArgs)
            ' 在會話結束時激發
        End Sub
        Sub Application_End(ByVal sender As Object, ByVal e As EventArgs)
            ' 在應用程序結束時激發
        End Sub
    End Class
    [C#]
    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Web;
    using System.Web.SessionState;
    namespace CSCH1
    {
    /// <summary>
    ///Global 的摘要說明。
    /// </summary>
    public class Global : System.Web.HTTPApplication
    {
          public Global()
          {
              InitializeComponent();
          }
          protected void Application_Start(Object sender, EventArgs e)
          {
          }
          protected void Session_Start(Object sender, EventArgs e)
          {
          }
          protected void Application_BeginRequest(Object sender, EventArgs e)
          {
          }
          protected void Application_EndRequest(Object sender, EventArgs e)
          {
          }
          protected void Application_AuthenticateRequest(Object sender, EventArgs e)
          {
          }
          protected void Application_Error(Object sender, EventArgs e)
          {
          }
          protected void Session_End(Object sender, EventArgs e)
          {
          }
          protected void Application_End(Object sender, EventArgs e)
          {
          }
          #region Web Form Designer generated code
            ///<summary>
            /// 設計器支持所需的方法 - 不要使用代碼編輯器修改
            /// 此方法的內容。
            ///</summary>
          private void InitializeComponent()
          {
          }
          #endregion

在本書后續章節將詳細討論如何編寫上述清單中的各個方法。

● Styles.css文件

新Web應用程序項目的默認CSS樣式表,使用樣式的好處是省去了為每個標志設置屬性的麻煩。樣式的定義語法為:

元素名稱{樣式名:值;樣式名:值…}

下面是該文件中定義的若干樣式類:

    BODY
    {
        BACKGROUND-COLOR: white;
        FONT-FAMILY: Verdana, Helvetica, sans-serif;
        FONT-SIZE: .8em;
        FONT-WEIGHT: normal;
        LETTER-SPACING: normal;
        TEXT-TRANSFORM: none;
        WORD-SPACING: normal
    }
    H1, H2, H3, H4, H5, TH, THEAD, TFOOT
    {
        COLOR: #003366;
    }
    H1  {
        font-family:Verdana,Arial,Helvetica,sans-serif;
        font-size:  2em;
        font-weight:     700;
        font-style: normal;
        text-decoration: none;
    word-spacing:        normal;
        letter-spacing:  normal;
        text-transform:  none;
        }
    IMG     {
    margin-top: 5px;
    margin-left: 10px;
    margin-right: 10px;
        }

如果為.aspx文件指定了應用上述樣式,那么<body>標志內的HTML元素自動以下面的設置為默認值:

BACKGROUND-COLOR: white;

FONT-FAMILY: Verdana, Helvetica, sans-serif;

FONT-SIZE: .8em;

FONT-WEIGHT: normal;

LETTER-SPACING: normal;

TEXT-TRANSFORM: none;

WORD-SPACING: normal

但如果對<body>內的某個子元素重新設置了相應的屬性,例如“FONT-SIZE”,那么以新設置的屬性為主。為了具體說明樣式的作用效果和規則,我們在項目中添加一個名為democss.html的超文本文件,其內容如下:

    <html>
    <head>
          <link ref="stysheet" href="styles.css" type="text/css"></link>
    </head>
    <body>
          <h1>使用默認樣式的效果</h1>
          <h1 style="color:red;font-size:20pt">
          定制的樣式覆蓋了默認樣式中的文字顏色和大小
          </h1>
    </body>
    </html>

瀏覽器中的瀏覽效果如圖1-7所示。

圖1-7 使用樣式后的瀏覽效果

<body>內的第一個<h1>元素采用<body>和<h1>中的默認屬性,而第二個<h2>重寫了文字顏色和大小兩個屬性。

其中第三句代碼用以引用外部設定的樣式文件,還可以使用內嵌的樣式,這時樣式在<style>標志內定義,例如:

    <html>
        <head>
            <!--
            <link ref="stysheet" href="styles.css" type="text/css"></link>
            -->
            <style>
                BODY
                {
                    BACKGROUND-COLOR: white;
                    FONT-FAMILY: Verdana, Helvetica, sans-serif;
                    FONT-SIZE: .8em;
                    FONT-WEIGHT: normal;
                    LETTER-SPACING: normal;
                    TEXT-TRANSFORM: none;
                    WORD-SPACING: normal
                }
                H1, H2, H3, H4, H5, TH, THEAD, TFOOT
                {
                    COLOR: #003366;
                }
                H1
                {
                    font-family: Verdana, Arial, Helvetica, sans-serif;
                    font-size:  2em;
                    font-weight:     700;
                    font-style: normal;
                    text-decoration: none;
                    word-spacing:    normal;
                    letter-spacing:  normal;
                    text-transform:  none;
                }
        </style>
        </head>
        <body>
            <h1>使用默認樣式的效果</h1>
            <h1 style="color:red;font-size:20pt">
                定制的樣式覆蓋了默認樣式中的文字顏色和大小
            </h1>
        </body>
    </html>

● 程序集信息文件

隱藏代碼被編譯為一個程序集。程序集信息文件設置該程序集的若干信息,如版本、區域性、密鑰文件等。

    [Visual Basic]
    Imports System.Reflection
    Imports System.Runtime.InteropServices
    ' 程序集的常規信息通過下列
    ' 屬性集控制。更改這些屬性值可
    ' 修改與程序集關聯的信息。
    ' 檢查程序集的屬性值
    <Assembly: AssemblyTitle("")>
    <Assembly: AssemblyDeScription("")>
    <Assembly: AssemblyCompany("")>
    <Assembly: AssemblyProduct("")>
    <Assembly: AssemblyCopyright("")>
    <Assembly: AssemblyTrademark("")>
    <Assembly: CLSCompliant(True)>
    '如果該項目向 COM 公開,則下列 GUID 用于類型庫的 ID
    <Assembly: Guid("FF8D28EA-4294-4189-924A-FF51319DB917")>
    ' 程序集的版本信息由下列 4 個值組成:
    '
    '      主版本
    '      次版本
    '      內部版本號
    '      修訂號
    '
    ' 您可以指定所有這些值,也可以使用“內部版本號”和“修訂號”的默認值,方法是按
    ' 如下所示使用“*”:
    <Assembly: AssemblyVersion("1.0.*")>
    [C#]
    using System.Reflection;
    using System.Runtime.CompilerServices;
    //
    // 有關程序集的常規信息是通過下列
    //屬性集控制的。更改這些屬性值可修改與程序集
    //關聯的信息。
    //
    [assembly: AssemblyTitle("")]
    [assembly: AssemblyDeScription("")]
    [assembly: AssemblyConfiguration("")]
    [assembly: AssemblyCompany("")]
    [assembly: AssemblyProduct("")]
    [assembly: AssemblyCopyright("")]
    [assembly: AssemblyTrademark("")]
    [assembly: AssemblyCulture("")]
    //
    // 程序集的版本信息包含下列 4 個值:
    //
    //     主版本
    //     次版本
    //     內部版本號
    //     修訂號
    //
    // 您可以指定所有值,或使用“修訂號”和“內部版本號”的默認值,方法為按如下方式
    // 使用“*”:
    [assembly: AssemblyVersion("1.0.*")]
    //
    // 要對程序集進行簽名,必須指定要使用的密鑰。有關程序集簽名的更多信息,請參考
    //Microsoft.NET 框架文檔。
    //
    // 使用下面的屬性控制用于簽名的密鑰。
    //
    // 注意:
    //   (*) 如果未指定密鑰,則程序集不會被簽名。
    //   (*)KeyName 是指已經安裝在
    //       計算機上的加密服務提供程序 (CSP) 中的密鑰。KeyFile 是指包含
    //       密鑰的文件。
    //   (*) 如果 KeyFile 和 KeyName 值都已指定,則發生下面的處理:
    //       (1) 如果在 CSP 中可以找到 KeyName,則使用該密鑰。
    //       (2) 如果 KeyName 不存在而 KeyFile 存在,則
    //          KeyFile 中的密鑰安裝到 CSP 中并且使用該密鑰。
    //   (*) 要創建 KeyFile,可以使用 sn.exe(強名稱)實用工具。
    //       在指定 KeyFile 時,KeyFile 的位置應該
    //       相對于“項目輸出目錄”。項目輸出
    //       目錄的位置取決于您是在使用本地項目還是 Web 項目。
    //       對于本地項目,項目輸出目錄定義為
    //       <Project Directory>\obj\<Configuration>。例如,如果 KeyFile 位于該
    //       項目目錄中,應將 AssemblyKeyFile
    //       屬性指定為 [assembly:AssemblyKeyFile("..\\..\\mykey.snk")]
    //       對于 Web 項目,項目輸出目錄定義為
    //   %HOMEPATH%\VSWebCache\<Machine Name>\<Project Directory>\obj\<Configuration>。
    //   (*)“延遲簽名”是一個高級選項 - 有關它的更多信息,請參閱 Microsoft.NET 框架文檔。
    //
    [assembly: AssemblyDelaySign(false)]
    [assembly: AssemblyKeyFile("")]
    [assembly: AssemblyKeyName("")]

提示

上述文件主要是利用程序集層次的相關特性來設置程序集的屬性。特性是.NET框架提供的功能,用以對程序集作批注,例如可以用Assembly層次上的AssemblyVersion特性設置程序集版本:

              [Visual Basic]
              <Assembly: AssemblyVersion("1.0.*")>
                      [C#]
                      [assembly: AssemblyVersion("1.0.*")]

其中參數“1.0.*.*”是Assembly: AssemblyVersion特性的占位參數(也就是AssemblyVersion特性類構造函數中的一個參數)。

1.3.3 第三步:設計WebForm1窗體

把WebForm1窗體設計成一個如圖1-8所示的登錄界面。

圖1-8 設計好的登錄界面

圖1-8中各個標號所指的控件分別是:

①和②是Web窗體下的標簽控件,將①、②所指的標簽分別設置為“用戶名”和“口令”。

提示

Web控件的屬性不同于HTML元素的屬性。ASP.NET框架根據Web控件的屬性設置轉化為相應的HTML標志并設置其屬性。

③所指的為Web按鈕控件,將其Text屬性設置為“提交”。

④所指的為Web驗證匯總控件ValidationSummary,將其屬性保持為默認值。

⑤所指的是Web文本框TextBox控件,將其ID屬性設置為username。

提示

代碼中通過ID引用相應的屬性。

⑥所指的是HTML口令Password控件,將其ID屬性設置為pwd。然后選中該控件,單擊右鍵,單擊【作為服務器控件運行】按鈕,如圖1-9所示。

圖1-9 將HTML控件設置為作為服務器控件運行

說明

默認情況下,HTML控件作為客戶端控件運行,這樣服務端的代碼就不用通過其ID引用該控件。轉化為服務器端控件運行后,自動將其runat屬性設置為server。

⑦所指的是Web必須域RequiredFieldValidator驗證控件,將其Text屬性設置為“*”,將其ErrorMessage屬性設置為“用戶名不能為空”,將其ControlToValidate屬性設置為⑤所指的文本框控件的ID“username”。

提示

RequiredFieldValidator驗證控件驗證其ControlToValidate屬性所指的控件的值是否為空,如果為空,則將顯示其Text屬性所設的值,同時向驗證匯總控件ValidationSummary中添加一條由其ErrorMessage所指的錯誤消息。

⑧所指的也是Web必須域RequiredFieldValidator驗證控件,將其Text屬性設置為“*”,將其ErrorMessage屬性設置為“口令不能為空”,將其ControlToValidate屬性設置為⑥所指的文本框控件的ID“pwd”。

提示

在窗體的設計視圖下,圖1-9中所有的控件都可以從工具箱中拖放到窗體上。Web控件位于工具箱的“Web窗體”頁下,HTML控件則位于“HTML”頁下。

切換到HTML視圖下,可以查看Web窗體的代碼。本例中設計完成后的窗體具有下面清單所示的代碼:

    <%@ Page Language="cs" AutoEventWireup="false" Codebehind="WebForm1.aspx.vb" Inherits=
"CH1.WebForm1"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
                <HEAD>
                    <title>WebForm1</title>
                    <meta content="Microsoft Visual Studio.NET 7.0"name="GENERATOR">
                    <meta content="Visual Basic 7.0"name="CODE_LANGUAGE">
                    <meta content="JavaScript"name="vs_defaultClientScript">
                    <meta                            content="http://schemas.microsoft.com/intellisense/ie5"
name="vs_targetSchema">
                </HEAD>
                <body MS_POSITIONING="GridLayout">
                    <form id="Form1"method="post"runat="server">
                           <FONT face="宋體">
                            <asp:label id="Label1" style="Z-INDEX: 101; LEFT: 63px; POSITION:
absolute;   TOP:   41px"      runat="server"   Width="68px"            Height="24px">   用  戶  名
</asp:label><asp:requiredfieldvalidator  id="RequiredFieldValidator2"  style="Z-INDEX:  106;  LEFT:
382px;  POSITION:  absolute;  TOP:  96px"  runat="server"  ErrorMessage=" 口 令 不 能 為 空 "
ControlToValidate="pwd">*</asp:requiredfieldvalidator><asp:label id="Label2" style="Z-INDEX: 103;
LEFT: 65px; POSITION: absolute; TOP: 98px" runat="server" Width="68px" Height="24px">口令
</asp:label>
                            <asp:TextBox  id="username"  style="Z-INDEX:  102;        LEFT:         156px;
POSITION:absolute;TOP:36px"runat="server"Width="201px"Height="30px"></asp:TextBox>
                            <INPUT id="pwd" style="Z-INDEX: 104; LEFT: 152px; POSITION:
absolute;TOP:97px"type="password"name="Password1"runat="server">&nbsp;
                            <asp:RequiredFieldValidator id="RequiredFieldValidator1" style="Z-INDEX:
105; LEFT: 381px; POSITION: absolute; TOP: 39px" runat="server" ErrorMessage="用戶名不能為空"
ControlToValidate="username"Display="None">*</asp:RequiredFieldValidator>
                            <asp:ValidationSummary id="ValidationSummary1" style="Z-INDEX: 107;
        LEFT:   74px;   POSITION:   absolute;        TOP:   216px"   runat="server"   Width="228px"
        Height="36px"></asp:ValidationSummary>
                            <asp:Button id="Button1" style="Z-INDEX: 108; LEFT: 75px; POSITION:
absolute;   TOP:   149px"   runat="server"   Width="313px"   Height="32px"   Text="         提  交
"></asp:Button></FONT></form>
                </body>
    </HTML>

說明

上面清單只列出了編程語言為Visual Basic的窗體界面代碼。如果編程語言為C#,那么把設置特定語言的代碼中的“vb”替換為“cs”(或C#)即可。

1.3.4 第四步:編碼

雙擊WebForm1上的按鈕控件,ASP.NET自動在代碼隱藏文件中添加處理按鈕控件事件的代碼框架。

    [Visual Basic]
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles Button1.Click
        End Sub
    [C#]
                    private void Button1_Click(object sender, System.EventArgs e)
                    {
                    }說明

Web窗體設計器還自動在InitializeComponent方法中添加掛鉤事件的代碼:

                          this.Button1.Click += new System.EventHandler(this.Button1_Click);

然后在Button1_Click函數體內輸入下面的代碼:

    [Visual Basic]
          If username.Text = "曉華" And pwd.Value = "1234" Then
              FormsAuthentication.RedirectFromLoginPage("曉華", True)
          Else
              Response.Redirect("webform1.aspx")
          End If
    [C#]
            if(username.Text == "曉華" && pwd.Value == "1234" )
            {
                FormsAuthentication.RedirectFromLoginPage("曉華", true);
            }
          else
                Response.Redirect("webform1.aspx");

上述代碼判斷用戶是否是特定的用戶(用戶名為“曉華”,口令為“1234”),如果是則在客戶端生成標志用戶身份的Coockie,并定位到請求的網頁。否則將重定向到登錄界面。

為了順利編譯上述代碼,請引入FormsAuthentication所在的命名空間:

    [Visual Basic]
    Imports System.Web.Security
    [C#]
    using System.Web.Security;

說明

FormsAuthentication.RedirectFromLoginPage將已驗證身份的用戶重定向最初請求的URL。第一個參數表示用于Cookie身份驗證的用戶名稱,該名稱不必是Windows系統中的賬戶。第二個參數指示是應當發出持久性Cookie。

如果沒有指定請求的網頁(例如本例中通過點擊按鈕提交WebForm1窗體就是如此),那么FormsAuthentication.RedirectFromLoginPage將重定向到Default.aspx。正是這個原因,稍后我們要往項目中添加一個名為Default.aspx的窗體。

Response.Redirect方法將結果導到指定的網頁作為回應。Web窗體的Response屬性封裝了跟客戶端的響應相關的操作。

1.3.5 第五步:添加Default.aspx窗體

在資源管理器視圖下,選中ASP.NET應用項目,單擊右鍵,指向【添加Web窗體】,在彈出的子菜單中單擊【添加】按鈕,如圖1-10所示。

圖1-10 添加Web窗體的菜單

這時會彈出如圖1-11所示的“添加新項”對話框,將新建的窗體命名為Default.aspx,然后單擊【打開】按鈕。

圖1-11 “添加新項”對話框

這時添加的DefaultWeb窗體處于設計視圖下,按照如圖1-12所示設計其界面。

圖1-12 設計DefaultWeb窗體的界面

DefaultWeb窗體上包含了一個Web標簽控件和一個Web按鈕控件。

然后雙擊按鈕,添加處理按鈕單擊的代碼:

    [Visual Basic]
              Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
      Handles Button1.Click
                  FormsAuthentication.SignOut()
              End Sub
    [C#]
                    private void Button1_Click(object sender, System.EventArgs e)
                    {
                        FormsAuthentication.SignOut();
                    }

同樣在代碼隱藏文件的開頭引入FormsAuthentication所在的命名空間:

    [Visual Basic]
    Imports System.Web.Security
    [C#]
    using System.Web.Security;

FormsAuthentication.SignOut方法移除身份驗證憑據,調用后,客戶端表示用戶身份的持久性Cookie或會話Cookie將被刪除。

1.3.6 第六步:配置

雙擊web.config文件,找到下面的代碼:

    <authentication mode="Windows" />

用下面的代碼替換上面的代碼:

                  <authentication mode="Forms">
                    <forms loginURL="webform1.aspx" />
                  </authentication>

上述配置的含義是將驗證模式設置為窗體驗證模式,并設置登錄窗體為webform1.aspx。窗體驗證模式允許ASP.NETWeb應用通過窗體收集用戶的信息,并驗證用戶是否合法。

然后找到<authorization></authorization>元素,用下面的內容替換該元素及其內部的代碼:

              <authorization>
                  <deny users="?" />
              </authorization>

<deny users="?" />禁止沒有通過身份驗證的用戶訪問本Web應用程序。

1.3.7 第七步:測試

按【Ctrl+Shift+B】鍵編譯項目,然后按【Ctrl+F5】鍵運行程序。

說明

ASP.NET應用的隱藏代碼在執行前要被編譯成程序集,對ASP應用開發比較熟悉的讀者一定要注意這一點。直接按【Ctrl+F5】鍵,在執行之前要先編譯項目,然后執行項目的啟動頁面。

讀者可能會對集成開發工具具體的編譯過程感到好奇。在用戶發出編譯命令后,集成開發環境將調用特定編程語言的編譯器(Visual Basic為vbc.exe、C#為csc.exe)把項目中的隱藏代碼文件編譯成一個DLL形式的程序集(也叫類庫),生成后的程序集位于應用程序根目錄下的bin子目錄下。默認情況下,生成的程序集的名字跟項目名相同,但可以通過設置項目的相關屬性改變。改變的方法是在項目資源管理器視圖下單擊要設置的項目,單擊鼠標右鍵,單擊【屬性】按鈕,這時會彈出項目的“屬性”對話框。展開【通用屬性】節點,單擊【常規】子項,就出現如圖1-13所示(如果項目的編程語言為C#,則對應的畫面如圖1-14所示)的畫面,在該畫面下可以設置程序集的名稱。

圖1-13 設置項目輸出的程序集(Visual Basic)

圖1-14 設置項目輸出的程序集(C#)

在介紹ASP.NET Web應用部署的時候,我們將進一步介紹相關的編譯命令vbc.exe和csc.exe。現在大家只要知道,ASP.NET Web應用可以引用位于bin子目錄下的程序集就夠了。

可以引用某個程序集的含義是可以使用該程序集內實現的各種類型。程序集包含了它依賴的其他程序集的信息,以及其中定義的所有類型的信息,這些信息叫做程序集清單。為了使用某個程序集實現的組件,不用注冊該組件,直接將該程序集拷貝到bin子目錄下即可。

提示

bin子目下的程序集是ASP.NET Web應用的專用程序集。某些情況下,可能希望同一個程序集內的組件被多個ASP.NET Web應用(或其他類型的.NET應用,如本地窗體應用、控制臺應用等),那么可以將該組件轉化為強名程序集,并將之放入全局程序集緩存,這樣的程序集叫做共享程序集。.NET應用不必在私有的庫目錄(對ASP.NET Web應用而言,該目錄是BIN子目錄)保存共享程序集的拷貝。大家可能注意到,.NET框架類庫就是共享的程序集,這些程序集都有強名字并被預先放入了全局程序集緩存,所以ASP.NET Web應用可以自由引用.NET框架庫,而不會在bin子目錄下保存它們的副本。

程序集是.NET應用的核心,多花些時間深入了解程序集是值得的。本書后面介紹ASP.NET Web應用的部署的時候將會對程序集做進一步介紹。

隱藏代碼在運行之前就編譯成了bin子目錄下的程序集,那么Web窗體的界面元素文件(后綴為.aspx的文件)又如何呢?答案是在第一次請求.aspx文件時,該文件被動態編譯成程序集,該程序集實現一個從代碼隱藏類實現的Web窗體的派生類。我們在回頭看看webform1.aspx文件的第一行代碼:

    [Visual Basic]
    <%@   Page   Language="vb"   AutoEventWireup="false"   Codebehind="WebForm1.aspx.vb"
Inherits="CH1.WebForm1"%>
    [C#]
    <%@   Page   Language="cs"   AutoEventWireup="false"   Codebehind="WebForm1.aspx.cs"
Inherits="CH1.WebForm1"%>

其中Inherits屬性就指定了本頁面的父類,而其中的Codebehind只是用來把界面元素和隱藏代碼關聯起來,只在編輯代碼時候起到同步界面視圖和隱藏代碼的作用,對最后的.aspx文件及隱藏代碼文件的編譯并沒有影響。讀者可以試著刪除代碼中的Codebehind屬性設置,應該會發現代碼運行后沒有任何不同。

上面討論的內容是為了幫助讀者了解一些內幕信息。這樣對程序設計過程中不致于被出現的一些意外所惑。順便提一下,程序集中的代碼是一種所謂的微軟中間代碼(MSIL),不能直接在CPUT上執行,但.NET運行時,提供的即時編譯JIT技術能夠動態地把MSIL轉化為可被特定的CPU(例如X86芯片)執行的二進制代碼。轉化后的二進制代碼將被緩存,并可以在響應后續請求時直接在CPU上運行。

上面的討論實質上揭示了一個ASP.NET應用被編譯直至運行過程中涉及的一些底層細節。本書后續章節將會對這些內容做進一步的探討。下面回到測試的主題上來,運行項目后,將出現如圖1-15所示的登錄畫面。

圖1-15 登錄畫面

先實驗一下必須域驗證的效果。保持用戶名和口令為空,直接單擊【提交】按鈕,將出現如圖1-16所示的畫面。因為必須域驗證控件檢查到輸入用戶名和口令中輸入為空,從而顯示提示文本(由其Text屬性設定),并且錯誤信息(由驗證控件的ErrorMessage屬性設置)出現在驗證匯總控件中。

圖1-16 驗證未通過

從執行結果可以看出,通過使用相關的驗證控件,可以保證提交到服務器上的數據為有效數據。如果輸入了無效數據,驗證將不能通過,這時原來提交的請求頁面,以及添加了若干驗證信息的頁面被返回。

在用戶名文本框中輸入“曉華”,再單擊【提交】按鈕,執行結果如圖1-17所示。從執行結果可以看出,驗證提示信息變化了,因為只有口令為空,而輸入的用戶名則在往返行程中保持不變。

圖1-17 保持口令為空時的驗證結果

在口令框中輸入口令“1234”后,單擊【提交】按鈕,將彈出如圖1-18所示的畫面。彈出的“自動完成”對話框提示是否根據用戶名文本框自動設置口令框中的口令,單擊【否】繼續。

圖1-18 提示是否自動完成

這時將返回默認頁面default.aspx的執行結果,如圖1-19所示。服務器端將在客戶端設置標志用戶“曉華”身份的Coockie。

圖1-19 成功登錄后的畫面

在圖1-19中單擊【Sign Out】按鈕,將在客戶端取消標志用戶“曉華”身份的Coockie。如果試圖不經過登錄界面直接請求default.aspx頁面,則ASP.NET框架首先驗證用戶的身份;如果客戶端標志用戶的Coockie,則把用戶當成未經身份驗證的匿名用戶,而本示例通過配置文件中授權設置<deny users="?" />拒絕匿名用戶的訪問請求,并自動重定向到身份驗證配置部分的Forms元素的loginURL屬性設定的登錄頁面。

提示

如果客戶端已經有了標志用戶曉華身份的Coockie,則可以直接獲得請求的頁面。

從上面的測試可以看出,本示例中設計的登錄界面的確保證了只有特定的用戶才能成功登錄,任何不經身份驗證而直接獲取本應用的請求都將失敗。

注意

身份驗證本身不能提供任何安全措施,安全的實施是通過對用戶的授權實現的。本示例中,如果允許所有的用戶都能登錄,也就是在web.config文件的授權部分添加<deny users="?" />,那么任何用戶都可以直接請求default.aspx。當然對webform1.aspx頁面而言,仍然只有當用戶名為“曉華”,口令為“1234”時,才會進入default.aspx頁面,但這種設防已經毫無意義!

提示

可以在default.aspx頁面內顯示當前登錄的用戶名,這時請打開default.aspx的隱藏代碼文件,并把Page_Load方法的代碼修改為:

                      [Visual Basic]
                          Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
                  System.EventArgs) Handles MyBase.Load
                              '在此處放置初始化頁的用戶代碼
                              If Not IsPostBack Then
                                  Label1.Text = User.Identity.Name & ",歡迎光臨"
                              End If
                          End Sub
                      [C#]
                                private void Page_Load(object sender, System.EventArgs e)
                                {
                                    // 在此處放置用戶代碼以初始化頁面
                                    Label1.Text = User.Identity.Name + ",歡迎光臨";
                          }

其中,User.Identity獲得當前用戶的標志。

1.3.8 第八步:功能完善

上面示例僅允許一個特定的用戶登錄,假設隨著程序的運行,需要允許更多的用戶例如小楊等人也可以登錄,那么就必須修改webform1.aspx的提交按鈕的處理代碼:

    [Visual Basic]
    If (username.Text = "曉華" And pwd.Value = "1234") Or (username.Text = "小楊" And pwd.Value =
"5157")  Then
    ‘…
    end if
    [C#]
    if((username.Text=="曉華"&&pwd.Value=="1234")||        (username.Text=="小楊"&&
pwd.Value == "5157" ))
    {
    }

隨著允許訪問的用戶名單的增加,上述代碼還會進一步增加,因此必須考慮另外一種更一般的方法。答案在于FormsAuthentication.Authenticate方法,它接收兩個分別表示用戶名和口令的參數,并根據配置文件中的身份驗證節中的配置信息驗證用戶的身份。為了支持“曉華”和“小楊”兩個用戶登錄,可以把web.config中配置身份驗證的部分修改為如下所示:

                  <authentication mode="Forms">
                    <forms loginURL="webform1.aspx">
                      <credentials passwordFormat = "Clear" >
                          <user name="小楊" password="5157"/>
                          <user name="曉華" password="1234"/>
                      </credentials>
                      </forms>
                  </authentication>

credentials元素的passwordFormat屬性設置為Clear,表示用戶的密碼用明文表示,因此用戶“小楊”的密碼就是“5157”,用戶“曉華”的密碼就是“1234”。

注意

passwordFormat屬性區分大小寫,不要把Clear誤寫為clear。

然后把webform1的提交按鈕的單擊事件處理代碼修改為如下所示:

    [Visual Basic]
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles Button1.Click
            If FormsAuthentication.Authenticate(username.Text, pwd.Value) Then
                FormsAuthentication.RedirectFromLoginPage(username.Text, True)
            Else
                Response.Redirect("webform1.aspx")
            End If
        End Sub
    [C#]
              private void Button1_Click(object sender, System.EventArgs e)
              {
                  if( FormsAuthentication.Authenticate(username.Text, pwd.Value))
                  {
                      FormsAuthentication.RedirectFromLoginPage(username.Text, true);
                  }
                else
                      Response.Redirect("webform1.aspx");
              }

重新編譯項目后啟動,然后在輸入用戶名“小楊”及口令“5157”,如圖1-20所示。

圖1-20 測試改進后的應用

在圖1-19所示的畫面中單擊【提交】按鈕,將出現如圖1-21所示的畫面。

圖1-21 小楊登錄后的界面

還可以通過配置文件修改授權,例如下面的授權配置拒絕用戶“曉華”和匿名用戶登錄:

        <authorization>
            <deny users="?,曉華"/>
                <allow users="*" />
        </authorization>

從本例可以看出,利用配置文件可以不用修改源代碼而改變ASP.NET Web應用的行為。對開發人員而言,靈活地使用配置文件,也是一項重要的技能。

注意

在修改源代碼后,請不要忘了先編譯再執行!

1.3.9 第九步:部署

因為ASP.NET中所使用的組件都包含在程序集中,而程序集通過一個詳細的清單實現了自描述,所以ASP.NET應用部署過程中不用考慮組件(例如傳統的COM組件)的注冊問題,可以通過復制策略把ASP.NET應用從開發服務器部署到最終的發行服務器上。集成開發環境提供了兩種方法實現ASP.NET應用的部署:拷貝項目和使用安裝項目。

假設我們要把開發服務器localhost上的ASP.NET應用CH1部署到發行服務器diana的CH1RELEASE虛目錄下,則可以:

1.利用項目復制功能步驟

(1)選中要復制的ASP.NET項目。

(2)選擇【項目】菜單,繼續選擇【復制項目】子菜單。

(3)這時將彈出“復制項目”對話框,如圖1-22所示。設置好目標項目文件夾的名稱和相關的復制選項,然后單擊【確定】按鈕。

圖1-22 “復制項目”對話框

(4)這時會出現如圖1-23所示的對話框指示復制進度。當項目復制完畢后,該對話框自動關閉。

圖1-23 復制進度進度圖

(5)復制結束后,通過瀏覽器訪問發行服務器上的ASP.NET應用。

在瀏覽器的地址欄中發行服務器上的應用地址,如圖1-24所示,將會出現開發服務器上類似的界面。

圖1-24 訪問部署到發行服務器上的ASP.NET應用

2.用Web安裝項目部署步驟

(1)在解決方案資源視圖下,右鍵單擊解決方案,鼠標指向【新建項目】,然后在彈出的子菜單中單擊【添加】按鈕,如圖1-25所示。

圖1-25 往解決方案中添加項目

(2)這時會彈出“添加新項目”對話框,如圖1-26所示。選擇左邊的“項目類型”列表框中的【安裝和部署項目】,在右邊的“模板”列表框中單擊【Web安裝項目】,在設置安裝項目的名稱和保存該項目的目錄后,單擊【確定】按鈕。

圖1-26 “添加新項目”對話框

(3)解決方案資源視圖下的項目列表框中會出現新建的安裝項目,右鍵單擊該項目,鼠標引向【添加】后單擊【項目輸出】。

(4)這時會彈出如圖1-27所示的“添加項目輸出組”對話框。選擇項目“CH1”,在列表框中選中“主輸出”和“內容文件”,單擊【確定】按鈕,關閉對話框。

圖1-27 “添加項目輸出組”對話框

提示

對于CH1項目,只用發行編譯后的程序集(項目主輸出)和所有的*.aspx文件(內容文件)。至于代碼隱藏文件(源文件)和資源和調試符號則不用部署到目標服務器上。

(5)右鍵單擊安裝項目,指向【視圖】,單擊【自定義操作】按鈕。

(6)選中【自定義操作】節點,單擊右鍵,單擊【添加自定義操作】按鈕。

(7)按照如圖1-28所示進行選擇,設置好后,單擊【確定】按鈕,關閉對話框。

圖1-28 選擇項目中的項

(8)右鍵單擊安裝項目,單擊【生成】按鈕,這時輸出窗口將輸入如圖1-29所示的信息。

圖1-29 編譯安裝項目時的輸出窗口

(9)查看安裝項目的調試(或發行)目錄生成的安裝文件,如圖1-30所示。

圖1-30 安裝項目的生成文件

(10)把安裝項目生成的安裝文件復制到ASP.NET應用發行服務器Diana。

(11)在發行服務器Diana上運行安裝文件。

啟動安裝后,會依次出現如圖1-31至圖1-35所示的畫面。

圖1-31 歡迎畫面

圖1-35 安裝結束

圖1-32 設置安裝地址

圖1-33 確認安裝

圖1-34 正在安裝

(12)在瀏覽器上輸入http://diana/WebSetupCH1/webform1.aspx,測試發行服務器上的ASP.NET應用。

提示

通過控制面板下的“添加/刪除程序”工具刪除安裝的ASP.NET應用,如圖1-36所示。

圖1-36 通過“添加/刪除程序”工具刪除安裝的ASP.NET應用

從整個安裝實例來看,ASP.NET應用的部署是比較容易的。如果涉及到數據庫訪問,則部署ASP.NET應用時,還要考慮數據庫的部署。

1.4 小結

本章簡單介紹了直到ASP.NET誕生,Web應用開發的歷史。本章的重點是通過開發一個基于窗體驗證的登錄Web窗體,介紹了ASP.NET應用開發的全貌。本章所涉及到的大量技術,在本書后面都有詳細介紹。

主站蜘蛛池模板: 隆化县| 德保县| 驻马店市| 寻甸| 施秉县| 白玉县| 吉安县| 阿克苏市| 大田县| 印江| 岢岚县| 永康市| 晴隆县| 枣庄市| 正阳县| 肥乡县| 海宁市| 开化县| 鄂伦春自治旗| 土默特左旗| 绥芬河市| 阜南县| 台安县| 黑龙江省| 台北市| 柞水县| 河津市| 芷江| 金塔县| 科技| 普陀区| 沐川县| 永吉县| 中卫市| 新巴尔虎右旗| 侯马市| 洪湖市| 乌审旗| 罗田县| 从江县| 庆城县|