URL重寫與URL路由


要介紹這兩個內容,必須要從ASP.NET管線說起。

ASP.NET管線

管線(Pipeline)這個詞形象地說明了每個Asp.net請求的處理過程: 請求是在一個管道中,要經過一系列的過程點,這些過程點連接起來也就形成一條線。 這些一系列的過程點,其實就是由HttpApplication引發的一系列事件,通常可以由HttpModule來訂閱, 也可以在Global.asax中訂閱,這一系列的事件也就構成了一次請求的生命周期。

下面通過兩張圖片來詳細說明一下請求的過程

第一張圖,主要展示:請求的過程

從上面的圖中,我們可以看出

1.請求先交給HttpModule處理,然后由HttpModule交給HttpHandler,最后再由HttpHandler交回給HttpModule,由HttpModule結束請求。

2.Session的有效期,只有在HttpHandler處理時有效。HttpModule處理時,都是無效的。

3.整個過程由一系列的事件組成,這點正應驗了前面對管線的定義。

第二張圖,主要說明:管線中所有事件的意義

 

注意:這是iis7的處理過程,其中多了LogRequest與PostLogRequest這兩個事件。iis6的處理過程並沒有這兩個事件。

對於各個事件的含義,我想圖片已經解釋的很清楚了。

 

下面通過一個案例,來講解一下本篇博客的主題。

案例需求:第三方以這樣的url:http://host:port/xxxx/mobile/form?Id=xxxxx。向系統發出請求時。系統可以將該url映射到對應的業務層。由於本次主要講解的重點不在業務層,所以就將該url直接映射到一個簡單業務層,輸入Hello+Query

URL重寫

中心思想:將請求的url重寫成服務器可以處理的url形式。然后由服務器根據重寫后的url,查找出可以處理重寫后的url的Handler,最后由Handler對其進行處理。

思路:

1.定義url重寫后的樣子。比如將url:http://host:port/xxxx/mobile/form?Id=xxxxx。重寫成:http://host:port/xxxx/mobile/service.mobile?Id=xxxxx。

2.編寫自定義Module:IHttpModule,檢測url是否是需要重寫的url,如果是重寫url。由管線根據重寫后的url來尋找對應的Handler對其進行處理

3.編寫自定義Handler:IHttpHandler,來處理重寫后的url。

步驟:

1.編寫自定義Module

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace Service
{
    /// <summary>
    /// url重寫Module
    /// </summary>
    internal class UrlRewriteModule : IHttpModule
    {
        /*
         * 為了演示簡單,直接寫死地址
         * 這里我寫了兩個url,一個從虛擬路徑的根路徑重寫(我本機的虛擬路徑是/Web);另一個從url的末尾處重寫
         * 具體用哪個url,根據需求。但是有一點要注意,如果采用根路徑重寫方式,
         * 那么服務器上的虛擬路徑、重寫后的url的虛擬路徑、Web.config中<httpHandlers>節點下配置的path的虛擬路徑都必須相同,
         * 否則Module無法根據url映射對應的Handler
         */
        public static string rootUrlPattern = "/Web/service.mobile";
        //public static string urlPattern = "service.mobile";

        public void Init(HttpApplication app)
        {
            app.PostAuthorizeRequest += app_PostAuthorizeRequest;
        }

        void app_PostAuthorizeRequest(object sender, EventArgs e)
        {
            HttpApplication app = sender as HttpApplication;

            //檢測是否是要重寫的url(這里最好用正則表達式匹配)
            if (app.Context.Request.Url.PathAndQuery.Contains("mobile/form"))
            {
                //檢查url中是否帶有參數
                int p = app.Request.Path.IndexOf("?");
                if (p > 0)
                {
                    //重寫url,並且將url參數進行拼接
                    app.Context.RewritePath(rootUrlPattern
                        + "&" + app.Request.Path.Substring(p + 1));
                }
                else
                {
                    //重寫url(url中不帶參數)
                    app.Context.RewritePath(rootUrlPattern);
                }
            }
            
        }
        
        public void Dispose()
        {
        }
    }
}
View Code

2.編寫自定義Handler

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace Service
{
    public class UrlHandler : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            HttpRequest request = context.Request;
            string result = string.Empty;
            if (!string.IsNullOrEmpty(request.Form["ID"]))
            {
                string id = request.Form["ID"];
                result = "Hello " + id;
            }
            else
            {
                result = "Hello";
            }
            context.Response.Write(result);
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}
View Code

3.Web.config配置

<httpHandlers>
    <add path="/Web/service.mobile" verb="*" validate="false" type="Service.UrlHandler,Service"/>
