天天看點

httpModules 與 httpHandlers

ASP.NET對請求處理的過程:

當請求一個*.aspx檔案的時候,這個請求會被inetinfo.exe程序截獲,它判斷檔案的字尾(aspx)之後,将這個請求轉交給ASPNET_ISAPI.dll,ASPNET_ISAPI.dll會通過http管道(Http PipeLine)将請求發送給ASPNET_WP.exe程序,在ASPNET_WP.exe程序中通過HttpRuntime來處理這個請求,處理完畢将結果傳回用戶端。

    inetinfo.exe程序:是www服務的程序,IIS服務和ASPNET_ISAPI.DLL都寄存在此程序中。

    ASPNET_ISAPI.DLL:是處理.aspx檔案的win32元件。其實IIS伺服器是隻能識别.html檔案的,當IIS伺服器發現被請求的檔案是.aspx檔案時,IIS伺服器将其交給aspnet_isapi.dll來處理。

    aspnet_wp.exe程序:ASP.NET架構程序,提供.net運作的托管環境,.net的CLR(公共語言運作時)就是寄存在此程序中。

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的時候,系統還沒有對這個請求真正處理,但是我們可以在這個請求傳遞到進行中心(HttpHandler)之前附加一些其它資訊,或者截獲的這個請求并作一些額外的工作,也或者終止請求等。在HttpHandler處理完請求之後,我們可以再在相應的HttpModule中把請求處理的結果進行再次加工傳回用戶端。

HttpModule

    HTTP子產品是實作了System.Web.IhttpModule接口的類。

    IHttpModule接口的聲明:

        public interface IHttpModule

        {

            void Init (HttpApplication context);

            void Dispose ();

        }

        Init 方法:系統初始化的時候自動調用,這個方法允許HTTP子產品向HttpApplication 對象中的事件注冊自己的事件處理程式。

        Dispose方法: 這個方法給予HTTP子產品在對象被垃圾收集之前執行清理的機會。此方法一般無需編寫代碼。

    HTTP子產品可以向System.Web.HttpApplication對象注冊下面一系列事件:

        AcquireRequestState 當ASP.NET運作時準備好接收目前HTTP請求的對話狀态的時候引發這個事件。

        AuthenticateRequest 當ASP.NET 運作時準備驗證使用者身份的時候引發這個事件。

        AuthorizeRequest 當ASP.NET運作時準備授權使用者通路資源的時候引發這個事件。

        BeginRequest 當ASP.NET運作時接收到新的HTTP請求的時候引發這個事件。

        Disposed 當ASP.NET完成HTTP請求的處理過程時引發這個事件。

        EndRequest 把響應内容發送到用戶端之前引發這個事件。

        Error 在處理HTTP請求的過程中出現未處理異常的時候引發這個事件。

        PostRequestHandlerExecute 在HTTP處理程式結束執行的時候引發這個事件。

        PreRequestHandlerExecute 在ASP.NET開始執行HTTP請求的處理程式之前引發這個事件。在這個事件之後,ASP.NET 把該請求轉發給适當的HTTP處理程式。

        PreSendRequestContent 在ASP.NET把響應内容發送到用戶端之前引發這個事件。這個事件允許我們在内容到達用戶端之前改變響應内容。我們可以使用這個事件給頁面輸出添加用于所有頁面的内容。例如通用菜單、頭資訊或腳資訊。

        PreSendRequestHeaders 在ASP.NET把HTTP響應頭資訊發送給用戶端之前引發這個事件。在頭資訊到達用戶端之前,這個事件允許我們改變它的内容。我們可以使用這個事件在頭資訊中添加cookie和自定義資料。

        ReleaseRequestState 當ASP.NET結束所搜有的請求處理程式執行的時候引發這個事件。

        ResolveRequestCache 我們引發這個事件來決定是否可以使用從輸出緩沖傳回的内容來結束請求。這依賴于Web應用程式的輸出緩沖時怎樣設定的。

        UpdateRequestCache 當ASP.NET完成了目前的HTTP請求的處理,并且輸出内容已經準備好添加給輸出緩沖的時候,引發這個事件。這依賴于Web應用程式的輸出緩沖是如何設定的。

    上面這麼多的事件,我們看起來可能會有些眼暈,但沒關系,下面一步一步地看。

    HttpModule生命周期示意圖

下面是事件的觸發順序:

