UrlRewrite,Url重写,无扩展名重写

A. 最简单的改写Global.asax

    void Application_BeginRequest(Object sender, EventArgs e)
    {
        String oldUrl 
= System.Web.HttpContext.Current.Request.RawUrl;

        
//其中()最为一个整体,.+任意多个除了()以外的字符,^与字符串开始的地方匹配
        
//d+任意多个数字,w+任意多个字母或数字或下划线
        String pattern = @"^(.+)/test4/(d+).aspx/(w+)";
        String replace 
= @"~/test4.aspx?NID=$1&id=$2&uid=$3";
        
if(Regex.IsMatch(oldUrl,pattern,RegexOptions.IgnoreCase | RegexOptions.Compiled))
        {
            String newUrl
=Regex.Replace(oldUrl,pattern,replace,RegexOptions.Compiled| RegexOptions.IgnoreCase);
            Context.RewritePath(newUrl);
        }
    }

B.研究Aspx网站的UrlRewrite组件(Net2.0)

using System;

namespace UrlRewriter
{
    
/// <summary>
    
/// 实现接口IHttpModule
    
/// </summary>
    public class HttpModule:System.Web.IHttpModule
    {
        
#region "IHttpModule成员"
        
public void Dispose()
        {
            
throw new Exception("The mothod or operation is not implemented.");
        }

        
public void Init(System.Web.HttpApplication context)
        {
            
throw new Exception("The mothod or operation is not implemented.");
        }
        
#endregion
        
        
#region IHttpModule 成员
        
void  System.Web.IHttpModule.Dispose()
        {
            
throw new Exception("The method or operation is not implemented.");
        }

        
void  System.Web.IHttpModule.Init(System.Web.HttpApplication context)
        {
            context.BeginRequest 
+= new EventHandler(Module_BeginRequest);
            context.EndRequest 
+= new EventHandler(Module_EndRequest);
        }

        
void Module_EndRequest(object sender, EventArgs e)
        {
            
        }

        
void Module_BeginRequest(object sender, EventArgs e)
        {
            System.Web.HttpContext hc 
= (sender as System.Web.HttpApplication).Context;
            String url 
= hc.Request.Path.ToLower();
            url 
= RuleParser.Parse(url);
            
if (!String.IsNullOrEmpty(url))
                hc.RewritePath(url);
        }        
        
#endregion
    }

    
/// <summary>
    
/// 规则转换
    
/// </summary>
    public static class RuleParser
    {
        
private static Settings settings = System.Configuration.ConfigurationManager.GetSection("rewriter"as Settings;
        
private static System.Collections.Specialized.NameValueCollection cache = new System.Collections.Specialized.NameValueCollection(settings.maxcache);

        
public static String Parse(String url)
        {
            String k 
= Utility.Hash.md5(url);
            String s 
= CheckCache(k);
            
if (!String.IsNullOrEmpty(s))
            {
                
return s;
            }
            System.Text.RegularExpressions.Match match 
= null;
            System.Text.RegularExpressions.Regex regex 
= null;
            
foreach (Rule r in settings.rules)
            {
                regex 
= new System.Text.RegularExpressions.Regex(r.urlfor, System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.IgnorePatternWhitespace);
                match 
= regex.Match(url);
                
if (match.Success)
                {
                    System.Text.RegularExpressions.GroupCollection gc 
= match.Groups;
                    String[] ss 
= new String[gc.Count];
                    Int32 i 
= 0;
                    
foreach (System.Text.RegularExpressions.Group g in gc)
                    {
                        ss[i
++= g.Value;                        
                    }
                    s 
= String.Format(r.urlnew,ss);
                    UpdateCache(k, s);
                    
return s;
                }
            }
            
return null;
        }

        
private static String CheckCache(String key)
        {
            
if (cache[key] != null)
                
return cache[key];
            
else
                
return null;
        }

        
private static void UpdateCache(String key, String val)
        {
            
if (cache.Count >= settings.maxcache)
            {
                cache.Remove(cache.GetKey(
0));
            }
            cache.Add(key, val);
        }
    }

    
/// <summary>
    
/// 读取web.Config中<rewriter>
    
/// </summary>
    public sealed class Configuration : System.Configuration.IConfigurationSectionHandler
    {
        
public Object Create(Object parent, Object input, System.Xml.XmlNode section)
        {
            Rule r 
= new Rule();
            Settings settings 
= new Settings();
            settings.maxcache 
= Int32.Parse(section.Attributes["maxcache"].Value);
            
foreach (System.Xml.XmlNode xn in section.ChildNodes)
            {
                
if (xn.HasChildNodes)
                {
                    
//get <for> value
                    if (xn.FirstChild.HasChildNodes)
                        r.urlfor 
= xn.FirstChild.FirstChild.Value;
                    
else
                        r.urlfor 
= xn.FirstChild.Value;
                    
//get <new> value
                    if (xn.LastChild.HasChildNodes)
                        r.urlnew 
= xn.LastChild.FirstChild.Value;
                    
else
                        r.urlnew 
= xn.LastChild.Value;
                }
                settings.rules.Add(r);
            }
            
return settings;
        }
    }

    
/// <summary>
    
/// 存放Url,及其转换规则
    
/// </summary>
    public class Settings
    {
        
public Int32 maxcache=1024;
        
public System.Collections.Generic.List<Rule> rules = new System.Collections.Generic.List<Rule>();
    }

    
/// <summary>
    
/// 规则
    
/// </summary>
    public struct Rule
    {
        
public String urlfor;
        
public String urlnew;
    }
}

 

//常用工具类
namespace UrlRewriter.Utility
{
    
/// <summary>
    
/// 加密
    
/// </summary>
    public static class Hash
    {
        
public static String md5(String s)
        {
            
return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(s, "MD5").ToLower();
        }

        
public static String sha1(String s)
        {
            
return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(s, "SHA1").ToLower();
        }
}
}

 

<!--Web.Config设置-->
<configuration>
  
<!--添加策略配置节-->
  
<configSections>
    
<section name="rewriter" type="UrlRewriter.Configuration,UrlRewriter"/>
  
</configSections>
  
</connectionStrings>
<system.web>
    
<!--添加模块-->
    
<httpModules>
      
<add name="UrlRewriter" type="UrlRewriter.HttpModule,UrlRewriter" />
    
</httpModules>
    
</system.web>
  
<!--地址重写策略-->
  
<rewriter maxcache="2048">
    
<rule>
      
<for><![CDATA[/test3/(w)]]></for>
      
<new><![CDATA[~/test3.aspx?p={1}]]></new>
    
</rule>
  
</rewriter>

测试结果:
重写1
前:
http://localhost:3142/WebExample2/test3/a
后:
http://localhost:3142/WebExample2/test3.aspx?p=a

重写2
前:
http://localhost:3142/WebExample2/test3.aspx/a
后:
http://localhost:3142/WebExample2/test3.aspx?p=a

重写3
前:
http://localhost:3142/WebExample2/(\w)
后:
没有转成


C. 研究UrlRewriting.net,只需要添加Intelligencia.UrlRewriter.dll,设置Web.Config即可。

<configuration>
  
<configSections>
    
<section name="rewriter" requirePermission="false" type="Intelligencia.UrlRewriter.Configuration.RewriterConfigurationSectionHandler,Intelligencia.UrlRewriter"/>
  
</configSections>
    
<system.web>
    
<httpModules>
      
<add name="UrlRewriter" type="Intelligencia.UrlRewriter.RewriterHttpModule,Intelligencia.UrlRewriter"/>
  
</httpModules>
    
</system.web>
  
<rewriter>
    
<rewrite url="~/product/(.+).aspx" to="~/product.aspx?category=$1"/>
  
</rewriter>
</configuration>

D.UrlReWrite(Url重写或伪静态),发现ActionlessForm.dll没什么用(访微软组件所写):

//读取Web.Config中设置
using System;

namespace UrlRewriter.Config
{
    
// Define a custom section containing a simple element and a collection of the same element.
    
// It uses two custom types: UrlsCollection and UrlsConfigElement.
    class UrlsConfig
    {
        
public static UrlsSection GetConfig()
        {
            
return (UrlsSection)System.Configuration.ConfigurationManager.GetSection("CustomConfiguration");
        }
    }

    
public class UrlsSection:System.Configuration.ConfigurationSection
    {
        [System.Configuration.ConfigurationProperty(
"urls",IsDefaultCollection=false)]
        
public UrlsCollection Urls
        {
            
get
            {
                
return (UrlsCollection)this["urls"];
            }
        }
    }

    
// Define the UrlsCollection that contains UrlsConfigElement elements.
    public class UrlsCollection:System.Configuration.ConfigurationElementCollection
    {
        
protected override System.Configuration.ConfigurationElement CreateNewElement()
        {
            
return new UrlConfigElement();
        }

        
protected override object GetElementKey(System.Configuration.ConfigurationElement element)
        {
            
return ((UrlConfigElement)element).VirtualUrl;
        }

        
public UrlConfigElement this[Int32 index]
        {
            
get
            {
                
return (UrlConfigElement)BaseGet(index);
            }
        }
    }

    
// Define the UrlConfigElement.
    public class UrlConfigElement : System.Configuration.ConfigurationElement
    {
        [System.Configuration.ConfigurationProperty(
"virtualUrl",IsRequired=true)]
        
public String VirtualUrl
        {
            
get
            {
                
return (String)this["virtualUrl"];
            }
            
set
            {
                
this["virtualUrl"]=value;
            }
        }

