URL重寫與URL路由

要介紹這兩個內容,必需要從ASP.NET管線提及。javascript

ASP.NET管線

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

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

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

從上面的圖中,咱們能夠看出ajax

1.請求先交給HttpModule處理,而後由HttpModule交給HttpHandler,最後再由HttpHandler交回給HttpModule,由HttpModule結束請求。正則表達式

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

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

第二張圖,主要說明:管線中全部事件的意義app

 

注意:這是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節點不須要任何配置。

感謝你們的耐心閱讀。

相關文章
相關標籤/搜索