BeginRequest和PreRequestHandlerExecute之間的事件是在伺服器執行HttpHandler處理之前觸發。

    PostRequestHandlerExecute和PreSendRequestContent之間的事件是在伺服器執行Handler處理之後觸發。

 下面我們看一下如何使用HttpModule來實作我們日常的應用:

        HttpModule通過在某些事件中注冊,把自己插入ASP.NET請求處理管道。當這些事件發生的時候,ASP.NET調用對相應的HTTP子產品,這樣該子產品就能處理請求了。

       1、向每個頁面動态添加一些備注或說明性的文字:

            有的網站每一個頁面都會彈出一個廣告或在每個頁面都以注釋形式(<!-- -->)加入網站的版權資訊。如果在每個頁面教編寫這樣的JS代碼的話,對于大一點的網站,這種JS代碼的編寫與維護可是一個很繁瑣枯燥的工作。

            有了HttpModule我們就可以很簡單地解決這個問題了。HttpModule是用戶端送出請求到用戶端接收到伺服器響應之間的一段必經之路。我們完全可以在伺服器處理完請求之後,并在向用戶端發送響應文本之前這段時機,把這段注釋文字添加到頁面文本之後。這樣,每一個頁面請求都會被附加上這段注釋文字。

            這段代碼究竟該在哪個事件裡實作呢? PostRequestHandlerExecute和PreSendRequestContent之間的任何一個事件都可以,但我比較喜歡在EndRequest事件裡編寫代碼。

            第一步:建立一個類庫ClassLibrary831。

            第二步:編寫一個類實作IHttpModule接口

                class TestModule:IHttpModule

                {

                    public void Dispose()

                    {

                    }

                    public void Init(HttpApplication context)

                    {

                    }

                }

            第三步:在Init事件中注冊EndRequest事件,并實作事件處理方法

               class TestModule:IHttpModule

                {

                    public void Dispose(){}

                    public void Init(HttpApplication context)

                    {

                        context.EndRequest += new EventHandler(context_EndRequest);

                    }

                    void context_EndRequest(object sender, EventArgs e)

                    {

                        HttpApplication ha = (HttpApplication)sender;

                        ha.Response.Write("<!--這是每個頁面都會動态生成的文字。--grayworm-->");

                    }

                }

            第四步:在Web.Conofig中注冊一下這個HttpModule子產品

          <httpModules>

           <add name="TestModule" type="ClassLibrary831.TestModule,ClassLibrary831"></add>

          </httpModules>

          name:子產品名稱,一般是類名

          type:有兩部分組成,前半部分是命名空間和類名組成的全名,後半部分是程式集名稱,如果類是直接放在App_Code檔案夾中,那程式名稱是App_Code。

                這樣在Web站點是添加該類庫的引用後,運作每個頁面,會發現其源檔案中都會加入“<!--這是每個頁面都會動态生成的文字。--grayworm-->”這句話。同樣的方法你也可以在其中加入JS代碼。

       2、身份檢查

            大家在作登入時,登入成功後,一般要把使用者名放在Session中儲存,在其它每一個頁面的Page_Load事件中都檢查Session中是否存在使用者名,如果不存在就說明使用者未登入,就不讓其通路其中的内容。

            在比較大的程式中,這種做法實在是太笨拙,因為你幾乎要在每一個頁面中都加入檢測Session的代碼,導緻難以開發和維護。下面我們看看如何使用HttpModule來減少我們的工作量

            由于在這裡我們要用到Session中的内容,我們隻能在AcquireRequestState和PreRequestHandlerExecute事件中編寫代碼,因為在HttpModule中隻有這兩事件中可以通路Session。這裡我們選擇PreRequestHandlerExecute事件編寫代碼。

            第一步:建立一個類庫ClassLibrary831。

            第二步:編寫一個類實作IHttpModule接口

                class TestModule:IHttpModule

                {

                    public void Dispose()

                    {

                    }

                    public void Init(HttpApplication context)

                    {

                    }

                }

            第三步:在Init事件中注冊PreRequestHandlerExecute事件,并實作事件處理方法

               class AuthenticModule:IHttpModule

                {

                    public void Dispose(){}

                    public void Init(HttpApplication context)

                    {

                        context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);

                    }

                    void context_PreRequestHandlerExecute(object sender, EventArgs e)

                    {

                        HttpApplication ha = (HttpApplication)sender;

                        string path = ha.Context.Request.Url.ToString();

                        int n = path.ToLower().IndexOf("Login.aspx");

                        if (n == -1) //是否是登入頁面,不是登入頁面的話則進入{}

                        {

                            if (ha.Context.Session["user"] == null) //是否Session中有使用者名,若是空的話,轉向登入頁。

                            {

                                ha.Context.Response.Redirect("Login.aspx?source=" + path);

                            }

                        }

                    }

                }

            第四步:在Login.aspx頁面的“登入”按鈕中加入下面代碼

                protected void Button1_Click(object sender, EventArgs e)

                {

                    if(true)    //判斷使用者名密碼是否正确

                    {

                        if (Request.QueryString["source"] != null)

                        {

                            string s = Request.QueryString["source"].ToLower().ToString();   //取出從哪個頁面轉來的

                            Session["user"] = txtUID.Text;

                            Response.Redirect(s); //轉到使用者想去的頁面

                        }

                        else

                        {

                            Response.Redirect("main.aspx");    //預設轉向main.aspx

                        }

                    }

                }

            第五步:在Web.Conofig中注冊一下這個HttpModule子產品

          <httpModules>

           <add name="TestModule" type="ClassLibrary831.TestModule,ClassLibrary831"></add>

          </httpModules>

       3、多子產品的操作

            如果定義了多個HttpModule,在web.config檔案中引入自定義HttpModule的順序就決定了多個自定義HttpModule在處理一個HTTP請求的接管順序。

