zoukankan      html  css  js  c++  java
  • 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节点不需要任何配置。

    感谢大家的耐心阅读。

  • 相关阅读:
    【转】winrar命令行详解
    【转】关于色彩空间sRGB和Adobe RGB...
    深入解读TPC-C指标
    解决因 RsFX devicer 而无法卸载 SQL Server 的问题
    LUHN算法
    信用卡卡号编排的含义
    关于第三方API调用的工具 WebApiClient.JIT 的使用记录
    ocelot.json模板
    C#进阶之事件与委托(Event&Delegate)
    C#进阶之面向对象(OOP)
  • 原文地址:https://www.cnblogs.com/color-wolf/p/3664391.html
Copyright © 2011-2022 走看看