zoukankan      html  css  js  c++  java
  • 在ASP.NET 2.0中实现URL重写

    URL重写技术在今天已不是什么新鲜的话题了,在Apache服务器提供了名为mod_rewrite的URL重写模块,而在IIS服务器上,也有很多商业的ISAPI 筛选器模块可供使用。然而这对于我们,没有很多的资金或使用的共享服务器,使得以上的方法都不是最佳的解决方案。幸而ASP.NET给我们提供了强大的可扩展性,能让我们自己定义页面的访问规则,很方便实现URL重写。

    在ASP.NET中实现URL重写,需要创建HTTP模块(HttpModule)或HTTP处理程序(HttpHandler),通过调用HttpContext的RewritePath方法来近进行URL重写。本篇文章使用的是HTTP模块做的示例。

    使用HTTP模块执行URL重写

    首先需要定义一个实现了IHttpModule接口的类。IHttpModule接口定义了两个方法需要实现:

    • Init(HttpApplication)。此方法在初始化HTTP模块后触发。在此方法中,您将把事件处理程序绑定到相应的HttpApplication事件。
    • Dispose()。当请求已完成并已发送回IIS时调用此方法。您应当在此处执行所有最终的清除操作。
    C#代码
    1. public virtual void Init(HttpApplication app)   
    2. {   
    3.     // WARNING!  This does not work with Windows authentication!   
    4.     // If you are using Windows authentication, change to app.BeginRequest   
    5.     app.AuthorizeRequest += new EventHandler(this.URLRewriter);   
    6. }  

    注意如果要使用窗体身份验证而不使用Windows身份验证,请将URL重写放在AuthorizeRequest事件处理程序中执行。如果要使用Windows身份验证,请在BeginRequest或AuthenticateRequest事件进行过程中安排URL重写。

    在URLRewriter方法里的第7行从配置文件里读取URL重写信息,进行处理,如对正则表达式的处理。如您对如何扩展标准的配置文件还不清楚,请看这篇Blog:扩展.NET 2.0标准配置文件

    C#代码
    1. protected void URLRewriter(object sender, EventArgs e)   
    2. {   
    3.     HttpApplication app = (HttpApplication)sender;   
    4.     string requestedPath = app.Request.Path;   
    5.     // get the configuration rules   
    6.     UrlsCollection rules = UrlsConfig.GetConfig().Urls;   
    7.     for (int i = 0; i < rules.Count; i++)   
    8.     {   
    9.         // get the pattern to look for, and Resolve the Url (convert ~ into the appropriate directory)   
    10.         string lookFor = "^" + RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, rules[i].VirtualUrl) + "$";   
    11.         Regex re = new Regex(lookFor, RegexOptions.IgnoreCase);   
    12.         if (re.IsMatch(requestedPath))   
    13.         {   
    14.             string sendToUrl = RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, re.Replace(requestedPath, rules[i].DestinationUrl));   
    15.             RewriterUtils.RewriteUrl(app.Context, sendToUrl);   
    16.             break;   
    17.         }   
    18.     }   
    19. }  

    如果匹配,则调用RewriteUrl方法,将URL分解成路径和查询字符串两部分,以调用HttpContext.RewritePath方法来实现URL的重写。其中对“URL资源的附加路径信息”(如:Http://www.microsoft.com/virdir/page.html/tail 的tail部分)未做处理,直接用String.Empty来表示,如您需要,可以自行扩展一下。

    OK,到此为止,一个简单的URL重写程序就初步完成了,但还没有大功告成,还有一个细节的问题需要我们处理一下,就是页面回发后又会在地址栏显示出重写前的地址,也就是真实的地址,影响美观:)。有两种方法可以解决这个问题:

    • 自定义一个继承form控件的控件

     

    C#代码
    1. public class Form : System.Web.UI.HtmlControls.HtmlForm   
    2. {   
    3.     /// <summary>   
    4.     /// The RenderAttributes method adds the attributes to the rendered <form> tag   
    5.     /// We override this method so that the action attribute is not emitted.   
    6.     /// </summary>   
    7.     protected override void RenderAttributes(HtmlTextWriter writer)   
    8.     {   
    9.         // write the form's name   
    10.         writer.WriteAttribute("name"this.Name);   
    11.         base.Attributes.Remove("name");   
    12.   
    13.         // write the form's method   
    14.         writer.WriteAttribute("method"this.Method);   
    15.         base.Attributes.Remove("method");   
    16.   
    17.         // remove the action attribute   
    18.         base.Attributes.Remove("action");   
    19.   
    20.         // finally write all other attributes   
    21.         this.Attributes.Render(writer);   
    22.   
    23.         if (base.ID != null)   
    24.             writer.WriteAttribute("id"base.ClientID);   
    25.     }   
    26. }  

     

    这个方法直接去掉了form的action属性,所以页面就直接回发给自己了,能够解决问题,但使用起来比较麻烦。想象一下在每个需要重写URL的页面都要去改写form标记,够崩溃的了。

    • 利用ASP.NET 2.0控件适配器扩展架构来定制控件的输出

    在ASP.NET 2.0中,有个比较干净的诀窍可以用来重写<form>控件的action属性。具体地来说,利用新的ASP.NET 2.0控件适配器扩展架构来定制控件的输出,用提供的值来覆盖action属性的值。这不要求在.aspx页面里做任何编码改动,而只要在/app_browsers文件夹里添加一个.browser文件,注册使用一个控件适配类即可输出新的action属性。

    .browser文件 

    XML/HTML代码
    1. <browsers>  
    2.   <browser refID="Default">  
    3.     <controlAdapters>  
    4.       <adapter controlType="System.Web.UI.HtmlControls.HtmlForm"  
    5.           adapterType="URLRewriter.Form.FormRewriterControlAdapter" />  
    6.     </controlAdapters>  
    7.   </browser>  
    8. </browsers>  

    URLRewriter.Form.cs文件

     

    C#代码
    1. public class FormRewriterControlAdapter : System.Web.UI.Adapters.ControlAdapter   
    2.    {   
    3.        public FormRewriterControlAdapter()   
    4.        {   
    5.        }   
    6.        protected override void Render(HtmlTextWriter writer)   
    7.        {   
    8.            base.Render(new RewriteFormHtmlTextWriter(writer));   
    9.        }   
    10.    }   
    11.    public class RewriteFormHtmlTextWriter : HtmlTextWriter   
    12.    {   
    13.        public RewriteFormHtmlTextWriter(HtmlTextWriter writer)   
    14.            : base(writer)   
    15.        {   
    16.            base.InnerWriter = writer.InnerWriter;   
    17.        }   
    18.        public RewriteFormHtmlTextWriter(System.IO.TextWriter writer)   
    19.            : base(writer)   
    20.        {   
    21.            base.InnerWriter = writer;   
    22.        }   
    23.        public override void WriteAttribute(string name, string value, bool fEncode)   
    24.        {   
    25.            //If the attribute we are writing is the "action" attribute, and we are not on a sub-control   
    26.            //then replace the value to write with the raw URL of the request - which ensures that we'll   
    27.            //preserve the PathInfo value on postback scenarios   
    28.            if (name == "action")   
    29.            {   
    30.                HttpContext context = HttpContext.Current;   
    31.                if (context.Items["ActionAlreadyWritten"] == null)   
    32.                {   
    33.                    //We will use the Request.RawUrl property within ASP.NET to retrieve the origional   
    34.                    //URL before it was re-written.   
    35.                    value = context.Request.RawUrl;   
    36.                    //Indicate that we've already rewritten the <form>'s action attribute to prevent   
    37.                    //us from rewriting a sub-control under the <form> control   
    38.                    context.Items["ActionAlreadyWritten"] = true;   
    39.                }   
    40.            }   
    41.            base.WriteAttribute(name, value, fEncode);   
    42.        }   
    43.    }  

    直接将action属性的值赋予成URL重写后的地址,简单又实惠,何乐而不为呢。

    作者:superstone

    原文地址:http://www.51aspx.com/CT/Z9UMK7ZUJXE31/

  • 相关阅读:
    Mysql登录错误:ERROR 1045 (28000): Plugin caching_sha2_password could not be loaded
    Docker配置LNMP环境
    Docker安装mysqli扩展和gd扩展
    Docker常用命令
    Ubuntu常用命令
    单例模式的优缺点和使用场景
    ABP 多租户数据共享
    ABP Core 后台Angular+Ng-Zorro 图片上传
    ERROR Error: If ngModel is used within a form tag, either the name attribute must be set or the form control must be defined as 'standalone' in ngModelOptions.
    AbpCore 执行迁移文件生成数据库报错 Could not find root folder of the web project!
  • 原文地址:https://www.cnblogs.com/yamajia/p/1171032.html
Copyright © 2011-2022 走看看