HttpHandler

    HttpHandler是HTTP請求的進行中心,真正地對用戶端請求的伺服器頁面做出編譯和執行,并将處理過後的資訊附加在HTTP請求資訊流中再次傳回到HttpModule中。

    HttpHandler與HttpModule不同,一旦定義了自己的HttpHandler類,那麼它對系統的HttpHandler的關系将是“覆寫”關系。

    IHttpHandler接口聲明

    public interface IHttpHandler

    {

        bool IsReusable { get; }

        public void ProcessRequest(HttpContext context); //請求處理函數

    }

    示例:把硬碟上的圖檔以流的方式寫在頁面上

        class TestHandler : IHttpHandler

        {

            public void ProcessRequest(HttpContext context)

            {

                FileStream fs = new FileStream(context.Server.MapPath("worm.jpg"), FileMode.Open);

                byte[] b = new byte[fs.Length];

                fs.Read(b, 0, (int)fs.Length);

                fs.Close();

                context.Response.OutputStream.Write(b, 0, b.Length);

            }

            public bool IsReusable

            {

                get

                {

                    return true;

                }

            }

        }

        Web.Config配置檔案

      <httpHandlers>

       <add verb="*" path="*" type="ClassLibrary831.TestHandler,ClassLibrary831"></add>

      </httpHandlers>

           Verb屬性:指定了處理程式支援的HTTP動作。*-支援所有的HTTP動作;“GET”-支援Get操作;“POST”-支援Post操作;“GET, POST”-支援兩種操作。

  Path屬性:指定了需要調用處理程式的路徑和檔案名(可以包含通配符)。“*”、“*.aspx”、“showImage.aspx”、“test1.aspx,test2.aspx”

  Type屬性:用名字空間、類名稱和程式集名稱的組合形式指定處理程式或處理程式工廠的實際類型。ASP.NET運作時首先搜尋bin目錄中的DLL,接着在GAC中搜尋。

        這樣程式運作的效果是該網站的任何一個頁面都會顯示worm.jpg圖檔。如何隻讓一個頁面(default21.aspx)執行HttpHandler中的ProcessRequest方法呢?最簡單的辦法是在Web.Config檔案中把path配置資訊設為default21.aspx。

        根據這個例子大家可以考慮一下如何編寫“驗證碼”了。

IHttpHandler工廠

    IHttpHandlerFactory的作用是對IHttpHandler進行管理。工廠的作用請見http://hi.baidu.com/grayworm/blog/item/4a832160f8c9de46eaf8f8c1.html"

    IHttpHandlerFactory接口的聲明:

        public interface IHttpHandlerFactory

        {

            IHttpHandler GetHandler (HttpContext context,string requestType,string url,string pathTranslated);

            void ReleaseHandler (IHttpHandler handler);

        }

       GetHandler傳回實作IHttpHandler接口的類的執行個體,ReleaseHandler使工廠可以重用現有的處理程式執行個體。

    示例:兩個用IHttpHandlerFactory來實作對不同HttpHandler的調用。

    有兩個HttpHandler:将圖檔顯示在頁面上的HttpHandler和生成驗證碼的Handler

        //将圖檔顯示在頁面上的Handler

        class TestHandler : IHttpHandler

        {

            public void ProcessRequest(HttpContext context)

            {

                FileStream fs = new FileStream(context.Server.MapPath("worm.jpg"), FileMode.Open);

                byte[] b = new byte[fs.Length];

                fs.Read(b, 0, (int)fs.Length);

                fs.Close();

                context.Response.OutputStream.Write(b, 0, b.Length);

            }

            public bool IsReusable

            {

                get

                {

                    return true;

                }

            }

        }

        //生成驗證碼的Handler

        class CodeHandler:IHttpHandler

        {

            public bool IsReusable

            {

                get

                {

                    return true;

                }

            }

            public void ProcessRequest(HttpContext context)

            {

                Image b = new Bitmap(50,20);

                Graphics g = Graphics.FromImage(b);

                SolidBrush sb = new SolidBrush(Color.White);

                Font f = new Font("宋體", 12);

                string str = "";

                Random r = new Random();

                for (int i = 0; i < 4; i++)

                {

                    str += r.Next(10);

                }

                g.DrawString(str,f,sb,0,0);

                b.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);

            }

        }

         IHttpHandler工廠

         class TestHandlerFactory : IHttpHandlerFactory

         {

            public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)

            {

                string fname = url.Substring(url.IndexOf('/') + 1);

                while (fname.IndexOf('/') != -1)

                    fname = fname.Substring(fname.IndexOf('/') + 1);

                string cname = fname.Substring(0, fname.IndexOf('.'));

                string className ="";

                className = "ClassLibrary831.CodeHandler";

                object h = null;

                try

                {

                    //h = new TestHandler();

                    h = Activator.CreateInstance(Type.GetType(className));

                }

                catch (Exception e)

                {

                    throw new HttpException("工廠不能為類型" + cname + "建立執行個體。", e);

                }

                return (IHttpHandler)h;

            }

            public void ReleaseHandler(IHttpHandler handler)

            {

            }

         }(車延祿)

        配置檔案

    <httpHandlers>

    <add verb="*" path="default21.aspx,default22.aspx" type="ClassLibrary831.TestHandlerFactory,ClassLibrary831"></add>

   </httpHandlers>

   這樣TestHandlerFactory就會根據請求的不同頁面執行不同的HttpHandler處理程式了。

HttpHandler使用會話

    如果要在處理程式中使用Session,那必須把該HttpHandler實作IRequiresSessionState接口,,IRequiresSessionState接口是個空接口,它沒有抽象方法,隻是一個标記。此處就不作例子驗證了

ASP.Net處理Http Request時,使用Pipeline(管道)方式,由各個HttpModule對請求進行處理,然後到達 HttpHandler,HttpHandler處理完之後,仍經過Pipeline中各個HttpModule的處理,最後将HTML發送到用戶端浏覽 器中。

生命周期中涉及到幾個非常重要的對象:HttpHandler,HttpModule,IHttpHandlerFactory,他們的執行(順序)大緻的執行過程是這樣的:client端發送頁面請求,被IIS的某個程序截獲,它根據申請的頁 面字尾(.aspx)不同,調用不同的頁面處理程式(.asp->asp.dll; .aspx->ISAPI.dll).而頁面處理程式在處理過程中,則要經曆HttpModule,HttpHandler的處理:前者HttpModule用于頁面處理前和處理後的一些事件的處理,後者HttpHandler進行真正的頁面的處理。

如前所說,HttpModule會在頁面處理前和後對頁面進行處理,是以它不會影響真正的頁面請求。通常用在給每個頁面的頭部或者尾部添加一些資訊(如版 權聲明)等.曾經見過一些免費的空間,我們的頁面上傳上去後,浏覽的時候發現,在每個頁面的頭部和尾部多了很多小廣告....,如果了解了 HttpModule的原理,要做這個就不是很難了~