</httpHandlers>
<httpModules>
    <add name="UrlRewriteModule" type="Service.UrlRewriteModule,Service"/>
</httpModules>

4.測試頁面

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <script src="Scripts/jquery-1.8.2.js" type="text/javascript"></script>
    <script type="text/javascript">
        function formTest() {
            $.ajax({
                type: "POST",
                url: "mobile/form",
                data: { ID: "wolf" },
                complete: function (XHR, TS) {
                    XHR = null;
                },
                success: function (msg) {
                    alert(msg);
                }
            });
        }
    </script>
</head>
<body>
    <input type="button" value="發起請求" onclick="formTest();" />
</body>
</html>
View Code

以上代碼有2點需要說明

1.選擇注冊PostAuthorizeRequest(用戶已經得到授權)事件中重寫url。因為

  a.用戶驗證,用戶授權都讓其按照asp.net框架自行運行。

  b.PostAuthorizeRequest的下一個事件是ResolveRequestCache(獲取以前處理緩存的處理結果)。如果本次請求的url在之前處理過,那么會直接點用緩存結果,而不會再進行處理工作。如果我寫在ResolveRequestCache事件之后,如果緩存中有處理結果。那么后面的事件都有可能被跳過(EndRequest不會被跳過)。所以我選擇在PostAuthorizeRequest事件中重寫url。

2.自定義Module中,有關於url重寫時需要注意虛擬路徑的一段描述。

如果采用根路徑重寫方式,那么服務器上的虛擬路徑、重寫后的url的虛擬路徑、Web.config中<httpHandlers>節點下配置的path的虛擬路徑都必須相同,否則Module無法根據url映射對應的Handler。

URL路由

中心思想:檢測url是否是需要處理的格式。然后直接指定Handler對重寫后的url進行處理(這點就是url路由與url重寫的區別,url路由是指定Handler來對重寫后的url進行處理,而url重寫是交給管線,讓其尋找能處理重寫后的url的Handler

思路:

1.編寫自定義Module:IHttpModule,檢測url是否是需要處理的格式,如果是由管線根據重寫后的url來尋找對應的Handler對其進行處理

2.編寫自定義Handler:IHttpHandler,來處理重寫后的url。

步驟

1.編寫自定義Module

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace Service
{
    /// <summary>
    /// URL路由
    /// </summary>
    internal class UrlRoutingModule : IHttpModule
    {
        public void Init(HttpApplication app)
        {
            app.PostResolveRequestCache += app_PostResolveRequestCache;
        }

        void app_PostResolveRequestCache(object sender, EventArgs e)
        {
            HttpApplication app = sender as HttpApplication;

            //檢測是否是要重寫的url(這里最好用正則表達式匹配)
            if (app.Context.Request.Url.PathAndQuery.Contains("mobile/form"))
            {
                app.Context.RemapHandler(new UrlHandler());
            }
        }

        public void Dispose()
        {
        }
    }
}
View Code

2.編寫自定義Handler

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace Service
{
    internal class UrlHandler : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            HttpRequest request = context.Request;
            string result = string.Empty;
            if (!string.IsNullOrEmpty(request.Form["ID"]))
            {
                string id = request.Form["ID"];
                result = "Hello " + id;
            }
            else
            {
                result = "Hello";
            }
            context.Response.Write(result);
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}
View Code

3.Web.config配置(只需要配置httpModules節點

<httpModules>
    <add name="UrlRoutingModule" type="Service.UrlRoutingModule,Service"/>
</httpModules>

4.測試頁面

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <script src="Scripts/jquery-1.8.2.js" type="text/javascript"></script>
    <script type="text/javascript">
        function formTest() {
            $.ajax({
                type: "POST",
                url: "mobile/form",
                data: { ID: "wolf" },
                complete: function (XHR, TS) {
                    XHR = null;
                },
                success: function (msg) {
                    alert(msg);
                }
            });
        }
    </script>
</head>
<body>
    <input type="button" value="發起請求" onclick="formTest();" />
</body>
</html>
View Code

以上代碼有2點需要說明

1.PostMapRequestHandler(根據用戶請求,創建處理請求對象)事件是asp.net框架根據請求選擇Handler的事件。所以,如果想自定義選擇Handler,一定要選擇管線中在其事件之前的事件。而比較早的事件,例如:驗證用戶事件、授權事件,都讓asp.net框架幫我們處理。

2.本次在Web.config配置中,只要配置httpModule節點就可以。因為url路由是自定義選擇Handler,並不需要asp.net框架根據請求選擇對應的Handler,所以Handler節點不需要任何配置。

感謝大家的耐心閱讀。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM