Asp.net 的工做原理



轉:http://www.cnblogs.com/linjiancun/archive/2010/09/14/1825662.html

1.1.1          Asp.net 的工做原理

Aspx頁面的的通常處理過程以下圖所示:html

 

1.1.2          Asp.net 的頁面處理過程:

下面經過一個更加詳細的圖形來描述aspnet_isapi.dll處理頁面的一個流程:web

 

 

請求的處理過程是基於管道模型的。編程

咱們經過下圖來理解什麼管道模型:c#

其實就是能夠有多個HttpModule,可是隻能有一個HttpHandlerapi

1.1.3          Isapi篩選器

Iis默認不會處理動態頁面,只能處理html頁面,因而就須要對iis進行擴展,這些擴展要註冊到iis中,和特定的後綴名綁定,這樣之後每當iis遇到了某個後綴名,就把他發送給響應的擴展來處理,這些篩選器處理完以後,把結果返回給iisiis就把這個結果返回給客戶。好比對於asp,就要用asp_isapi.dll來處理,對於asp.net就要使用aspnet_isapi.dll來處理。擴展的方法有兩種:ISAPI Filter ISAPI Extension兩種。其中HttpModule就是篩選器;HttpHandler就是Http Extensionapp

1.1.4          HttpModule

Httpmodule實現了過濾器也就是篩選器的功能;HttpModule 實現了System.Web.IHttpModule的接口。asp.net

(1)       實現步驟編程語言

l         編寫一個類,實現IHttpModule接口;ide

l         實現init方法,註冊須要的方法;函數

l         實現註冊的方法;

l         實現dispose方法,這是在爲類實現一些清除工做的時候才實現的,一般狀況下能夠什麼都不做,爲空;

l         web.config是註冊該HttpModule類。

2)能夠被處理的事件

其實所謂添加HttpModule,就是給HttpApplication的一些列時間添加事件處理函數,在HttpModule類中給須要添加處理函數的事件添加處理函數便可。

HttpApplication主要有如下一些事件:

l         BeginRequest

l         AuthenticateRequest

l         AuthorizeRequest

l         ResolveRequestCache

l         AcquireRequestState

l         PreRequestHandlerExecute

l         PostRequestHandlerExecute

l         ReleaseRequestState

l         UpdateRequestCache

l         EndRequest

全部的這些事件都可以被從新定義,可是不是override;你要明白,也就是增長了一層Module,原來的HttpModule仍然存在。這就是HttpModule的基本工做原理。

3)一個例子

下面給出一個如何自定義HttpModule的例子。

該HttpModule名爲:MyHttpModule其中有一個AcquireRequestState事件的處理函數,整個類的定義以下:

using System;

using System.Data;

using System.Configuration;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

 

/// <summary>

/// Summary description for MyHttpModule

/// </summary>

public class MyHttpModule: System.Web.IHttpModule

{

    public MyHttpModule()

    {

       //

       // TODO: Add constructor logic here

       //

    }

    public void Init(HttpApplication httpA)

 {

    // Application 對象註冊事件處理程序

     httpA.AuthenticateRequest += new EventHandler(this.AuthenticateRequest);

 }

 

 public void Dispose()

 {

  

 }

 

 private void AuthenticateRequest(object r_objSender,EventArgs r_objEventArgs)

    {

       HttpApplication httpA = (HttpApplication)r_objSender;

       httpA.Context.Response.Write("in MyHttpModule AuthenticateRequest Event Handler");

 

    }

}

 

把該類放在solution下的叫作App_Code文件夾下,而後在web.config中添加以下代碼:

<system.web>

    <httpModules>

       <add name="Test1" type="MyHttpModule,App_Code"/>

    </httpModules>

   

</system.web>

 

而後給solution添加一個空白頁面,運行該頁面,獲得的結果以下:
 

4)這些事件的執行順序如何?

若是想要弄清HttpApplication的全部這些事件的執行順序如何,那麼經過下面的這個例子就明白了。

咱們對上面的例子做一個簡單的修改,代碼以下:

using System;

using System.Data;

using System.Configuration;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

 

