[2007最后一博]Url地址重写,利用HttpHander手工编译页面并按需生成静态HTML文件


很多朋友可能都讨论过ASP.NET中生成HTML的方法了,有按照模板用IO方法写文件
有在404错误页面内生成HTML的,有在Render内保存页面输出到HTML文件的。
今天我发一个配合Url重写利用HttpHander手工编译.aspx页面方法。
HTML文件的方法,可按需、“定时”的生成,以减轻数据库的访问。

声明:下面的文字是本文不可缺少的部分,转载请保留,谢谢!
////////////////////////////////////////////////////
作者:武眉博<活靶子.NET>
同时首发于:
    
落伍者   && 博客园  
    
开发者学院   && .Net男孩社区
知识点:UrlRewriteIHttpModuleIHttpHander 的编写
效果:
http://www.devedu.com/Doc/DotNet/AspNet/default.2.aspx
http://www.devedu.com/Doc/DotNet/AspNet/default.2.html
思路:
1 挂载“.aspx"的请求到自定义的Httphander内
2 配置URL重写规则
3 访问某.aspx文件时,在HttpHander内 根据配置确定是否应该生成
 接着...
 if(需要生成)
 {
  if(若已经生成html文件 )
  {
   if(文件并未过期)
   {
    则直接定向(Server.Transfer())。
   }
   else
   {
    删除HTML文件;
    重新编译.aspx(Page内数据库操作等等)
    生成HTML文件;
   }
  }
  else if(尚未生成文件)
  {
   生成Html。
  }
 }
 else
 {
  则编译.aspx文件
 }

另:建议阅读一下dudu的blog中关于asp.net页面编译的讨论
http://www.cnblogs.com/dudu/archive/2006/03/07/345107.html
http://www.cnblogs.com/dudu/archive/2006/03/07/344351.html

部分代码

C#代码
  1. public void ProcessRequest(HttpContext context)   
  2.         {   
  3.             string rawUrl = context.Request.RawUrl;   
  4.             string requestPath = context.Request.Path;   
  5.             string applicationPath = context.Request.ApplicationPath;   
  6.             Url urlItem = null;   
  7.   
  8.             //上下文中没有定义ToStaticUrlItem表示,此请求没有经过UrlRewrite,直接编译,不生成html   
  9.             //参考UrlRewriteModule.cs   
  10.             if (context.Items["ToStaticUrlItem"] == null)   
  11.             {   
  12.                 if (!File.Exists(context.Request.PhysicalPath))   
  13.                 {   
  14.                     throw new HttpException(404, "您访问的页面没有找到。");   
  15.                 }   
  16.   
  17.                 // asp.net 1.1 采用下面方法编译页面   
  18.                 //PageParser.GetCompiledPageInstance(requestPath, context.Request.PhysicalPath, context).ProcessRequest(context);   
  19.                 IHttpHandler hander = BuildManager.CreateInstanceFromVirtualPath(requestPath, typeof(Page)) as IHttpHandler;   
  20.                 hander.ProcessRequest(context);   
  21.   
  22.                 return;   
  23.             }   
  24.   
  25.             string filePath;   
  26.   
  27.             urlItem = (Url)context.Items["ToStaticUrlItem"];   
  28.   
  29.             Regex regex = new Regex(   
  30.                 Globals.ApplicationPath + urlItem.LookFor,   
  31.                 RegexOptions.CultureInvariant | RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);   
  32.   
  33.             string requestFile = regex.Replace(rawUrl, Globals.ApplicationPath + urlItem.WriteTo.Replace("^""&"));   
  34.   
  35.             if (requestFile.IndexOf("?") > 0)   
  36.             {   
  37.                 filePath = requestFile.Substring(0, requestFile.IndexOf("?"));   
  38.             }   
  39.             else  
  40.             {   
  41.                 filePath = requestFile;   
  42.             }   
  43.   
  44.             string inputFile = context.Request.PhysicalApplicationPath + filePath;   
  45.             string path = context.Request.PhysicalApplicationPath + rawUrl.ToLower().Replace(".aspx"".html");   
  46.             if (applicationPath != "/")   
  47.             {   
  48.                 inputFile = inputFile.Replace(applicationPath + "/", @"\");  
  49.                 path = path.Replace(applicationPath + "/", "").Replace("/", @"\");  
  50.             }  
  51.             else  
  52.             {  
  53.                 path = path.Replace("/", @"\");  
  54.             }  
  55.  
  56.             if (!urlItem.EnabledToStatic)  
  57.             {  
  58.                 // asp.net 1.1 采用下面方法编译页面  
  59.                 //PageParser.GetCompiledPageInstance( filePath , inputFile , context ).ProcessRequest( context );  
  60.                 IHttpHandler hander = BuildManager.CreateInstanceFromVirtualPath(filePath, typeof(Page)) as IHttpHandler;  
  61.                 hander.ProcessRequest(context);  
  62.  
  63.                 return;  
  64.             }  
  65.  
  66.             if (!File.Exists(path))  
  67.             {  
  68.                 // asp.net 1.1 采用下面方法编译页面  
  69.                 //PageParser.GetCompiledPageInstance( filePath , inputFile , context ).ProcessRequest( context );  
  70.                 IHttpHandler hander = BuildManager.CreateInstanceFromVirtualPath(filePath, typeof(Page)) as IHttpHandler;  
  71.                 hander.ProcessRequest(context);  
  72.                 context.Response.Filter = new AspxBoy.BuildHtmlDemo.ToHtmlFilter(context.Response.Filter, path);  
  73.  
  74.                 return;  
  75.             }  
  76.  
  77.             if (urlItem.Minutes == Int32.MaxValue)  
  78.             {  
  79.                 context.Server.Transfer(rawUrl.ToLower().Replace(".aspx", ".html"));  
  80.             }  
  81.             else  
  82.             {  
  83.                 FileInfo fileInfo = new FileInfo(path);  
  84.                 if (fileInfo.LastWriteTime.AddMinutes((double)urlItem.Minutes) < DateTime.Now)  
  85.                 {  
  86.                     fileInfo.Delete();  
  87.  
  88.                     // asp.net 1.1 采用下面方法编译页面  
  89.                     //PageParser.GetCompiledPageInstance( filePath , inputFile , context ).ProcessRequest( context );  
  90.                     IHttpHandler hander = BuildManager.CreateInstanceFromVirtualPath(filePath, typeof(Page)) as IHttpHandler;  
  91.                     hander.ProcessRequest(context);  
  92.                     context.Response.Filter = new AspxBoy.BuildHtmlDemo.ToHtmlFilter(context.Response.Filter, path);  
  93.                 }  
  94.                 else  
  95.                 {  
  96.                     context.Server.Transfer(rawUrl.ToLower().Replace(".aspx", ".html"));   
  97.                 }   
  98.                 return;   
  99.             }   
  100.         }  

示例项目下载:http://files.cnblogs.com/huobazi/BuildHtmlDemo.rar

标签: .net, asp.net

posted on 2007-12-31 16:28 活靶子.Net 阅读(7795) 评论(14) 编辑 收藏

评论

#1楼 2007-12-31 17:53 minidxer[未注册用户]

出错页面也可以?  回复 引用   

#2楼[楼主] 2007-12-31 17:59 武眉博<活靶子.Net>      

--引用--------------------------------------------------
minidxer: 出错页面也可以?
--------------------------------------------------------
以前园子内有人发过在404内根据请求路径去HTML的生了下次就不404了,但我觉得如果恰好搜索引擎蜘蛛来了 那404 被它捕获 可能就直接认为是单纯的404了。
 回复 引用 查看   

#3楼 2007-12-31 18:07 asp.net学习社区[未注册用户]

好东西,已经转载至
http://i.aspx1.com/showforum-4.aspx
若有不妥,请回复,将立即删除
 回复 引用   

#4楼 2008-02-27 15:42 一抹微蓝      

很好很强大,收藏了;
我调试的时候直接对.html文件进行urlrewrite也是可以的,在生成的html没有过期之间直接访问.html,如果过期或者尚没有生成访问的时候生成.html,这样就可以视为是灵活的自动生成了吧,不是“手工”编译了。
终于找到一个完美方案,谢谢博主。
 回复 引用 查看   

#5楼 2008-05-09 19:09 雨中漫步的太阳      

--引用--------------------------------------------------
一抹微蓝: 很好很强大,收藏了;
我调试的时候直接对.html文件进行urlrewrite也是可以的,在生成的html没有过期之间直接访问.html,如果过期或者尚没有生成访问的时候生成.html,这样就可以视为是灵活的自动生成了吧,不是“手工”编译了。
终于找到一个完美方案,谢谢博主。
--------------------------------------------------------
确实是一个好的办法,以前我曾使用重定向错误页面的方式进行过类似的尝试,园主直接通过地址映射确实是一个好的办法.现在有一个问题就是,当大并发访问的时候,多人同时访问相同的页面,静态生成可能就会出现问题.其次楼上的说直接使用html映射,看起来确实网站更像一个静态站了,确实会节约服务器资源,但是你实际访问的还是aspx程序,还是会进行逻辑判断,这个还是会浪费服务器资源的.所以我建议还是使用先静态话的方式.但是那个方式会带来的弊端是我的动态页面可能由于静态话的需要无法正常的浏览,这个时候就可以借助地址映射的方式
 回复 引用 查看   

#6楼 2008-05-22 22:21 kong521[未注册用户]

想问下这些怎么配置IIS  回复 引用   

#7楼 2008-05-28 23:51 BAsil      

很好很强大  回复 引用 查看   

#8楼 2008-07-07 12:34 榕城小榕      



这篇博文的源码能否发一份给小弟,谢谢,博文底下的下载链接,好像源程序没有办法在VS05上面编译
 回复 引用 查看   

#9楼 2009-04-15 11:19 MyDream      

首先,感谢大哥,您两年前与的东西,今天让我很受用,不过我有个问题还是不明白.
当首页访问页面,并生成html页面时,在httphandler里如何把它转向为html页面呢.
if(页面不存在)
{
//生成html页面
//在这里如何转向到html页面呢.


}
 回复 引用 查看   

#10楼 2009-04-15 14:12 活靶子[未注册用户]

@MyDream
你好,你可以使用server.transfer

context.Server.Transfer(rawUrl.ToLower().Replace(".aspx", ".html"));
 回复 引用   

#11楼 2009-06-09 12:39 握薪尝蛋      

学习学习  回复 引用 查看   

#12楼 2009-08-03 23:18 ffffffffffff[未注册用户]

fdsafdasf  回复 引用   

#13楼 2009-09-17 22:34 fengwf[未注册用户]

我有一个需求,就是访问.ashx之前加一步验证,参数包含字符baidu.com的我允许程序继续执行,否则停止.
总是报错 不是有效的虚拟路径.不知道是不是成了个死循环了.
web.config
<httpHandlers>
<add verb="*" path="*.ashx" type="myWeb.BasicHandler, BasicHandler"/>
</httpHandlers>

BasicHandler.cs

using System;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Compilation;

namespace myWeb
{
/// <summary>
/// $验证失败$ 的摘要说明
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class BasicHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string rawUrl = context.Request.RawUrl;
if (rawUrl.indexOf("baidu.com")>-1)
{
string rawUrl = context.Request.RawUrl;
IHttpHandler hander = BuildManager.CreateInstanceFromVirtualPath("~/"+rawUrl, typeof(IHttpHandler)) as IHttpHandler;
hander.ProcessRequest(context);
return;
}
else
context.Response.Write("验证失败的");
}

public bool IsReusable
{
get
{
return false;
}
}
}
}

,我想应该可以内部执行把,可是好象是死循环.

有点这种的意思
<urlMappings enabled="true">
<add url="~/1.aspx" mappedUrl="~/1.aspx"/>
</urlMappings>
 回复 引用   

#14楼 2010-06-21 20:43 空逸云      

博主,您好!看了您这篇文章后收益匪浅.但是还是有几处不太明白的地方.不知您是否可以抽些时间解答疑惑?
===============================
您这里使用了HTTPMoudle和HTTPHandler.
在Moudle中.您最后使用了context.RewritePath(filePath, pathInfo, queryString);来实现URL的重写,并且在Handler中再使用BuildManager.CreateInstanceFromVirtualPath方法编译实例.这里我不明白的是.既然调用了RewritePath,为何还调用BuildManager.CreateInstanceFromVirtualPath呢?我尝试不调用Handler.结果是一样的.而不调用Moudle只调用Handler结果却大不相同,原因是BuildManager.CreateInstanceFromVirtualPath不能传入QueryString吧.另外.您调用RewritePath后.我查看Form的action属性.结果是指向重写后的URL,这我很纳闷,您是如何做到的呢?一直看,调试也没弄明白..您也没重写Form控件啊.这就是我的两处不明之处.盼望您的回复!谢谢

PS:不知为何.在您的博客上发布不了评论.
 回复 引用 查看   

导航

公告

昵称:活靶子.Net
园龄:8年
粉丝:30
关注:2

统计

搜索

 
 

我的标签

随笔分类(190)

随笔档案(152)

相册

常去链接

我的东西

友情博客

积分与排名

最新评论

阅读排行榜

评论排行榜

推荐排行榜