A. 最简单的改写Global.asax:B.研究Aspx网站的UrlRewrite组件(Net2.0):
{
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);
}
}
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();
}
}
}
< 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即可。
< 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 >
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
它需要使用还要添加App_Browers
Form.browser
参考文献:http://blog.joycode.com/scottgu/archive/2007/03/01/94004.aspx
参考文献:微软组件。
可在 < windir > Microsoft.NETFramework < ver > CONFIGBrowsers 中找到现有的浏览器定义
-->
< browsers >
< browser refID = " Default " >
< controlAdapters >
< adapter controlType = " System.Web.UI.HtmlControls.HtmlForm "
adapterType = " FormRewriterControlAdapter " />
</ controlAdapters >
</ browser >
</ browsers >
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);
}
}
}