/// <summary>

/// Summary description for MyHttpModuleMultiEvent

/// </summary>

public class MyHttpModuleMultiEvent : System.Web.IHttpModule

{

    public MyHttpModuleMultiEvent()

    {

       //

       // TODO: Add constructor logic here

       //

    }

    public void Init(HttpApplication httpA)

    {

       // Application 對象註冊事件處理程序

       httpA.BeginRequest += new EventHandler(this.BeginRequest);

       httpA.AuthenticateRequest += new EventHandler(this.AuthenticateRequest);

       httpA.AuthorizeRequest += new EventHandler(this.AuthorizeRequest);

       httpA.ResolveRequestCache += new EventHandler(this.ResolveRequestCache);

       httpA.AcquireRequestState += new EventHandler(this.AcquireRequestState);

       httpA.PreRequestHandlerExecute += new EventHandler(this.PreRequestHandlerExecute);

       httpA.PostRequestHandlerExecute += new EventHandler(this.PostRequestHandlerExecute);

       httpA.ReleaseRequestState += new EventHandler(this.ReleaseRequestState);

       httpA.UpdateRequestCache += new EventHandler(this.UpdateRequestCache);

       httpA.EndRequest += new EventHandler(this.EndRequest);

    }

 

    public void Dispose()

    {

 

    }

 

    private void AuthenticateRequest(object r_objSender, EventArgs r_objEventArgs)

    {

       HttpApplication httpA = (HttpApplication)r_objSender;

       httpA.Context.Response.Write("in MyHttpModule AuthenticateRequest Event Handler <br/>");

    }

    private void BeginRequest(object r_objSender, EventArgs r_objEventArgs)

    {

       HttpApplication httpA = (HttpApplication)r_objSender;

       httpA.Context.Response.Write("in MyHttpModule BeginRequest Event Handler <br/>");

    }

    private void AuthorizeRequest(object r_objSender, EventArgs r_objEventArgs)

    {

       HttpApplication httpA = (HttpApplication)r_objSender;

       httpA.Context.Response.Write("in MyHttpModule AuthorizeRequest Event Handler <br/>");

    }

    private void ResolveRequestCache(object r_objSender, EventArgs r_objEventArgs)

    {

       HttpApplication httpA = (HttpApplication)r_objSender;

       httpA.Context.Response.Write("in MyHttpModule ResolveRequestCache Event Handler <br/>");

    }

    private void AcquireRequestState(object r_objSender, EventArgs r_objEventArgs)

    {

       HttpApplication httpA = (HttpApplication)r_objSender;

       httpA.Context.Response.Write("in MyHttpModule AcquireRequestState Event Handler <br/>");

    }

    private void PreRequestHandlerExecute(object r_objSender, EventArgs r_objEventArgs)

    {

       HttpApplication httpA = (HttpApplication)r_objSender;

       httpA.Context.Response.Write("in MyHttpModule PreRequestHandlerExecute Event Handler <br/>");

    }

    private void PostRequestHandlerExecute(object r_objSender, EventArgs r_objEventArgs)

    {

       HttpApplication httpA = (HttpApplication)r_objSender;

       httpA.Context.Response.Write("in MyHttpModule PostRequestHandlerExecute Event Handler <br/>");

    }

    private void ReleaseRequestState(object r_objSender, EventArgs r_objEventArgs)

    {

       HttpApplication httpA = (HttpApplication)r_objSender;

       httpA.Context.Response.Write("in MyHttpModule ReleaseRequestState Event Handler <br/>");

    }

    private void UpdateRequestCache(object r_objSender, EventArgs r_objEventArgs)

    {

       HttpApplication httpA = (HttpApplication)r_objSender;

       httpA.Context.Response.Write("in MyHttpModule UpdateRequestCache Event Handler <br/>");

    }

    private void EndRequest(object r_objSender, EventArgs r_objEventArgs)

    {

       HttpApplication httpA = (HttpApplication)r_objSender;

       httpA.Context.Response.Write("in MyHttpModule EndRequest Event Handler <br/>");

    }

}

固然了,此時也要在web.config中做相應的修改;