IHttpModule與IHttpHandler的差別整理

    1.先後次序.先IHttpModule,後IHttpHandler. 注:Module要看你響應了哪個事件,一些事件是在Handler之前運作的,一些是在Handler之後運作的

    2.對請求的處理上:

        IHttpModule是屬于大小通吃類型,無論用戶端請求的是什麼檔案,都會調用到它;例如aspx,rar,html的請求.

        IHttpHandler則屬于挑食類型,隻有ASP.net注冊過的檔案類型(例如aspx,asmx等等)才會輪到調用它.

   3.IHttpHandler按照你的請求 生成響應的内容,IHttpModule對請求進行預處理,如驗證、修改、過濾等等,同時也可以對響應進行處理

ASP.Net系統本身配置有很多HttpHandler和HttpModule,以處理aspx等.Net标準的頁面檔案,以及這些頁面檔案中标 準的事件處理等。檢視%System%/Microsoft.NET/Framework/v2.0.50727/CONFIG目錄下的 web.config檔案中的httpHandlers和httpModules節點,可以看到這些配置。如果有興趣,可以使用Reflector查 看.Net系統中相關的類和方法,了解.Net如何處理以及做了什麼處理。

.Net也提供了一套機制來開發自定義的HttpHandler和 HttpModule,均可以用于對HttpRequest的截取,完成自定義的處理。 HttpModule 繼承System.Web.IHttpModule接口,實作自己的HttpModule類。必須要實作接口的兩個方法:Init和Dispose。在 Init中,可以添加需要截取的事件;Dispose用于資源的釋放,如果在Init中建立了自己的資源對象,請在Dispose中進行釋放。

namespace MyModule

{

public class MyHttpModule : IHttpModule

{

    public MyHttpModule()

    {

    }

   //Init方法用來注冊HttpApplication 事件。

   public void Init(HttpApplication r_objApplication)

    {

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

    }   

public void Dispose()

    {

    }   

private void BeginRequest(object r_objSender, EventArgs r_objEventArgs)

    {

      HttpApplication objApp = (HttpApplication)r_objSender;

      objApp.Response.Write("您請求的URL為" + objApp.Request.Path);

    }

}

}  

将編譯的dll檔案拷貝到web項目的bin目錄下,在web項目的web.config檔案system.web節點中配置:

    這樣就将自定義的HttpModule類MyHttpModule插入到了目前web的HttpModule的Pipeline中。 HttpModule主要功能是對Application的各個事件進行截取,在這些事件中完成自己的處理。其實如果自己開發一些項目,直接在 Global.asax中處理已經足夠了。如果是開發一個Framework或者是某些方面的元件,需要在事件中添加處理,開發自定義的 HttpModule,可以避免使用Framework或者元件時,還得手工在Global.asax中添加代碼。     目前想到的開發自定義HttpModule的用途,有全局的身份/權限驗證、自定義網站通路/記錄檔的記錄、處于管理/調試等目的對站點進行監控追蹤 等。當然,如果是結合自定義的HttpHandler進行Framework的開發,HttpModule可以用于其它的一些特殊的處理。

      <httpModules>

         <add name="test" type="MyHttpModuleTest.MyHttpModule,MyHttpModule"/>

       </httpModules>

   注意要區分大小寫,因為web.config作為一個XML檔案是大小寫敏感的。“type=MyHttpModuleTest.MyHttpModule,MyHttpModule”告訴我們

   系統将會将http request請求交給位于MyHttpModule.dll檔案中的MyHttpModuleTest.MyHttpModule類去處理。

HttpHandler是完全的對Http Request的截取。

    首先,繼承System.Web.IHttpHandler接口,實作自己的HttpHandler類。必須要實作接口的ProcessRequest方 法和IsReusable屬性。ProcessRequest方法中完成對每個Http Request的處理,發送處理結果的HTML到輸出緩存中。IsReusable屬性被.Net Framework調用,用以确定這個HttpHandler的執行個體是否可以被重用于同類型其它的Request處理。

    如果你在自己的HttpHandler類中,需要讀取或者是寫Session值,需要再繼承一個接口IRequiresSessionState。這個接 口沒有任何方法,隻是一個标記接口。繼承這個接口之後,就可以在自己的HttpHandler中通路Session,可以在Session中寫入值。

namespace MyHandler

{

public class MyHttpHandler : IHttpHandler, IRequiresSessionState

{

    public MyHttpHandler() {}

    public bool IsReusable

