可以看到,这样就可以通过RewriteContext.Current 集合来访问 “虚拟路径参数”了,所有的参数都被指定成了虚拟路径或页面,而不是像查询字符串那样了。
重写 URL接下来,让我们尝试重写。首先,我们要读取配置文件中的重写规则。其次,我们要检查那些在 URL 中与规则不符的部分,如果有,进行重写并以适当的页执行。
创建一个 HttpModule:
class RewriteModule : IHttpModule
{
public void Dispose() { }
public void Init(HttpApplication context)
{}
}
当我们添加 RewriteModule_BeginRequest 方法以处理不符合规则的 URL时,我们要检查给定的 URL 是否包含参数,然后调用 HttpContext.Current.RewritePath 来进行控制并给出合适的 ASP.NET 页。
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Configuration;
using System.Xml;
using System.Text.RegularExpressions;
using System.Web.UI;
using System.IO;
using System.Collections.Specialized;
namespace RewriteModule
{
class RewriteModule : IHttpModule
{
public void Dispose() { }
public void Init(HttpApplication context)
{
// it is necessary to
context.BeginRequest += new EventHandler(
RewriteModule_BeginRequest);
}
void RewriteModule_BeginRequest(object sender, EventArgs e)
{
RewriteModuleSectionHandler cfg =
(RewriteModuleSectionHandler)
ConfigurationManager.GetSection
("modulesSection/rewriteModule");
// module is turned off in web.config
if (!cfg.RewriteOn) return;
string path = HttpContext.Current.Request.Path;
// there us nothing to process
if (path.Length == 0) return;
// load rewriting rules from web.config
// and loop through rules collection until first match
XmlNode rules = cfg.XmlSection.SelectSingleNode("rewriteRules");
foreach (XmlNode xml in rules.SelectNodes("rule"))
{
try
{
Regex re = new Regex(
cfg.RewriteBase + xml.Attributes["source"].InnerText,
RegexOptions.IgnoreCase);
Match match = re.Match(path);
if (match.Success)
{
path = re.Replace(
path,
xml.Attributes["destination"].InnerText);
if (path.Length != 0)
{
// check for QueryString parameters
if(HttpContext.Current.Request.QueryString.Count != 0)
{
// if there are Query String papameters
// then append them to current path
string sign = (path.IndexOf('?') == -1) ? "?" : "&";
path = path + sign +
HttpContext.Current.Request.QueryString.ToString();
}
// new path to rewrite to
string rew = cfg.RewriteBase + path;
// save original path to HttpContext for further use
HttpContext.Current.Items.Add(
"OriginalUrl",
HttpContext.Current.Request.RawUrl);
// rewrite
HttpContext.Current.RewritePath(rew);
}
return;
}
}
catch (Exception ex)
{
throw (new Exception("Incorrect rule.", ex));
}
}
return;
}
}
}
这个方法必须注册:
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(RewriteModule_BeginRequest);
}
但这些仅仅完成了一半,因为重写模块还要处理表单的回发和虚拟路径参数集合,而这段代码中你会发现并没处理这些。让我们先把虚拟路径参数放到一边,先来正确地处理最主要的回发。