而後運行的結果以下:

 

如此一來,這些事件的執行順序就一目瞭然了。


 

5)配置文件中配置HttpModule的另一種方法;

另一種配置方法就是,以上面的這個例子爲例。

首先創建一個普通的工程,假設工程名爲:MyHttpModuleMultiEventProject,而後把MyHttpModuleMultiEvent.cs添加進去;編譯該工程,獲得MyHttpModuleMultiEventProject.dll,而後在要使用該httpModule的工程當中添加該dll的引用;而後在該工程的web.config中配置以下代碼:

<httpModules>

  <add name ="MultiEvent" type="MyHttpModuleMultiEvent,MyHttpModuleEventProject"/>

 

</httpModules>

一切就ok了。

有一點要注意的是,在這樣配置方式下,若是想要對那些本身寫的HttpModule可以進行單步調試,就要在web.config中添加以下代碼:

    <system.web>

      <authorization>

        <deny users="?"/>

 </authorization>

 

   </system.web>

否則將沒法進行調試,至於爲何,俺不明白的啦。

若是想要很好的理解一個http的執行過程,能夠參考下面的這個圖:


 

 

1.1.5          HttpHandler

關鍵的一個方法是:ProcessRequest()。通常來講,只要實現這個方法就能夠了。

 

若是要在HttpHandler中使用Session,就必須實現IRequireSessionState。該接口指定目標HTTP處理程序接口具備對會話狀態值的讀寫訪問權限。這是一個標記接口,沒有任何方法。
   
    本節將會在後面作一些補充


2
         
Master Pages[2006-10-26]

2.1         概述

Master page vs2005新出來的一種頁面設計技術,它對於保持一個網站的統一風格是十分有幫助的,在以往的asp的程序中,要想讓網站保持統一的風格就只能採用ctrl+c ,ctrl +v,即便是在vs2003的時代,也仍然是採用這樣的方式。此方式最大的壞處就在於一旦風格要有所改變,那麼要改動多個地方。也就是有重複代碼的bad smell

Master pages的好處就在於,模板只有一個,能夠被任意屢次的重複使用,並且之後若是模板須要改動,就只要修改一個地方就能夠了。

Vs2005之因此這麼作,是由於在vs2002vs2003的使用過程當中,用戶反映到了他的許多不合理的地方,microsoft及時的對其進行了調整。

其實master page的出現是由於在vs 2005中加入了partail class技術。這種技術使得在設計期間能夠把一個class分割成多個單元,在運行的時候把這多個單元進行合併。

採用master pages 的一個好處就是,你在設計子頁的content的時候,經過vs2005ide能夠清除的看到主頁的內容,而事實上呢,子頁的源文件並不包含master page的內容。

2.2         編輯Master pages

編輯一個master pages其實很簡單,和之前編輯任何的aspx的頁面是沒有區別的,因此在aspx頁面中可使用的控件在這裏同樣可使用。

有點稍微不一樣,也是顯而易見的就是:在master page中,你要使用一個叫作:ContentPlaceHolder的控件來標定content的區域,以便在content pages中對該區域進行編輯。

2.3         編輯Content pages

經過查看content page的源碼,你會發現他的代碼十分的簡單,下面就是一個例子:

<%@ Page Language="C#" MasterPageFile="~/MyFirstMasterPage.master" AutoEventWireup="true" CodeFile="MyFirstContentPage.aspx.cs" Inherits="MyFirstContentPage" Title="Untitled Page" %>

<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">

</asp:Content>

content page中,你只要負責編輯好content 中的內容就能夠了,其餘的什麼都不要你操心。

而在content 中編輯東西就和你之前在aspx中編輯東西是同樣的,基本感受不出有什麼不一樣。

2.4         代碼存放方式的混合和編程語言的混合

意思就是,在master page中,你可能使用的是嵌入代碼的方式,可是這不意味你在content page當中也必定要使用嵌入代碼的方式,你徹底能夠在content page中使用界面與代碼分開的方式。

一樣的,你能夠在master page中使用vb,而後在content page中使用c#

一切皆有可能。

2.5         指定使用哪一個master page 的方式

