zoukankan      html  css  js  c++  java
  • 基于PageHandlerFactory的路径重写

    现在在.net中,我们有很多方法可以实现路径的重写,不论是外部插件还是代码控制,总归是为了让URL对外更加的短小,易懂并且不包含敏感信息.

    所以,在这里,我主要介绍如何利用PageHandlerFactory类来拦截URL请求并且进行重写的.

    这里类是所有的aspx页面请求的默认父类对象,页面的任何请求都可以被其捕获,我们可以通过重写其中的getHandler方法来实现自我控制.

    功能需求

    不过,在开始写之前,我们先看看我们需要用到什么功能.

    1. URL重写需要支持GET, POST请求方式.
    2. URL重写需要支持实时的DEBUG功能,也就是能够跳转到重新定向的页面进行调试.

    代码构建

    基于这两点(其实这两点在开发过程中也是很重要的两点),我们构建如下的代码页:

    using System.Web;
    using System.Web.UI;
    using System.Web.SessionState;
    using System;
    
    namespace AsyncFactoryWEB
    {
        public class RewriterFactory : PageHandlerFactory,IReadOnlySessionState
        {
            private bool flag = true;
    
            public override IHttpHandler GetHandler(HttpContext context, string requestType, string virtualPath, string path)
            {
                string[] urlSegments = context.Request.Url.Segments; //获取URL片段
                int urlLen = urlSegments.Length;  //获取URL的片段长度
                if (urlLen <= 1) //当前请求为根目录页面,则不进行处理
                    flag = false;
                else  //当前请求不是根目录页面,进行处理
                    flag = true;
    
                if (flag)
                {
                    string conceratePath = ((char)RewriteSettings.splitter.slash).ToString(); 
    
                    string slashChar = ((char)RewriteSettings.splitter.slash).ToString(); // /斜线
                    string equalChar = ((char)RewriteSettings.splitter.equal).ToString(); // =等号
                    string andChar   = ((char)RewriteSettings.splitter.and  ).ToString(); // &符号
                    string extension = ((char)RewriteSettings.splitter.dot  ).ToString().Combine(RewriteSettings.fileExtension.aspx.ToString());  // .aspx后缀
    
                    string concerateParams=string.Empty;
                    for (int i = 0; i < urlLen; i++) 
                    {
                        string curSegment = urlSegments[i];
    
                        if (curSegment.LastIndexOf(slashChar) >= 0)  //如果检测片段中带有左斜线
                            curSegment = curSegment.Substring(0, curSegment.Length - 1); //将斜线去掉
    
                        if (!string.IsNullOrEmpty(curSegment)) 
                        {
                            if (curSegment.Contains(equalChar)) //如果带有等号,则表明应该进行 ***.aspx?id=1 类似的拼接
                            {
                                if (i == urlLen - 1)
                                    concerateParams = concerateParams.Combine(curSegment);
                                else
                                    concerateParams = concerateParams.Combine(curSegment.Combine(andChar));
                            }
                            else if (!curSegment.EndsWith(extension)) //如果不是以.aspx结尾的
                                conceratePath = conceratePath.Combine(curSegment.Combine(extension));
                            else
                                conceratePath = conceratePath.Combine(curSegment);
                        }
                    }
    
                    string newPath = context.Server.MapPath(conceratePath); //得到物理目录
                     
                    context.RewritePath(conceratePath, string.Empty, concerateParams); //重写路径,并传入parameters
    
                    try
                    {
                        IHttpHandler iHandler = PageParser.GetCompiledPageInstance(conceratePath, newPath, context);  //重写handler对象
                        return iHandler; 
                    }
                    catch (Exception ex)
                    {
                        throw new Exception(ex.Message);
                    }
                   
                }
                else
                {
                    return base.GetHandler(context, requestType, virtualPath, path);
                }
            }
        }
    }
    View Code

    代码注释比较清楚,就是先获取URL路径,然后进行处理拼接,最后返回一个Handler对象即可.

    下面来测试以下, 在Default.aspx中,我们前台代码如下:

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="AsyncFactoryWEB._Default" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>Url Rewrite testing daemon</title>
    </head>
    <body>
        <div>Using Get method to <a href="WebForm1/type=0/partype=1/testUserName=myRobot/">redirect</a> another page.</div><br />
        <hr style="height:1px;" />
        <form id="form1"  action="WebForm1/t=1/" method="post">
        <div>Using Post method to redirect another page.</div>
        <div>
            UserName:<input type="text" name="UserName" style="border:none;border-bottom:1px solid black;"/><br />
            UserPhone:<input type="text" name="UserPhone" style="border:none;border-bottom:1px solid black;"/><br />
            <input type="submit" value="Send" /><br />
        </div>
        </form>
        <hr style="height:1px;" />
    </body>
    </html>
    View Code

    可以看出其中有两种测试方式:

    Get方式:

    <a href="WebForm1/type=0/partype=1/testUserName=myRobot/">redirect</a>

    Post方式: 

    <form id="form1"  action="WebForm1/t=1/" method="post">

    跳转页面为WebForm1.aspx,后台代码为:

    using System;
    using System.Web.UI;
    using System.Collections.Specialized;
    
    namespace AsyncFactoryWEB
    {
        public partial class WebForm1 :Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                Response.Write("-----------------Using GET Method---------------------<br/>");
                NameValueCollection queryStringCollection = Request.QueryString;
                foreach (string key in queryStringCollection.Keys)
                {
                    Response.Write(string.Format("QueryString [{0}] value : {1} ",key,queryStringCollection[key]));
                    Response.Write("<br/>");
                }
                Response.Write("-----------------Using POST Method---------------------<br/>");
                NameValueCollection formStringCollection = Request.Form;
                foreach (string key in formStringCollection.Keys)
                {
                    Response.Write(string.Format("FormString [{0}] value : {1} ", key, formStringCollection[key]));
                    Response.Write("<br/>");
                }
            }
        }
    }
    View Code

    测试结果

    当利用Get方式测试时候,我们会跳转到WebForm1.aspx, 显示结果如图:

    -----------------Using GET Method---------------------
    QueryString [type] value         : 0 
    QueryString [partype] value      : 1 
    QueryString [testUserName] value : myRobot 
    -----------------Using POST Method---------------------

    可以看到成功获取了数据.

    当利用Post方式测试的时候,我们会跳转到WebForm1.aspx,显示结果如图:

    -----------------Using GET Method---------------------
    QueryString [t] value        : 1 
    -----------------Using POST Method---------------------
    FormString [UserName] value  : 程序诗人 
    FormString [UserPhone] value : 13103993996 

    数据均能正确捕获.

    那么调试功能怎么样呢? 当我们在webForm1.aspx中打上断点的时候,由于PageHandlerFactory会捕获所有请求,所以当返回创建的Hander的时候,会调用processrequest来处理WebForm1.aspx中的方法调用,所以会进入断点.

    当然,在上述示例中,我定义的URL实在是太过于难看,你可以自定义自己的URL解析规则.

    最后,我们需要在web.config文件<httpHandlers>中加上节点配置.

     <add  verb="*" path="*" type="AsyncFactoryWEB.RewriterFactory,AsyncFactoryWEB"/>

    希望对你有用.

     代码下载

    点击这里下载

  • 相关阅读:
    GhostBSD 3.0RC3,基于GNOME的FreeBSD
    Nagios 3.4.3 发布,企业级监控系统
    Jolokia 1.0.6 发布, JMX远程访问方法
    微软希望开发人员不要使 WebKit 成为新版 IE6
    Kwort Linux 3.5 正式版发布
    EJDB 1.0.24 发布,嵌入式 JSON 数据库引擎
    Pale Moon 15.3 Firefox“苍月”优化版发布
    Galera Load Balancer 0.8.1 发布
    SmartSVN V7.5 正式发布
    PostgresQL建立索引如何避免写数据锁定
  • 原文地址:https://www.cnblogs.com/scy251147/p/3095124.html
Copyright © 2011-2022 走看看