實作HttpHandler
HttpHandler對象必須實作IHttpHandler接口,在HttpApplication對象轉交要求至HttpHandler對象時會調用此接口中的init函數,下面是一個HelloHandler類的程式。
using System;
using System.Web;
using System.Web.SessionState;
namespace c64.HttpHandler
{
public class HelloHandler : IHttpHandler,IRequiresSessionState
{
#region IHttpHandler Members
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/html";
context.Response.Write("<html>");
context.Response.Write("<body>");
context.Response.Write("<B>Response By HelloHandler</B>");
context.Response.Write("</body");
context.Response.Write("</html>");
}
public bool IsReusable
{
get
{
return true;
}
}
#endregion
}
}
挂載這個HttpHandler對象的方法有兩種,一種是直接修改.NET Framework目錄中的machine.config檔案,這樣做将本機上所有的asp.net程式挂載此HttpHandler對象,另一中方式是修改虛拟目錄中的web.config檔案,此方案隻會影響該虛拟目錄中的asp.net程式。此處采用第二種方式,請于web.config檔案中加入下面的叙述。
<httpHandlers>
<add verb="*" path=".ho" type="c64.HttpHandler.HelloHandler,HelloHanlder"/>
</httpHanlders>
path部分的設定是告知HttpApplication對象此HttpHandler對象時對應那一種檔案擴充名,type設定的前段是類的名稱與namespace,後段是Assembly檔案名。除此之外,要讓aspnet_isapi.dll接受.ho檔案的要求,還得在IIS中設定虛拟目錄的内容設定擴充名對應表。
關于Session
預設情況下,當HttpHandler對象被調用時Session對象并未初始化成可用狀态,倘若HttpHandler對象須要使用到Session對象時,必須同時實作IRequiresSessionState接口,此接口隻是識别用途,無須實作任何的方法,下面的程式實作了IRequiresSessionState接口的HelloHandler類源代碼。
using System;
using System.Web;
using System.Web.SessionState;
namespace c64.HttpHandler
{
public class HelloHandler : IHttpHandler,IRequiresSessionState
{
#region IHttpHandler Members
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/html";
context.Response.Write("<html>");
context.Response.Write("<body>");
context.Response.Write("<B>Response By HelloHandler</B>");
string user = (string)context.Session["USER"];
if(user != null && user.Length > 0)
context.Response.Write(user);
context.Response.Write("</body");
context.Response.Write("</html>");
}
public bool IsReusable
{
get
{
return true;
}
}
#endregion
}
}
要測試這個程式,我們可以在WebForm上放置一個按鈕,當使用者按下後存放一個字元串到Session["USER"]中,接着要求.ho的檔案就可以看到結果。
實作HttpModule
與HttpHandler對象的加載時機不同,HttpModule對象是在HttpApplication對象初始化時就一并載入的,這個時機是在本機開機後第一個使用者通路此虛拟目錄時。設計人員撰寫HttpModule對象的機會不多,甚至比撰寫HttpHandler對象的機會還少。下面撰寫一個HelloModule對象來示範如何撰寫HttpModule對象。
using System;
using System.Web;
using System.Web.SessionState;
namespace HttpModule
{
public class HelloModule : IHttpModule,IRequiresSessionState
{
#region IHttpModule Members
public void Init(HttpApplication context)
{
context.Application["HELLO"] = "I am Hello Module!";
context.Application[GetHashCode().ToString()] = 123;
}
public void Dispose()
{
}
#endregion
}
}
這個HelloModule對象隻是很簡單地在Application的State對象中放入一個字元串,與加載HttpHandler對象的方式相同,我們可以修改mechine.config檔案或是虛拟目錄内的web.config檔案來載入它,此處采用第二種方案,請于web.config檔案中放入以下的叙述。
<httpModules>
<add name ="HelloModule" type="HttpModule.HttpModule,HelloModule"/>
</httpModules>
要測試這個HelloModule對象,隻須與WebForm上放置一個按鈕,當使用者按下後由Application State對象中取出由HelloModule對象所放入的字元串即可,下圖是HelloModule對象的執行結果。
IHttpModule實作權限控制
總所周知實作一個系統權限管理子產品有很多種實作方式,在這裡和大家探讨下管道模型實作權限管理子產品。
ASP.NET Framework處理一個Http Request的流程:
HttpRequest-->inetinfo.exe-->ASPNET_ISAPI.dll-->ASPNET_WP.exe-->HttpRuntime-->HttpApplication Factory-->HttpApplication-->HttpModule-->HttpHandler Factory-->HttpHandler-->HttpHandler.ProcessRequest()
ASP.NET請求處理過程是基于管道模型的,這個管道模型是由多個HttpModule和HttpHandler組成,ASP.NET把http請求依次傳遞給管道中各個HttpModule,最終被HttpHandler處理,處理完成後,再次經過管道中的HTTP子產品,把結果傳回給用戶端。
我們可以在每個HttpModule中都可以幹預請求的處理過程。
注意:在http請求的處理過程中,隻能調用一個HttpHandler,但可以調用多個HttpModule。
實作權限控制的思路:
可以利用這個特點對頁面通路進行權限控制,當使用者請求頁面時,可以在HttpModule中進行判斷,如果不是指定角色,就拒絕其通路
先了解下IHttpModule這個接口:
IHttpModule向實作類提供子產品初始化和處置事件。
IHttpModule包含兩個方法:
public void Init(HttpApplication context);
public void Dispose();
Init():這個方法接受一個HttpApplication對象,HttpApplication代表了目前的應用程式,我們需要在這個方法内注冊 HttpApplication對象暴露給用戶端的事件。可見,這個方法僅僅是用來對事件進行注冊,而實際的事件處理程式,需要我們另外寫方法。
整個過程很好了解:
1. 當站點第一個資源被通路的時候,Asp.Net會建立HttpApplication類的執行個體,它代表着站點應用程式,同時會建立所有在Web.Config中注冊過的Module執行個體。
2. 在建立Module執行個體的時候會調用Modul的Init()方法。
3. 在Init()方法内,對想要作出響應的HttpApplication暴露出的事件進行注冊。(僅僅進行方法的簡單注冊,實際的方法需要另寫)。
4. HttpApplication在其應用程式周期中觸發各類事件。
5. 觸發事件的時候調用Module在其Init()方法中注冊過的方法。
Dispose():它可以在進行垃圾回收之前進行一些清理工作。
實作步驟:
先建立一個登陸頁面Login.aspx;主要代碼:
protected void btnLogin_Click(object sender, EventArgs e)
{
if (this.txtUserName.Text.Trim()!="" && this.txtPwd.Text.Trim()!="")
{
string url = Request.QueryString["ReturnUrl"];
//添加身份驗證票證
FormsAuthentication.RedirectFromLoginPage(this.txtUserName.Text, false);
if (url!=null)
{
Response.Redirect(url);
}
Response.Redirect("Index.aspx");
}
}
建立一個類實作IHttpModule接口:Test.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
///Test 的摘要說明
/// </summary>
public class Test:IHttpModule
{
public Test()
{
//
//TODO: 在此處添加構造函數邏輯
//
}
#region IHttpModule 成員
public void Dispose()
{
//throw new NotImplementedException();
}
public void Init(HttpApplication context)
{
// 注冊HttpApplication應用程式 AcquireRequestState 事件
context.AcquireRequestState += new EventHandler(context_AcquireRequestState);
}
void context_AcquireRequestState(object sender, EventArgs e)
{
HttpApplication app =(HttpApplication) sender;
//擷取目前請求的路徑
string path = app.Context.Request.Path;
//判斷是不是登陸頁面
if (!path.EndsWith("login.aspx"))
{ //判斷目前登入使用者是不是admin
if (app.Context.User.Identity.Name!="admin")
{ //如果登入使用者不是admin就無權檢視目前頁面,重定向錯誤頁面
app.Context.Server.Transfer("Error.aspx?message=" + path + "");
}
}
//throw new NotImplementedException();
}
#endregion
}
http://xiaolongwang168.blog.163.com/blog/static/123642111201173095828628/