能夠有三種方式:

(1)       在建立content page的時候直接指定;

(2)       web.config中指定;

下面給出例子:

對於(2

<configuration>

<system.web>

<pages masterPageFile=」~/Wrox.master」 />

</system.web>

</configuration>

 

這裏須要指出的是,採用這種方式制定的master page是整個application中共同使用的,也就是整個程序的界面風格統一,可是這並不意味着不可更改,其實你徹底能夠在某頁中修改master page

<%@ Page Language=」VB」 MasterPageFile=」~/MyOtherCompany.master」 %>

 

此外,你還能夠專門爲某個目錄下的content page指定master page,代碼以下:

<configuration>

<location path=」AdministrationArea」>

<system.web>

<pages masterPageFile=」~/WroxAdmin.master」 />

</system.web>

</location>

</configuration>

(3)       在程序中經過代碼來指定;

這個其實也很簡單,代碼以下:

protected void Page_PreInit(object sender, EventArgs e)

    {

       MasterPageFile = "MySecondMasterPage.master";

}

注意,該屬性的修改代碼不能放在Page_Load()中,只能放在Page_PreInit()或者在這個事件以前。不要問我爲何,編譯器這麼說的。

2.6         Master page 的嵌套

到目前爲止,咱們給出的例子中,每一個content page都只用到一個master page。而在實際的應用中,不少組織自己就是多層的,這固然就但願master也可以有多層,如此一來組織的每一層均可以打造自身的master page。充分顯示其靈活性。

 

要編輯嵌套的master page有點點麻煩,主要是vs2005不可以經過view design的方式來編輯。下面說說一個二級master page的編輯過程。該例子共有三個頁面,這三個頁面之間的關係以下圖所示:mainMasterPage.mastersubmasterPage.mastermaster page SubMasterPage.master又是ContentPage.aspxmaster page

大概步驟是這樣的:

首先創建MainMasterPage.aspx,這步和通常創建masterpage 的過程沒有什麼區別,這裏就很少說了。

代碼以下:

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

 

<!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>Untitled Page</title>

</head>

<body>

    <form id="form1" runat="server">

    <div>

        <asp:Label ID="Label1" runat="server" Text="main1"></asp:Label><br />

       

        <asp:contentplaceholder id="ContentPlaceHolder1" runat="server">

        </asp:contentplaceholder> <br />

        

    </div>

    </form>

</body>

</html>

第二步是創建SubMasterPage.master,這一步最複雜。

(1)     像創建MainMasterpage.master同樣創建一個master page,命名爲SubMasterPage.master,創建好以後代碼以下:

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

 

<!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>Untitled Page</title>

</head>

<body>

    <form id="form1" runat="server">

    <div>

        <asp:contentplaceholder id="ContentPlaceHolder1" runat="server">

        </asp:contentplaceholder>

    </div>

    </form>

</body>

</html>

(2)     由於創建master page的時候不能選擇繼承自哪一個master page,因此SubMasterPage.mastermaster page要經過手動來添加:

<%@ Master Language="C#" MasterPageFile="~/MainMasterPage.master"  AutoEventWireup="true" CodeFile="subMasterPage.master.cs" Inherits="subMasterPage" %>

(3)     而後是修改SubMasterPage.master的內容,由於它是繼承自MainMasterPage.master,因此他的內容應該在mainMasterpagecontent裏頭。因此其內容要修改成:

<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">

   <asp:Label ID="Label2" runat="server" Text="main2"></asp:Label><br />

   <asp:contentplaceholder id="ContentPlaceHolder2" runat="server">    

   </asp:contentplaceholder>

</asp:Content>

 

第三步是添加Contentpage.aspx,這個步驟和通常的步驟沒有區別,

可是這裏有一點要注意的是,他只能使用SubMasterPageContentPlaceHolder,而不能使用MainMasterPageplaceholder,代碼以下:

<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder2" Runat="Server">

  <asp:Label ID="Label3" runat="server" Text="content"></asp:Label><br />

</asp:Content>

 

整個程序運行後的結果爲:

相關文章
相關標籤/搜索