• 基于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"/>

    希望对你有用.

     代码下载

    点击这里下载

  • 相关阅读:
    【原创】μC/OS Ⅱ工程中MAKETEST.BAT文件的改进与优化
    网络号和主机号等的分析和计算
    QQ电脑管家加速升级版便携版
    ARM发展历史
    μC/OS Ⅱ之任务就绪表的操作_2012.5.31
    删除word中的多余空行
    μC/OS II安装调试指南(带图解说明)
    WPF简单的User Control
    How to Databind SelectedItems of the ListPicker and RecurringDaysPicker
    数组排序
  • 原文地址:https://www.cnblogs.com/scy251147/p/3095124.html
Copyright © 2020-2023  润新知