    {

      get { return true; }

    }

    public void ProcessRequest(HttpContext context)

    {

      HttpResponse objResponse = context.Response ;

      objResponse.Write("

This request is handled by MyHttpHandler

");

    }

}

}

    把編譯的dll檔案拷貝到web項目的bin目錄下。

    接下來,這樣來測試一下MyHttpHandler。我們為IIS配置一個以.cc為字尾名的檔案類型,用我們寫的MyHttpHandler來處理。

    首先,在IIS站點的Configuration配置裡面,添加一個對.cc字尾名處理的Application Extention Mapping項。 

    然後,在web項目的web.config節點節點中配置:

MyHttpHandler, MyHandler"/>

    verb屬性配置這個HttpHandler處理那些HTTP方法,例如GET、POST等,如果是處理所有方法,就用*。path屬性配置HttpHandler對哪些檔案進行處理,例如可以是myfile.cc,如果是處理所有的.cc檔案,就用*.cc。

    這樣,這個站點上所有.cc類型檔案的通路,都由MyHttpHandler處理。使用http://localhost/站點虛拟目錄/a.cc通路測試站點,可以看到測試效果。當然,a.cc這個檔案在Web伺服器上是并不存在的。

    對HttpHandler的使用,比較典型的有.Net的Web MVC開源項目Maverick。Maverick使用一個Dispatcher類對所有的Http Request進行截取,他以.m作為字尾名向Web伺服器送出請求,在Dispatcher中,将.m的字尾去掉,提取Command Name,然後以這個command name從配置檔案中加載處理的flow,形成一個chain,依次對chain上的各個command和view進行處理,對各個command和 view的處理結果可能會在chain中選擇不同的處理分支,每個處理的Step中将處理結果的HTML寫入Response的緩存中進行輸出。

    總體來說,Maverick的架構架構概念很不錯,但也存在明顯的缺陷,以後有時間再詳細的寫寫它的架構和需要改進之處。

    總之,将HttpModule、HttpHandler,以及使用Ajax等将用戶端進行封裝結合起來,能夠給web項目的開發帶來非常大的改善空間。

Asp.Net HttpHandler實作URL重寫的

我們經常看到很多網站通路文章的時候才用的是***.html 或***.shtml (如本blog的日志通路效果),其時這寫檔案在伺服器上不存在的,那為什麼會出現這樣的效果呢,是因為Web伺服器上對URL執行了重寫,把通路的 URL根據特定的格式重寫成内部通路頁面來實作的,它的好處是便于使用者了解,同時搜尋引擎也能更好地收入你的網站,當然其它的好處也很多,這裡不做一一介 紹了。

本文所講的是使用Asp.Net中的HttpHandler實作URL重寫的,它所實作的原理請看這裡,本程式可以處理任何Url,因為我在程式中使用了URL過慮,隻有通路檔案名是數字的才進行處理,并指在内部執行一個新的頁面,并輸出資料,代碼如下:

public void ProcessRequest(HttpContext Context)

{  

try {      

         //申明Request       

HttpRequest Request = Context.Request;

//取來路Url的絕對路徑      

string Url = Request.Url.AbsolutePath;

//取通路的Web檔案的開始字元間隔數

int RegStart = Url.LastIndexOf("/") + 1;

//申明一個确定Web檔案名是否全是數字

Regex Reg = new Regex(@"/d+");

//用正規表達式進行比對

if (Reg.IsMatch(Url, RegStart))

{

// 如果web檔案名是數字,則判定是查詢相關文章,執行指定頁面             Context.Server.Execute("~/PermaLink.aspx?id=" + Reg.Match(Url, RegStart).Value);      

}  

}

catch

{

      Context.Response.Redirect(Context.Request.Url.ToString());

}

}

當然你首先要做的是先建一個類,并繼承自IHttpHandler,然後把這段代碼拷入,并編譯。在Web項目中若要使用此功能,需要在web.config裡面加上如下語句:

<httpHandlers>

    <add verb="*" path="*.shtml" type="HttpHandle.UrlRewrite" />

</httpHandlers>

同時,還要在IIS中對Web項目進行配置,在Web項目的屬性中,在主目錄頁籤裡,把執行權限改為"腳本和可執行檔案",然後打開配置,在應用程式擴充裡加上需重寫的檔案格式的擴充,好了,成事具備,隻欠運作了。