看了网上不少和URLRewrite相关的技术文章,提供的解决方案不少,下面我结合相关技术文献,通过实例简单的说下个人在程序中应用URLRewrite的方法:
一、将.html映射为.aspx
二、将
实现方法:
应用IIS进行配置(IIS5.0):
在IIS中找到应用程序站点或程序对应的虚拟目录,右击/属性/目录/应用程序配置/配置/应用程序映射选项/,然后选择添加映射,在可执行文件框中浏览aspnet_isapi.dll文件(一般为C:\WINNT\Microsoft.NET\Framework\v1.1.4322\aspnet_isapi.dll),扩展名输入.*(如果针对.html的可直接输入单个扩展即可),动作设为“POST,GET”(为减少不必要的资源耗费,不用设置为全部动作),其他的默认即可。之所以这样做,是要把请求判断权交给ASPNET处理,而不是IIS,所以这个映射是必要的。完成这里的操作后,继续……
由于用户请求连接时Application_BeginRequest()函数会被触发,所以只需要在这里判断客户端提交的请求就可以了,这就正是上面将IIS筛选权给ASPNET的原因所在。
方法一、直接判断请求参数信息
string strNewUrl;
if (Regex.IsMatch(strRawUrl, @"(w+).html", RegexOptions.IgnoreCase))
{
strNewUrl = Regex.Replace(strRawUrl, @"(w+).html", @"$1.aspx", RegexOptions.IgnoreCase);
HttpContext.Current.RewritePath( strNewUrl );
}
else if (Regex.IsMatch(strRawUrl, @"(d{4})/(d{1,2})/(d{1,2})(/?)", RegexOptions.IgnoreCase))
{
strNewUrl = Regex.Replace(strRawUrl, @"(d{4})/(d{1,2})/(d{2})(/*)", @"default.aspx?log_Year=$1&log_Month=$2&log_Day=$3",RegexOptions.IgnoreCase);
HttpContext.Current.RewritePath( strNewUrl );//路径显示不变 但执行的是正确的路径
}
//处理图片、样式表路径
if (Regex.IsMatch(strRawUrl, @"(d{4})/(d{1,2})/(d{1,2})(/?)([images|styles]+)/(.+)", RegexOptions.IgnoreCase))
{
strNewUrl = Regex.Replace(strRawUrl, @"(d{4})/(d{1,2})/(d{1,2})(/?)([images|styles]+)/(.+)", @"$5/$6",RegexOptions.IgnoreCase);
HttpContext.Current.RewritePath( strNewUrl );
}
//验证码页面
if (Regex.IsMatch(strRawUrl, @"(d{4})/(d{1,2})/(d{1,2})(/?)checkcode.aspx", RegexOptions.IgnoreCase))
{
strNewUrl = Regex.Replace(strRawUrl, @"(d{4})/(d{1,2})/(d{1,2})(/?)checkcode.aspx", @"checkcode.aspx",RegexOptions.IgnoreCase);
HttpContext.Current.RewritePath( strNewUrl );
}
//其他所有页面同样处理
if (Regex.IsMatch(strRawUrl, @"(d{4})/(d{1,2})/(d{1,2})(/?)(w+).aspx", RegexOptions.IgnoreCase))
{
strNewUrl = Regex.Replace(strRawUrl, @"(d{4})/(d{1,2})/(d{1,2})(/?)(w+).aspx", @"$5.aspx",RegexOptions.IgnoreCase);
HttpContext.Current.RewritePath( strNewUrl );
}
上面的代码很简单,对于正则表达式的应用也比较简单,我就不详述了。同样的方式,通过正则,可改为任何你需要的访问方式,无需DLL支持,
方法二、通过配置文件来完成,当然你也可以放到默认的站点配置文件中,这里我是放到单独的config文件里,格式如下:
仍然在在Application_BeginRequest()中完成。代码如下:
<RewriterConfig>
<Rules>
<RewriterRule><!--基本的静态页面访问 -->
<LookFor>(w+).html</LookFor>
<SendTo>$1.aspx</SendTo>
</RewriterRule>
<RewriterRule><!--2006/6/19的格式访问-->
<LookFor>(d{4})/(d{1,2})/(d{1,2})(/?)</LookFor>
<SendTo>default.aspx?log_Year=$1&log_Month=$2&log_Day=$3</SendTo>
</RewriterRule>
<RewriterRule><!--重写图片和样式表路径-->
<LookFor>(d{4})/(d{1,2})/(d{1,2})(/?)([images|styles]+)/(.+)</LookFor>
<SendTo>$5/$6</SendTo>
</RewriterRule>
<RewriterRule><!--重写验证码路径-->
<LookFor>(d{4})/(d{1,2})/(d{1,2})(/?)checkcode.aspx</LookFor>
<SendTo>checkcode.aspx</SendTo>
</RewriterRule>
<RewriterRule><!--重写通过2006/6/19格式访问后的 2006/6/19/blogview.aspx?logID=……等-->
<LookFor>(d{4})/(d{1,2})/(d{1,2})(/?)(w+).aspx</LookFor>
<SendTo>$5.aspx</SendTo>
</RewriterRule>
</Rules>
</RewriterConfig>
上面主要完成配置文件的读写和操作,该程序部分来自网上,不过运行时时总是有错误,达不到预期的效果,我修改了部分代码,实现如上,IIS5.0+ASP.NET1.1测试通过。
当然,方法还不止这些,还可以通过自定义错误的页面来完成,方法如下:
<customErrors defaultRedirect="404.aspx" mode="On" />
在404页面里进行判断(前提和上面同,需要交给ASPNET处理),当然启用该项,如果上面没有匹配到合适的串,将会交给404.aspx处理。同样global中异常信息也可以提交过来。
string strNewUrl;
if (Regex.IsMatch(strRawUrl, @"(w+).html", RegexOptions.IgnoreCase))
{
//避免多重目录访问 strNewUrl=Regex.Replace(Request.RawUrl.ToString(),@"(.*)404(.+)/(w+).html",@"$1$3.aspx",RegexOptions.IgnoreCase); //strNewUrl=Regex.Replace(Request.RawUrl.ToString(),@"(.+)[=](.+)(w+).html",@"$2$3.aspx",RegexOptions.IgnoreCase);
//Response.Write(strNewUrl);
Response.Redirect(strNewUrl);
}
else if (Regex.IsMatch(strRawUrl, @"(d{4})/(d{1,2})/(d{1,2})(/?)", RegexOptions.IgnoreCase))
{
strNewUrl = Regex.Replace(strRawUrl, @"(.+)[=](.+)(d{4})/(d{1,2})/(d{1,2})(/*)", @"default.aspx?log_Year=$3&log_Month=$4&log_Day=$5");
Response.Redirect(strNewUrl);
}
string errMessage="你看到这个页面<br>肯定是什么地方出错了<br>人难免会犯错<br>机器亦然<br>如果你没有搞错地址<br><font color=red>多半是文件不存在或已被删除<br>请确认正确的“连接地址”后再尝试</font>";
if(Session["Error"]==null) //接收Global中的应用程序异常信息
errMessage+="<br><br><br><font color=red><b>出现错误,已写入事件日志</b></font>";
else
errMessage+="<br><br><br><font color=red><b>"+Session["Error"].ToString()+"</b></font>"; errMessage+="<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>";
errMessage+="<div align=center><script language=JavaScript src=http://www1.itsun.com/counter.php?uuid=1553318&style=icon></script></div><br><p align=center><font size=2><b>10秒后转入主页,稍候……</b></font></p>";
Response.Write(errMessage);
补充:在Global中捕获程序异常
上面同样的完成处理,不过地址栏显示的地址将不会变动,似乎有一点影响,所以我不打算用这个,不过做为一种思路还是可以考虑的 :),
Exception objErr = Server.GetLastError().GetBaseException();
//Exception objErr = Server.GetLastError().Message;
string err ="Error Caught in Application_Error event " +
"Error in:" + Request.Url.ToString() +
" Error Message:"+ objErr.Message.ToString() +
" Stack Trace:"+ objErr.StackTrace.ToString();
EventLog.WriteEntry("W_Blog",err,EventLogEntryType.Error); //写入日志
//Server.ClearError(); //不清除 留给customerror处理 友好
HttpContext.Current.Session["Error"]=err;
Server.Transfer("404.aspx"); //404.aspx是所有错误与定向处理的页面
//Redirect会导致postback产生而丟失错误信息,所以直接在服务器端执行
另外,通过MS的DLL来实现,注册、重写规则、……我这里就没不说了,
当然,通过以下方式也可实现:
<httpHandlers>
<add verb="*" path="*.aspx" type="MyHandler.NewHandler,MyHandler"/>
</httpHandlers>
将其交给继承IHttpHandler接口的类来处理,大家可参考下MS的附加代码实现。