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节点不须要任何配置。

感谢你们的耐心阅读。

相关文章
相关标签/搜索