        [System.Configuration.ConfigurationProperty(
"destinationUrl",IsRequired=true)]
        
public String DestinationUrl
        {
            
get
            {
                
return (String)this["destinationUrl"];
            }
            
set
            {
                
this["destinationUrl"= value;
            }
        }
    }
}

 

//实现接口
using System;

namespace UrlRewriter
{
    
public class RewriterModule : System.Web.IHttpModule
    {
        
public void Dispose()
        {
        }

        
public void Init(System.Web.HttpApplication context)
        {
            
// WARNING!  This does not work with Windows authentication!
            
// If you are using Windows authentication, change to app.BeginRequest
            context.AuthorizeRequest += new EventHandler(URLRewriter);
        }

        
protected void URLRewriter(Object sender, EventArgs e)
        {
            System.Web.HttpApplication app 
=(System.Web.HttpApplication)sender;
            String requestedPath 
= app.Request.Path;

            
// get the configuration rules
            UrlRewriter_1.Config.UrlsCollection rules = UrlRewriter.Config.UrlsConfig.GetConfig().Urls;
            
for (Int32 i = 0; i < rules.Count; i++)
            {
                
// get the pattern to look for, and Resolve the Url (convert ~ into the appropriate directory)
                String lookFor = "^" + RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, rules[i].VirtualUrl) + "$";
                System.Text.RegularExpressions.Regex re
=new System.Text.RegularExpressions.Regex(lookFor,System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                
if(re.IsMatch(requestedPath))
                {
                    String sendToUrl
=RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath,re.Replace(requestedPath,rules[i].DestinationUrl));
                    RewriterUtils.RewriteUrl(app.Context,sendToUrl);
                    
break;
                }
            }
        }
    }

    
/// <summary>
    
/// Provides utility helper methods for the rewriting HttpModule and HttpHandler.
    
/// </summary>
    
/// <remarks>This class is marked as internal, meaning only classes in the same assembly will be able to access its methods.</remarks>
    internal class RewriterUtils
    {
        
internal static void RewriteUrl(System.Web.HttpContext context, String sendToUrl)
        {
            String x, y;
            RewriteUrl(context, sendToUrl,
out x,out y);
        }

        
internal static void RewriteUrl(System.Web.HttpContext context, String sendToUrl, out String sendToUrlLessQString, out String filePath)
        {
            
// see if we need to add any extra querystring information
            if (context.Request.QueryString.Count > 0)
            {
                
if(sendToUrl.IndexOf('?')!=-1)
                    sendToUrl
+="&"+context.Request.QueryString.ToString();
                
else
                    sendToUrl
+="?"+context.Request.QueryString.ToString();
            }
            
// first strip the querystring, if any
            String queryString = String.Empty;
            sendToUrlLessQString 
= sendToUrl;
            
if (sendToUrl.IndexOf("?"> 0)
            {
                sendToUrlLessQString
=sendToUrl.Substring(0,sendToUrl.IndexOf("?"));
                queryString 
= sendToUrl.Substring(sendToUrl.IndexOf("?"+ 1);
            }
            
// grab the file's physical path
            filePath = String.Empty;
            filePath 
= context.Server.MapPath(sendToUrlLessQString);
            
// rewrite the path...
            context.RewritePath(sendToUrlLessQString, String.Empty, queryString);
        }

        
/// <summary>
        
/// Converts a URL into one that is usable on the requesting client.
        
/// </summary>
        
/// <remarks>Converts ~ to the requesting application path.  Mimics the behavior of the 
        
/// <b>Control.ResolveUrl()</b> method, which is often used by control developers.</remarks>
        
/// <param name="appPath">The application path.</param>
        
/// <param name="url">The URL, which might contain ~.</param>
        
/// <returns>A resolved URL.  If the input parameter <b>url</b> contains ~, it is replaced with the
        
/// value of the <b>appPath</b> parameter.</returns>
        internal static String ResolveUrl(String appPath, String url)
        {
            
// there is no ~ in the first character position, just return the url
            if (url.Length == 0 || url[0!= '~')
                
return url;
            
else
            {
                
// there is just the ~ in the URL, return the appPath
                if (url.Length == 1)
                    
return appPath;
                
if (url[1== '/' || url[1== '\')
                {
                    
// url looks like ~/ or ~
                    if (appPath.Length > 1)
                        
return appPath + "/" + url.ToString();
                    
else
                        
return "/" + url.Substring(2);
                }
                
else
                {
                    
// url looks like ~something
                    if (appPath.Length > 1)
                        
return appPath + "/" + url.Substring(1);
                    
else
                        
return appPath + url.Substring(1);
                }
            }
        }
    }
}

总结:还有提到很多的无扩展名重写,上面的使用HttpModule实现URL重写, 利用ASP.NET提供的HttpContext.RewritePath方法。这个方法允许开发人员动态地重写收到的URL的处理路径,然后让ASP.NET使用刚重写过后的路径来继续执行请求。

其中的UrlRewriter.Form.cs是采用另外一种方式使用Request.PathInfo 参数而不是查询字符串. 这个技术的很好的地方在于,为部署使用这个方法的ASP.NET应用,不需作任何服务器配置改动。在共享主机的环境里,这个技术也行之有效。

 

其中:UrlRewriter.Form.cs

using System;

namespace UrlRewriter_1.Form
{
    
public class FormRewriterControlAdapter:System.Web.UI.Adapters.ControlAdapter
    {
        
protected override void Render(System.Web.UI.HtmlTextWriter writer)
        {
            
base.Render(writer);
        }
    }

    
public class RewriteFormHtmlTextWriter:System.Web.UI.HtmlTextWriter
    {
        
public RewriteFormHtmlTextWriter(System.Web.UI.HtmlTextWriter writer):base(writer)
        {
            
base.InnerWriter = writer.InnerWriter;
        }

        
public RewriteFormHtmlTextWriter(System.IO.TextWriter writer):base(writer)
        {
            
base.InnerWriter = writer;
        }

        
public override void WriteAttribute(string name, string value, bool fEncode)
        {
            
//If the attribute we are writing is the "action" attribute, and we are not on a sub-control, 
            
//then replace the value to write with the raw URL of the request - which ensures that we'll
            
//preserve the PathInfo value on postback scenarios
            if (name == "action")
            {
                System.Web.HttpContext Context 
= System.Web.HttpContext.Current;
                
if (Context.Items[""== null)
                {
                    
//We will use the Request.RawUrl property within ASP.NET to retrieve the origional 
                    
//URL before it was re-written.
                    value = Context.Request.RawUrl;
                    
//Indicate that we've already rewritten the <form>'s action attribute to prevent
                    
//us from rewriting a sub-control under the <form> control
                    Context.Items["ActionAlreadyWritten"= true;
                }
            }
            
base.WriteAttribute(name, value, fEncode);
        }
    }
}

它需要使用还要添加App_Browers

Form.browser

<!--
可在 
<windir>Microsoft.NETFramework<ver>CONFIGBrowsers 中找到现有的浏览器定义
-->
<browsers>
    
<browser refID="Default">
      
<controlAdapters>
        
<adapter controlType="System.Web.UI.HtmlControls.HtmlForm"
                 adapterType
="FormRewriterControlAdapter" />
      
</controlAdapters>
    
</browser>
</browsers>

参考文献:http://blog.joycode.com/scottgu/archive/2007/03/01/94004.aspx

参考文献:微软组件。
posted @ 2007-07-20 11:05  nyzfl  阅读(16811)  评论(6编辑  收藏  举报