由数据库驱动的动态WEB页面把我们编程人员从烦琐的查找替换中解放了出来,但如何事都有利弊,减少了我们的工作,但加重了服务器的负担,所以,各种各样的静态页面生成方法也就孕育而出了。本文只是简单叙述和总结了一下我所知道的几种ASP.NET静态页面生成技术,如有不妥之处还请大家包含和指教。
一、WebRequest
我们先来看一下MSDN对System.Net.WebRequest的解释吧。
WebRequest 是 .NET Framework 的请求/响应模型的 abstract 基类,用于访问 Internet 数据。使用该请求/响应模型的应用程序可以用协议不可知的方式从 Internet 请求数据,在这种方式下,应用程序处理 WebRequest 类的实例,而协议特定的子类则执行请求的具体细节。
请求从应用程序发送到某个特定的 URI,如服务器上的网页。URI 从一个为应用程序注册的 WebRequest 子代列表中确定要创建的适当子类。注册 WebRequest 子代通常是为了处理某个特定的协议(如 HTTP 或 FTP),但是也可以注册它以处理对特定服务器或服务器上的路径的请求。
如果在访问 Internet 资源时发生错误,则 WebRequest 类将引发 WebException。WebException.Status 属性是 WebExceptionStatus 值之一,它指示错误源。当 WebException.Status 为 WebExceptionStatus.ProtocolError 时,Response 属性包含从 Internet 资源接收的 WebResponse。
因为 WebRequest 类是一个 abstract 类,所以 WebRequest 实例在运行时的实际行为由 System.Net.WebRequest.Create 方法所返回的子类确定。有关默认值和异常的更多信息,请参见有关子类的文档,如 HttpWebRequest 和 FileWebRequest。
当我们传入的是 http://
或 https://
,则 Create 返回 HttpWebRequest 对象;如果是 file://
,则 Create 方法返回 FileWebRequest 对象。.NET Framework 包括了 http://
、https://
和 file://
URI 方案的支持。用 RegisterPrefix 方法注册要处理其他请求的自定义 WebRequest 子类。
在了解了WebRequest类之后,剩下来的就简单了,看下面代码:
//请求一个URL System.Net.WebRequest request = System.Net.WebRequest.Create(url); //返回该请求 WebResponse response = request.GetResponse(); //将得到的内容放入StreamReader中 StreamReader sr = new StreamReader(response.GetResponseStream()); StreamWriter sw = new StreamWriter(path, false, System.Text.Encoding.Default); //写入到文件 sw.Write(sr.ReadToEnd()); sw.Close(); sr.Close();
特点:因为URL是我们自己传入的,所以就可以抓取到任何程序、任何网站的页面。可以制作成一个总的后台页面或Win form程序来进行批量生成HTML或小偷程序。
二、Response.Filter
老样子,还是来看一下MSDN上的解释。
Response.Filter:获取或设置一个包装筛选器对象,该对象用于在传输之前修改 HTTP 实体主体。当创建 Stream 对象并将 Filter 属性设置为 Stream 对象时,所有由 Write 发送的 HTTP 输出将通过筛选器。
顾名思义Filter是个筛选器,能让我们在代码输出之前做一些额外的操作。首先我们需要自定义一个继承Stream的类,代码如下:
public class ResponseFilter : Stream { private Stream m_sink; private long m_position; private FileStream fs; public ResponseFilter(Stream sink, string filePath) { m_sink = sink; //创建一个文件流 fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write); } public override void Write(byte[] buffer, int offset, int count) { //把内容输出到browser m_sink.Write(buffer, 0, count); //把内容输出到文件 fs.Write(buffer, 0, count); } //重写抽象方法 public override bool CanRead { get { return true; } } public override bool CanSeek { get { return false; } } public override bool CanWrite { get { return false; } } public override long Length { get { return 0; } } public override long Position { get { return m_position; } set { m_position = value; } } public override long Seek(long offset, System.IO.SeekOrigin direction) { return 0; } public override void SetLength(long length) { m_sink.SetLength(length); } //别忘了fs.Close() public override void Close() { m_sink.Close(); fs.Close(); } public override void Flush() { m_sink.Flush(); } public override int Read(byte[] buffer, int offset, int count) { return m_sink.Read(buffer, offset, count); } }
然后我们就可以在需要生成HTML的页面中加入这个Filter就可以了。
//注意,要传入Response.Filter才能得要生成的HTML流 Response.Filter = new ResponseFilter(Response.Filter, path);
特点:可以在页面第一个浏览时才生成HTML,做到按需生成,效率上比较好。如果大面积的页面需要加载这个Filter,那我们可以使用IHttpHandlerFactory或IHttpModule。
三、Page.Render
这个方法也是比较简单的,我们重写Page的Render方法,以达到保存HTML的目的。代码如下:
protected override void Render(HtmlTextWriter writer) { //这是默认的Render实现,直接输出到writer中 //base.Render(writer); StringWriter html = new StringWriter(); HtmlTextWriter tw = new HtmlTextWriter(html); //通过base.Render()方法,把生成的HTML写入到我们定义的tw中 base.Render(tw); string path = Server.MapPath("~/html/Render_" + Guid.NewGuid() + ".html"); StreamWriter sw = new StreamWriter(path, false, System.Text.Encoding.Default); //写入到文件中 sw.Write(html.ToString()); sw.Close(); //写入到writer中,以输出页面的HTML //注意,这里不能再调用base.Render(writer),会出现错误 writer.Write(html.ToString()); }
特点:比较繁琐。:-(
四、小结
综上所述,在ASP.NET中生成HTML还是简单和方便的,推荐大家使用第一种和第二种。对于自定义模板再做文本替换的方法,在ASP中使用的比较多,但是也比较麻烦,所以在此也就不再讨论了。
本文只是展示了一些生成HTML的基本方法,并没有涉及到具体使用中的各种生成策略、URL重写方案等等,在以后的文章中再做讨论。
有待解决的疑点:
参考资料: