- 相關(guān)推薦
ASP.NET架構及開(kāi)發(fā)技術(shù)詳解教程
首先我們來(lái)說(shuō)一下Asp.net工作原理。
具體描述下這樣的:首先客戶(hù)請求WEB頁(yè)。然后WEB服務(wù)尋找指令文件(.aspx),而這時(shí)就是aspnet_isapi.dll這個(gè)動(dòng)態(tài)連接庫來(lái)處理。接著(zhù)Asp.net代碼被發(fā)送到公共語(yǔ)言運行時(shí)進(jìn)行編譯。接著(zhù)HTML流返回給瀏覽器和令。最后由瀏覽器處理HTML并顯示頁(yè)面。
什么是ISAPI呢?
在Internet時(shí)代的開(kāi)端,客戶(hù)端的需求非常有限;.htm文件就可以滿(mǎn)足他們的需求。但是,隨著(zhù)時(shí)間的流逝,客戶(hù)端需求的擴充超越了.htm文件或靜態(tài)文件所包含的功能。
開(kāi)發(fā)者需要擴充或擴展Web服務(wù)器的功能。Web服務(wù)器廠(chǎng)商設計了不同的解決方案,但是都遵循同一個(gè)主題“向Web服務(wù)器插入某些組件”。所有的Web服務(wù)器補充技術(shù)都允許開(kāi)發(fā)者建立并插入組件以增強Web服務(wù)器的功能。微軟公司提出了ISAPI(Internet服務(wù)器API),網(wǎng)景公司提出了 NSAPI(網(wǎng)景服務(wù)器API)等等。ISAPI是一種重要的技術(shù),它允許我們增強與ISAPI兼容的Web服務(wù)器(IIS就是一種與ISAPI兼容的 Web服務(wù)器)的能力。我們使用下面的組件達到這個(gè)目的:
1,ISAPI擴展:ISAPI擴展是使用Win32動(dòng)態(tài)鏈接庫來(lái)實(shí)現的。你可以把ISAPI擴展看作是一個(gè)普通的應用程序。ISAPI擴展的處理目標是http請求。
2,ISAPI過(guò)濾器:客戶(hù)端每次向服務(wù)器發(fā)出請求的時(shí)候,請求要經(jīng)過(guò)過(guò)濾器?蛻(hù)端不需要在請求中指定過(guò)濾器,只需要簡(jiǎn)單地把請求發(fā)送給Web服務(wù)器,接著(zhù)Web服務(wù)器把請求傳遞給相關(guān)的過(guò)濾器。接下來(lái)過(guò)濾器可能修改請求,執行某些登錄操作等等。
ASP.NET請求的處理過(guò)程:
ASP.NET請求處理過(guò)程是基于管道模型的,在模型中ASP.NET把http請求傳遞給管道中的所有模塊。每個(gè)模塊都接收http請求并有完全控制權限。模塊可以用任何自認為適合的方式來(lái)處理請求。一旦請求經(jīng)過(guò)了所有HTTP模塊,就最終被HTTP處理程序處理。HTTP處理程序對請求進(jìn)行一些處理,并且結果將再次經(jīng)過(guò)管道中HTTP模塊。
ISAPI的篩選器:
IIS本身是不支持動(dòng)態(tài)頁(yè)面的,也就是說(shuō)它僅僅支持靜態(tài)html頁(yè)面的內容,對于如.asp,.aspx,.cgi,.php等,IIS并不會(huì )處理這些標記,它就會(huì )把它當作文本,絲毫不做處理發(fā)送到客戶(hù)端。為了解決這個(gè)問(wèn)題。IIS有一種機制,叫做ISAPI的篩選器,它是一個(gè)標準組件(COM組件)。
Asp.net服務(wù)在注冊到IIS的時(shí)候,會(huì )把每個(gè)擴展可以處理的文件擴展名注冊到IIS里面(如:*.ascx、*.aspx等)。擴展啟動(dòng)后,就根據定義好的方式來(lái)處理IIS所不能處理的文件,然后把控制權跳轉到專(zhuān)門(mén)處理代碼的進(jìn)程中讓這個(gè)進(jìn)程開(kāi)始處理代碼,生成標準的HTML代碼,生成后把這些代碼加入到原有的Html中,最后把完整的Html返回給IIS,IIS再把內容發(fā)送到客戶(hù)端。
HttpModule:
HttpModule實(shí)現了ISAPI Filter的功能,是通過(guò)對IhttpModule接口的繼承來(lái)處理。
HTTP模塊是實(shí)現了System.Web.IhttpModule接口的.NET組件。這些組件通過(guò)在某些事件中注冊自身,把自己插入ASP.NET請求處理管道。當這些事件發(fā)生的時(shí)候,ASP.NET調用對請求有興趣的HTTP模塊,這樣該模塊就能處理請求了。
HttpModule的實(shí)現:
1. 編寫(xiě)一個(gè)類(lèi),實(shí)現IhttpModule接口。
2. 實(shí)現Init 方法,并且注冊需要的方法。
3. 實(shí)現注冊的方法。
4. 實(shí)現Dispose方法,如果需要手工為類(lèi)做一些清除工作,可以添加Dispose方法的實(shí)現,但這不是必需的,通?梢圆粸镈ispose方法添加任何代碼。
5. 在Web.config文件中,注冊您編寫(xiě)的類(lèi)。
下邊我們來(lái)看例子,HttpModule的實(shí)現:
首先添加一個(gè)類(lèi)庫,然后在引用里引用System.Web和System.Security這兩個(gè)命名空間。然后寫(xiě)個(gè)類(lèi),代碼如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Security.Principal;
namespace Httplibrary
{
public class SecurityModules:IHttpModule
{
public void Init(HttpApplication r_objApplication)
{
// 向Application 對象注冊事件處理程序,核心部分。
r_objApplication.AuthenticateRequest += new EventHandler(this.AuthenticateRequest) ;
}
public void Dispose()
{
}
private void AuthenticateRequest(object r_objSender,EventArgs r_objEventArgs)
{
// 鑒別用戶(hù)的憑證,并找出用戶(hù)角色。
HttpApplication objApp = (HttpApplication) r_objSender ;
HttpContext objContext = (HttpContext) objApp.Context ;
if ( (objApp.Request["userid"] == null) ||(objApp.Request["password"] == null) )
{
objContext.Response.Write("用戶(hù)名和密碼為空,驗證失!") ;
objContext.Response.End() ;
}
string userid = "" ;
userid = objApp.Request["userid"].ToString() ;
string password = "" ;
password = objApp.Request["password"].ToString() ;
string[] strRoles ;
strRoles = AuthenticateAndGetRoles(userid, password) ;
if ((strRoles == null) || (strRoles.GetLength(0) == 0))
{
objContext.Response.Write("用戶(hù)名或密碼錯誤!") ;
objApp.CompleteRequest() ;//終止一個(gè)Http請求
}
GenericIdentity objIdentity = new GenericIdentity(userid,"CustomAuthentication") ;
objContext.User = new GenericPrincipal(objIdentity, strRoles) ;
}
private string[] AuthenticateAndGetRoles(string r_strUserID,string r_strPassword)
{
string[] strRoles = null ;
if ((r_strUserID.Equals("Zhangsan")) && (r_strPassword.Equals("111")))
{
strRoles = new String[1] ;
strRoles[0] = "Administrator" ;
}
else if ((r_strUserID.Equals("Lisi")) && (r_strPassword.Equals("222")))
{
strRoles = new string[1] ;
strRoles[0] = "User" ;
}
return strRoles ;
}
}
}
編譯一下,下邊做測試頁(yè)面,很簡(jiǎn)單,放一個(gè)label,text=“測試頁(yè)面”如果成功則顯示測試頁(yè)面。然后在web.config里面配置,這里很重要。添加 注意注釋部分。
然后添加 這個(gè)節點(diǎn),這個(gè)大家應該都能明白。
然后啟動(dòng)測試頁(yè)面。剛啟動(dòng)開(kāi)始后頁(yè)面一定顯示“用戶(hù)名和密碼為空,驗證失!”呵呵,別忘記了咱們這就是目的,然后在你的地址欄后邊添加?userid= Zhangsan&password=111這行字。然后就會(huì )顯示“測試頁(yè)面”這幾個(gè)字。大家可以多輸入幾個(gè)名字單步調試一下就明白了。
WebConfig設置
<add type=“classname,assemblyname”
name=“modulename”/>
子標記說(shuō)明:
將HttpModule 類(lèi)添加到應用程序。請注意,如果以前已指定了相同的謂詞/路徑組合(例如在父目錄的Web.config 文件中),則對的第二個(gè)調用將重寫(xiě)以前的設置。
從應用程序移除HttpModule 類(lèi)。
從應用程序移除所有HttpModule 映射。
深入研究HttpModule
HttpModule通過(guò)對HttpApplication對象的一系列事件的處理來(lái)對HTTP處理管道施加影響,這些事件在HttpModule的Init方法中進(jìn)行注冊,包括:
BeginRequest
AuthenticateRequest
AuthorizeRequest
ResolveRequestCache
AcquireRequestState
PreRequestHandlerExecute
PostRequestHandlerExecute
ReleaseRequestState
UpdateRequestCache
EndRequest
我們都可以對以上事件進(jìn)行重新定義,注意時(shí)重新定義不時(shí)覆蓋。我們看一個(gè)例子,多個(gè)HttpModule的實(shí)現,建立兩個(gè)類(lèi)庫,什么都相同就是類(lèi)名不相同,引入相應的命名空間后我們編寫(xiě)這個(gè)類(lèi),代碼如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
namespace HttpModuleTest1
{
public class Test1Module:IHttpModule
{
public Test1Module()
{
}
public string ModuleName
{
get
{
return "Test1Module";
}
}
public void Init(HttpApplication application)
{
application.BeginRequest += new EventHandler(myBeginRequest);
application.EndRequest += new EventHandler(myEndRequest);
application.PreRequestHandlerExecute += new EventHandler(myPreRequestHandlerExecute);
application.PostRequestHandlerExecute += new EventHandler(myPostRequestHandlerExecute);
application.ReleaseRequestState += new EventHandler(myReleaseRequestState);
application.AcquireRequestState += new EventHandler(myAcquireRequestState);
application.AuthenticateRequest += new EventHandler(myAuthenticateRequest);
application.AuthorizeRequest += new EventHandler(myAuthorizeRequest);
application.ResolveRequestCache += new EventHandler(myResolveRequestCache);
application.PreSendRequestHeaders += new EventHandler(myPreSendRequestHeaders);
application.PreSendRequestContent += new EventHandler(myPreSendRequestContent);
}
private void myBeginRequest(object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write("Test1Module:Beggining of Request
");
}
private void myEndRequest(object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write("Test1Module:End of Request
");
}
private void myPreRequestHandlerExecute(object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write("Test1Module:Application_RequestHandlerExecute:
");
}
private void myPostRequestHandlerExecute(object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write("Test1Module:Application_PostRequestHandlerExecute:
");
}
private void myReleaseRequestState(object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write("Test1Module:Application_ReleaseRequestState:
");
}
private void myAcquireRequestState(object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write("Test1Module:Application_ReleaseRequestState:
");
}
private void myAuthenticateRequest(object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write("Test1Module:Application_AuthenticateRequest:
");
}
private void myAuthorizeRequest(object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write("Test1Module:Application_AuthorizeRequest:
");
}
private void myResolveRequestCache(object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write("Test1Module:Application_ResolveRequestCache:
");
}
private void myPreSendRequestHeaders(object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write("Test1Module:Application_PreSendRequestHeaders:
");
}
private void myPreSendRequestContent(object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write("Test1Module:Application_PreSendRequestContent:
");
}
public void Dispose()
{
}
}
}
然后在web.config里添加,不明白的看注釋部分。
還是用剛才那個(gè)測試頁(yè)面,我們就可以觀(guān)察到兩個(gè)test的執行順序。
我們具體分析一下就是這樣的:
HttpRequest開(kāi)始->進(jìn)入HttpModule->HttpModule->
首次截獲HttpRequest->HttpModule.BeginRequest->
HttpModule.AuthorizeRequest->HttpModule.ResolveRequestCache->
初始化HttpHandler->建立HttpHandler控制點(diǎn)->HttpModule繼續處理。HttpHandler已經(jīng)建立,此后Session可用->HttpModule.AcquireRequestState
->HttpModule.PreRequestHandlerExecute->進(jìn)入HttpHandler處理HttpRequest
->HttpHandler->HttpHandler.ProcessRequest->返回HttpModule, HttpHandler結束,Session失效->HttpModule.PostRequestHandlerExecute-> HttpModule.ReleaseRequestState->
HttpModule.UpdateRequestCache->HttpModule.EndRequest->HttpModule.PreSendRequestHeaders->HttpModule.PreSendRequestContent->
將處理的數據返回客戶(hù)端,處理結束。
HttpHandler:
HttpHandler實(shí)現了ISAPI Extention的功能,他處理請求(Request)的信息和發(fā)送響應(Response)。HttpHandler功能的實(shí)現通過(guò)實(shí)現IHttpHandler接口來(lái)達到。
HTTP處理程序是實(shí)現了System.Web.IHttpHandler接口的.NET組件。任何實(shí)現了IHttpHandler接口的類(lèi)都可以用于處理輸入的HTTP請求。HTTP處理程序與ISAPI擴展有些類(lèi)似。HTTP處理程序和ISAPI擴展的差別在于在URL中可以使用HTTP處理程序的文件名稱(chēng)直接調用它們,與ISAPI擴展類(lèi)似。
HttpHandler的實(shí)現,實(shí)現我們的HTTP處理程序包含以下步驟:
編寫(xiě)一個(gè)實(shí)現IHttpHandler接口的類(lèi)。
在web.config或machine.config文件中注冊這個(gè)處理程序。
在Internet服務(wù)管理器中把文件擴展(你想要處理的文件擴展名)映射到ASP.NETISAPI擴展DLL(aspnet_isapi.dll)上。
我們來(lái)看一個(gè)例子,打開(kāi)IIS服務(wù)器,屬性,主目錄下有個(gè)配置,里面你就可以找到你的程序所執行文件所要調用的.dll文件。我們可以看到.aspx就是 C:WINDOWSMicrosoft.NETFramework 2.0.50727aspnet_isapi.dll這個(gè)文件
來(lái)執行的。這里還可以添加你自己任意定義任意擴展名文件,定義了后你的服務(wù)器就可以認識這些人間,注意只是你的服務(wù)器,別人的不認識。這時(shí)候大家就會(huì )對網(wǎng)絡(luò )上流行的各式各樣的后綴名不奇怪了吧,可以自己定義的。
我們自己定義一個(gè)帶.xxx后綴的。
添加一個(gè)類(lèi)庫,引用的相應的命名空間,
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
namespace MyHandler
{
public class NewHandler:IHttpHandler
{
public NewHandler()
{
// TODO: 此處添加構造邏輯
}
Implementation of IHttpHandler#region Implementation of IHttpHandler
/**////
/// http處理程序的核心。我們調用這個(gè)方法來(lái)處理http請求。
///
///
public void ProcessRequest(System.Web.HttpContext context)
{
HttpResponse objResponse = context.Response;
objResponse.Write("
Hello xxx ! ");
objResponse.Write("");
}
/**////
/// 我們調用這個(gè)屬性來(lái)決定http處理程序的實(shí)例是否可以用于處理相同其它類(lèi)型的請求。
/// HTTP處理程序可以返回true或false來(lái)表明它們是否可以重復使用。
///
public bool IsReusable
//
{
get
{
return true;
}
}
#endregion
}
}
然后再web.config里面配置相應節點(diǎn):這里不懂的參考前邊的,XXX就是我們剛才定義那個(gè)后綴名。
<add verb="*" path="*.xxx"
type="MyHandler.NewHandler,MyHandler" />
然后添加一個(gè)測試頁(yè)面,就可以了。
HttpHandler之間的關(guān)系是這樣的:
發(fā)送一個(gè)Http請求,然后判斷是否存在自定義的HttpHandler,如果存在的話(huà)由自定義的HttpHandler處理Http請求,否則由系統默認的HttpHandler處理Http請求。
在HttpHandler中訪(fǎng)問(wèn)Session:
不能直接通過(guò)HttpContext訪(fǎng)問(wèn)。
必須實(shí)現IRequiresSessionState接口。
IRequiresSessionState接口指定目標HTTP處理程序接口具有對會(huì )話(huà)狀態(tài)值的讀寫(xiě)訪(fǎng)問(wèn)權限。這是一個(gè)標記接口,沒(méi)有任何方法。
怎樣實(shí)現呢,我們還是來(lái)看例子吧:添加類(lèi)庫,引用相應的命名空間。
using System;
using System.Web;
using System.Web.SessionState;
namespace MyHandler
{
public class NewHandlerSession : IHttpHandler,IRequiresSessionState
{
public NewHandlerSession()
{
// TODO: 此處添加構造邏輯
}
Implementation of IHttpHandler#region Implementation of IHttpHandler
/**////
/// http處理程序的核心。我們調用這個(gè)方法來(lái)處理http請求。
///
///
public void ProcessRequest(System.Web.HttpContext context)
{
HttpResponse objResponse = context.Response ;
HttpRequest objRequest = context.Request;
HttpSessionState objSession = context.Session;
objResponse.Write("歡迎使用自定義HttpHandler!
");
objSession["Test"] = "Session 測試!
";
objResponse.Write("Session的值為:"+objSession["Test"].ToString());
}
/**////
/// 我們調用這個(gè)屬性來(lái)決定http處理程序的實(shí)例是否可以用于處理相同其它類(lèi)型的請求。
/// HTTP處理程序可以返回true或false來(lái)表明它們是否可以重復使用。
///
public bool IsReusable
//
{
get
{
return true;
}
}
#endregion
}
}
然后配置Web.config的節點(diǎn):
<add verb="*" path="*"
type="MyHandler.NewHandlerSession,MyHandlerSession" />
這樣就可以了。
ASP.NET事件模型機制:
ASP.NET之所以對于以前的ASP是一個(gè)革命性的巨變,在很大程度上是由于A(yíng)SP.NET技術(shù)是一種完全基于事件驅動(dòng)的全新技術(shù)。
在A(yíng)SP.NET中事件的觸發(fā)和處理分別是在客戶(hù)端和服務(wù)器段進(jìn)行的。
ASP.NET中,如果頻繁和服務(wù)器進(jìn)行事件信息的傳遞,會(huì )大大降低服務(wù)器的處理效率和性能,因而有些事件如OnMouseOver沒(méi)有提供。
但提供了Change事件。為了提高效率它們被緩存在客戶(hù)端。等到再一次事件信息被發(fā)送到服務(wù)器端時(shí)一同發(fā)送回去。
【ASP.NET架構及開(kāi)發(fā)技術(shù)詳解教程】相關(guān)文章:
ASP.NET MVC異常處理模塊簡(jiǎn)單教程-ASP.NET教程實(shí)例推薦07-19
MCSA認證教程詳解10-04
Web開(kāi)發(fā)的教程圖解06-05
音頻后期制作教程詳解05-08
朝鮮族舞蹈基本動(dòng)作教程詳解09-23
軟件開(kāi)發(fā)整體方案詳解09-01
鑄造安全技術(shù)詳解01-21
OSI七層與TCP/IP五層網(wǎng)絡(luò )架構詳解09-07
足球頭頂球技術(shù)教程01-19
拳擊4大拳法技術(shù)詳解06-15