为了向用户提供友好的URL需要对URL进行重写,比如有一个应用被多个用户使用,象这样的URL:http://www.***.com/serverpage.aspx?UserID=***
对用户来说这样的URL看上去是不友好的,如果用户想直接查看属于他的应用,这样的URL是不好接受的,参考了一些资料,我对URL重写进行了简单
了实现。
URL重写:
1:通过ISAPI,这种方式是用c/c++与IIS交互,实现起来相对麻烦一些。
2:使用asp.net,有两种方式:1-使用HttpModule,2-使用HttpHandle,这里用前者。
有asp.net,对URL重写就不想以前的asp那么麻烦,不需要你重起IIS,也不用ISAPI与IIS底层交互。
我在我的本地机器上访问http://UrlRewrite/test.aspx?UserID=goodbaby,现在的目的是要把他变成http://localhost/Urlwrite/goodbaby,这里的
UrlRewrite是我的虚拟目录。
好了首先写一个继承至IHttpModule的类:
public class HttpModuleUR:IHttpModule
{
public HttpModuleUR()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
public virtual void Init(HttpApplication app)
{
//Trace.Write("Module is invoked");
app.AuthorizeRequest += new EventHandler(this.ModuleRewriterForAuthorizeRequest);
}
public void Dispose()
{
}
protected virtual void ModuleRewriterForAuthorizeRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication) sender;
Rewrite(app.Request.Path, app);
}
protected void Rewrite(string path, HttpApplication app)
{
Trace.Write("hello Rewrite Path");
//app.Context.RewritePath("~/test.aspx");
Rule[] rules=UrlRewriteConfig.Instance().Rules;
// app.Context.RewritePath( rules[0].Instead);
for(int i=0;i<rules.Length;i++)
{
Regex re = new Regex(rules[i].Pattern, RegexOptions.IgnoreCase);
if(re.IsMatch(path))
{
app.Context.RewritePath(Regex.Replace(path,rules[i].Pattern,rules[i].Instead));
break;
}
}
}
}
这个类将完成URL重写,使用这个类在asp.net管道模型中截取,这里是基于表单的身份验证,那么最佳的截取位置是在AuthorizeRequest事件中,这
里一个关键的操作:RewritePath()应用上下文的这个方法完成URL重写,UrlRewriteConfig类用来保存配置信息,他从my.config中反序列化这个xml
文档,从Rules属性中获取要规则集,规则Rule有两个属性Pattern,Instead,分别代表匹配模式,和替换模式,如果虚拟路径匹配Pattern那么就用Instead
替换路径,这是真正可用URL重写的模式。UrlRewriteConfig的实现是这样的:
[Serializable]
public class UrlRewriteConfig
{
public UrlRewriteConfig()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
private UrlRewriteConfig urc=null;
public static UrlRewriteConfig Instance()
{
return (UrlRewriteConfig)LoadXmlSerializedObject(typeof(UrlRewriteConfig),System.Web.HttpContext.Current.Server.MapPath("~/my.Config"));
}
public static object LoadXmlSerializedObject(Type type, string filepath)
{
FileStream filestream=null;
try
{
filestream=new FileStream(filepath,FileMode.Open,FileAccess.Read);
XmlSerializer xms=new XmlSerializer(type);
return xms.Deserialize(filestream);
}
catch(Exception e)
{
throw e;
}
finally
{
if(filestream!=null)
filestream.Close();
}
}
private Rule[] _Rules;
[XmlArray("Rules")]
public Rule[] Rules
{
get
{
return _Rules;
}
set
{
_Rules=value;
}
}
}
Rule同样是一个可序列化的对象:
public class Rule
{
public Rule()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
private string _pattern;
[XmlElement]
public string Pattern
{
get {return this._pattern;}
set {this._pattern = value;}
}
private string _Instead;
[XmlElement]
public string Instead
{
get {return this._Instead;}
set {this._Instead = value;}
}
}
配置文件存储了规则:
<?xml version="1.0" encoding="utf-8" ?>
<UrlRewriteConfig>
<Rules>
<Rule>
<Pattern>/AspNetForums/([a-zA-Z]+)</Pattern>
<Instead>test.aspx?UserID=$1</Instead>
</Rule>
</Rules>
</UrlRewriteConfig>
接下来还需要在web.config里加上
<httpModules>
<add type="UrlRewriteHttpModule.HttpModuleUR,UrlRewriteHttpModule" name="gdpz"/>
</httpModules>
把UrlRewriteHttpModule编译后放到bin/gac,见一个test.aspx好了ok.
不过这里还要处理回传,需要重写form类,不然回传后的页面仍然是test.aspx,原因是重写后
的Url会付值到Request中,那么用的浏览器仍然会是不友好的URL,同时URL的改变会使用户不安,
所以需要重写系统表单类的RenderAttrubute使他不要修改属性。
处理了回传,但是并没有实际goodbaby目录,一个办法是建立一个,但是想象一个拥有很多用户的
站点都建立一个目录,那是很dirty的,所以要使用虚拟多用户,通过架空IIS,在IIS中添加对*扩展
名的映射这样就把处理都交给了asp.net,不然会出现http 404错误,好了就这样吧。入门学习,请大家讨论指正。
参考文献: www.microsoft.com/china/libruray/webservice/asp.net/urlrewrite.aspx
浙公网安备 33010602011771号