URLRewrite重写的简单应用和自定义出错页面
2006-05-25 18:02
381 查看
URLRewrite重写的简单应用和自定义出错页面
看了网上不少和URLRewrite相关的技术文章,提供的解决方案不少,下面我结合相关技术文献,通过实例简单的说下个人在程序中应用URLRewrite的方法:
一、将.html映射为.aspx
二、将2006/6/19映射为default.aspx?log_Year=2006&log_Month=6&log_Day=19
实现方法:
应用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 strRawUrl = HttpContext.Current.Request.RawUrl;
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()中完成。代码如下:
<?xml version="1.0" encoding="utf-8" ?>
<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测试通过。
第二种方法 可直接编辑规则就可以 不用每次都写#region 第二种方法 可直接编辑规则就可以 不用每次都写
try
...{
string path = Server.MapPath("~/Rewrite.config");
XPathDocument myXPathDocument = new XPathDocument(path);
XPathNavigator myXPathNavigator = myXPathDocument.CreateNavigator();
XPathNodeIterator myXPathNodeIterator = myXPathNavigator.Select("//RewriterRule");
while (myXPathNodeIterator.MoveNext())
...{
XPathNavigator nav2 = myXPathNodeIterator.Current.Clone();
string oldString = "", newString = "";
XPathNodeIterator it2 = nav2.Select("LookFor");
while (it2.MoveNext())
...{
oldString = it2.Current.Value;
break;
}
it2 = nav2.Select("SendTo");
while (it2.MoveNext())
...{
newString = it2.Current.Value;
break;
}
if (oldString != "" && newString != "")
...{
string strRawUrl = HttpContext.Current.Request.RawUrl;
string strNewUrl;
if (Regex.IsMatch(strRawUrl, oldString, RegexOptions.IgnoreCase))
...{
strNewUrl = Regex.Replace(strRawUrl, oldString, newString, RegexOptions.IgnoreCase);
HttpContext.Current.RewritePath(strNewUrl);
//return;
}
}
}
}
catch (Exception ex)
...{
HttpContext.Current.Response.Write(ex.Message);
}
#endregion
当然,方法还不止这些,还可以通过自定义错误的页面来完成,方法如下:
<customErrors defaultRedirect="404.aspx" mode="On" />
在404页面里进行判断(前提和上面同,需要交给ASPNET处理),当然启用该项,如果上面没有匹配到合适的串,将会交给404.aspx处理。同样global中异常信息也可以提交过来。
string strRawUrl = HttpContext.Current.Request.RawUrl;
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的附加代码实现。
《完》
看了网上不少和URLRewrite相关的技术文章,提供的解决方案不少,下面我结合相关技术文献,通过实例简单的说下个人在程序中应用URLRewrite的方法:
一、将.html映射为.aspx
二、将2006/6/19映射为default.aspx?log_Year=2006&log_Month=6&log_Day=19
实现方法:
应用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 strRawUrl = HttpContext.Current.Request.RawUrl;
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()中完成。代码如下:
<?xml version="1.0" encoding="utf-8" ?>
<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测试通过。
第二种方法 可直接编辑规则就可以 不用每次都写#region 第二种方法 可直接编辑规则就可以 不用每次都写
try
...{
string path = Server.MapPath("~/Rewrite.config");
XPathDocument myXPathDocument = new XPathDocument(path);
XPathNavigator myXPathNavigator = myXPathDocument.CreateNavigator();
XPathNodeIterator myXPathNodeIterator = myXPathNavigator.Select("//RewriterRule");
while (myXPathNodeIterator.MoveNext())
...{
XPathNavigator nav2 = myXPathNodeIterator.Current.Clone();
string oldString = "", newString = "";
XPathNodeIterator it2 = nav2.Select("LookFor");
while (it2.MoveNext())
...{
oldString = it2.Current.Value;
break;
}
it2 = nav2.Select("SendTo");
while (it2.MoveNext())
...{
newString = it2.Current.Value;
break;
}
if (oldString != "" && newString != "")
...{
string strRawUrl = HttpContext.Current.Request.RawUrl;
string strNewUrl;
if (Regex.IsMatch(strRawUrl, oldString, RegexOptions.IgnoreCase))
...{
strNewUrl = Regex.Replace(strRawUrl, oldString, newString, RegexOptions.IgnoreCase);
HttpContext.Current.RewritePath(strNewUrl);
//return;
}
}
}
}
catch (Exception ex)
...{
HttpContext.Current.Response.Write(ex.Message);
}
#endregion
当然,方法还不止这些,还可以通过自定义错误的页面来完成,方法如下:
<customErrors defaultRedirect="404.aspx" mode="On" />
在404页面里进行判断(前提和上面同,需要交给ASPNET处理),当然启用该项,如果上面没有匹配到合适的串,将会交给404.aspx处理。同样global中异常信息也可以提交过来。
string strRawUrl = HttpContext.Current.Request.RawUrl;
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的附加代码实现。
《完》
相关文章推荐
- 关于VS2005中GridView的自定义分页,单选、多选、排序、自增列的简单应用
- 自定义视图的简单应用
- [Android开发] 自定义View之重写View非常简单实现开关按钮SwitchView
- 从零开始学习H5应用(1)——V1.0版,简单页面滑动切换效果
- 关于GridView中自定义分页、单选、多选、排序、自增列的简单应用
- android -简单注册登录页面应用
- 三种思路实现自定义404页面:Tomcat、SpringMVC精准匹配、重写DispatchServlet
- 超级简单:在你的ASP.NET页面自定义列表和分页
- WCF REST简单应用 编程初始化 help页面实现
- Java基础---Java---基础加强---内省的简单运用、注解的定义与反射调用、 自定义注解及其应用、泛型及泛型的高级应用、泛型集合的综合
- 关于VS2005中GridView的自定义分页,单选、多选、排序、自增列的简单应用
- java(j2ee)应用-简单自定义标签开发全过程----之一(Inber)
- 关于GridView中自定义分页、单选、多选的简单应用
- 在应用URLRewrite功能后自动输出重写过的URL
- .NET自定义异常的一个简单应用(转载)
- 关于GridView中自定义分页、单选、多选、排序、自增列的简单应用(转,非常的棒)
- 利用$.fn.extend自定义拓展插件(简单应用)
- 关于GridView中自定义分页、单选、多选、排序、自增列的简单应用
- Android自定义一个简单的动画加载页面
- GridView的自定义分页,单选、多选、排序、自增列的简单应用