如何将ASPX 转换为静态文件。

原创 2007年09月19日 00:41:00
如何将ASPX 转换为静态文件。
前段日子一直在为Web 的缓存策略烦恼。微软自己提供的cache机制很不灵活,而且喜欢在header 中加入一些郁闷的key,导致CDN缓存时不时的失效。最终反复讨论的结果是:如果太麻烦的话,干脆不要使用微软的页面缓存
就是类似:<%@ OutputCache Duration="1200" VaryByParam="cid" %> 这样的代码。
 除了这样的页面缓存,没有其他办法保存缓存结果了吗?自己拼字符串? OMG !页面多的情况下,无疑是个恶梦!
 
久寻不获,索性自己写了一个模板解析类,自己发明一套语法,将按照规定格式编写的 htm 文件,作为模板载入,设定变量字典后输出页面结果(字符串),然后自己实现缓存机制。花了3天时间搞定......
 然而这样对于asp.net 快速开发来说,仍然是个障碍,难道就没有好的办法吗? 比如直接获取aspx的字符串输出之类的......。近日网上瞎逛,在 csharpsharper 处看到一篇文章比较完美的解决这个问题:
How to freeze a dynamic aspx page into a static html page (on the server) 地址如下:http://30649.aspx.codebetter.com/blogs/peter.van.ooijen/archive/2004/11/01/30649.aspx
 不禁欣喜异常,特翻译如下,以飨各位同学:
Take this scenario: On a website a visitor fills in a form after which the form is to be filed as a static html page.
想象这样一个场景:当某位用户在一个网站上填写一个表单(Form),当提交之后,返回的结果是一个静态页面(当有人填写完全一样的表单时,可以直接看到这个静态页面,无须服务器再次计算)。
 You might have several reasons for wanting to do that, one of them are search engines. Getting it done in asp.net took me more effort than I had originally expected. Let me share what I have found to be working.
你可能会有很多理由想去这么做,比如说搜索引擎……。为了在asp.net 中实现这个效果,我花费了比我想象中更多的功夫完成了这个效果,让我来和大家分享一下我是如何做到将aspx 结果转换成为静态文件。
 
The easy way to catch the html rendered by asp.net is to save a page in the client browserTo catch it on the server you have to hook into the (html) rendering process.
Asp.net 生成的HTML页面代码很你可以很容易的在浏览器端得到,但要在服务器端获取HTML 页面代码,你必须跟踪 Asp.net 生成页面的过程。
There is no Page.OnRender event but the Page class does have a Render method. The method has a protected visibility, you cannot invoke it form your code.
在Asp.net 生成页面代码的过程中,没有Page.OnRender 这个事件(你无法在页面生成时执行你自己的代码),但是Page 类有个Render 方法,它是protected型,你无法在在你自己的代码中执行它。

The Render method is invoked when asp.net renders the page to the output, to hook in you override the method.

Render 方法在 Asp.net 在生成页面时被执行,并将HTML代码输出。为了能在这一过程中加入你的代码,你需要重载此方法(Render)。
The Render method has a parameter of type HtmlTextWriter, the default implementation of the overriden Render method is invoking Base.Render passing it the HtmlTextWriter object.
Render 方法有一个HtmlTextWriter类型的参数,其默认执行过程是Render将HtmlTextWriter 对象传递给Base.Render执行
 
 
protected override void Render(HtmlTextWriter writer)
{
   // Default behavior
  
base.Render(writer);
}
 
This gives a place to hook in an own textwriter where asp,net can render the html into.
这里提供了一个机会让我们自己构造的textwriter 提供给asp.net 将生成的HTML代码输入进去。
The constructor of the HTMLtextwriter class has a protected visibility. Passing an own htmltextwriter requires specializing the frameworks's HTMLtextwriter class.
HTMLtextwriter 的构造函数是protected 型的,如果想要将自己的htmltextwriter作为参数传递进去,必须要自己订制一个HTMLtextwriter类。
 
The constructor of the base class requires a stringwriter. A wrapper class to house both custom HTMLtextwriter and stringwriter:
构造函数的基类是一个stringwriter,我们需要将封装一个类,订制HTMLtextwriter和stringwriter。
 
internal class MyHtmlFileCreator
{
   private StringWriter html;
   private MyHtmlTextWriter htmlWriter;
   // override the HtmlTextWriter to reach the constructor
//重载HtmlTextWriter
   // the constructor in the base class is protected 
   class MyHtmlTextWriter : HtmlTextWriter
   {
      internal MyHtmlTextWriter(TextWriter tw): base(tw){}
   }
   // publish the HTMLwriter
   internal HtmlTextWriter RenderHere
   {
      get {return htmlWriter;}
   }
   // constructor initializes stringwriter and htmlwriter based on that
//
构造函数在此初始化stringwriterhtmlwriter
   // initialize Url 
//
初始化URL
   internal MyHtmlFileCreator()
   {
      html = new StringWriter();
      htmlWriter = new MyHtmlTextWriter(html);
      newUrl = Context.Request.Url.AbsolutePath.ToString();
      newUrl = newUrl.Replace(".aspx",".htm");
   }
   internal void WriteHTMLFile(string virtualFileName)
   {
      // Stringreader reads output rendered by asp.net
     // Stringreader
用来读取asp.net 生成的HTML代码
      // Stringwriter writes html output file
      // Stringwriter
将代码生成文件
      StringReader sr = new StringReader(html.ToString());
      StringWriter sw = new StringWriter();
      // Read from input
      string htmlLine = sr.ReadLine();
      while (htmlLine != null)
      {
      // Filter out ASp.net specific tags
//
将指定的标签代码过滤
      if (! ((htmlLine.IndexOf("<form") > 0) ||
            (htmlLine.IndexOf("__VIEWSTATE") > 0) ||
            (htmlLine.IndexOf("</form>") > 0) ))
         {sw.WriteLine(htmlLine);}
      htmlLine = sr.ReadLine();
      }
      // Write contents stringwriter to html file
//
输出成为静态文件
     
StreamWriter fs = new StreamWriter(virtualFileName);
      fs.Write(sw.ToString());
       fs.Close();
   }
}
A MyHtmlFileCreator object has a place asp.net can render to and it has a method to write the contents of the stringwriter (inside the htmlwriter) to file.
MyHtmlFileCreator 对象提供一个容器,让Asp.net 可以将HTML 输出。并且MyHtmlFileCreator可以通过其内部的stringwriter 将HTML代码写入到一个文件中。
 
I use the MyHtmlFileCreator in a page base class. The page hooks in the render event. When the freeze flag is set the html is rendered to a file and the application is redirected to the html file just created.
我将在Page基类中使用MyHtmlFileCreator。该Page将在页面生成时触发render事件,当freeze 信号灯被置为true时,asp.net 生成的HTML代码将根据请求时的URL 生成相应的静态文件(xxx.html),并且程序将用户的请求重定向的到该静态文件的地址去(xxx.html)。
 
public class FreezablePage : System.Web.UI.Page
{
   internal class MyHtmlFileCreator{}
   // When Asp.Net renders the page the Page.Render method is invoked
//
Asp.net 输出结果时,page.render 方法将会被执行
   // Override the method to hook in
   protected override void Render(HtmlTextWriter writer)
   {
      if (freeze)
      {
         MyHtmlFileCreator htmlFile = new MyHtmlFileCreator();
         // Let Asp.net render the output, catch it in the file creator
//
使用自己订制的file creator捕获Asp.net 的输出
         base.Render(htmlFile.RenderHere);
         // Write new html file
//
创建一个HTML 静态文件
         htmlFile.WriteHTMLFile(Server.MapPath(NewUrl));
         // Redirect
//
将用户的请求转向到静态文件的地址去
         Response.Redirect(NewUrl, true);
      }
   else
   {
      // Default behavior
//
默认输出器
      base.Render(writer);
   }
   }
   // Flag render event
   protected void Freeze()
  {
      freeze = true;
   }
   protected void Freeze(string toUrl)
   {
      freeze = true;
      NewUrl = toUrl;
   }
   private bool freeze = false;
   private string newUrl;
   internal string NewUrl
   {
      get
      {
         return newUrl;
      }
      set
      {
          newUrl = value;
      }
   }
   }
}
Use this on your page like this :
使用示例:
public class _Default : Gekko.Web.UI.FreezablePage
{
    private void Button1_Click(object sender, System.EventArgs e)
   {
      Freeze(string.Format(@"Statisch/{0}.htm", TextBox1.Text));
   }
}
You will see that the resulting page has lost its form knocking out al buttons. There are no more postback possible. And the viewstate is also cut away.
你将看到结果页面将不会有任何按钮存在,自然也不会有postback 可能,viewstate 也消失不见了。
To process any file asp.net might produce will require more filtering. You can do quite flexible things treating the input as xml. Which requires some cutting and pasting, an html document is not always well-formed
如果要处理不同的请求和页面,asp.net 自然也需要更多的过滤方法(防止在生成的静态页面中产生form的提交造成服务器交互)。你可以对生成的HTML文件象XML一样做灵活活的处理。但是生成的HTML并不总是标准的(标准的HTML可以作为一个XML进行解析,请参考XHTML标准),你需要自行做一些调整(个人认为涉及的工作量比较大,读者自己权衡)。
 
这篇文章写得比较早了。我修改了一下,使其可以在framework 2.0 下运行
FreezablePage.cs

using System;
using System.IO;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
 
///<summary>
/// Summary description for FreezablePage
///</summary>
public class FreezablePage : System.Web.UI.Page
{
    // When Asp.Net renders the page the Page.Render method is invoked
    // Override the method to hook in
 
    protected override void Render(HtmlTextWriter writer)
    {
        if (freeze)
        {
            MyHtmlFileCreator htmlFile = new MyHtmlFileCreator();
            // Let Asp.net render the output, catch it in the file creator
            base.Render(htmlFile.RenderHere);
 
            newUrl = HttpContext.Current.Request.Url.AbsolutePath.ToString();
            newUrl = newUrl.Replace(".aspx", ".htm");
 
            // Write new html file
            htmlFile.WriteHTMLFile(Server.MapPath(newUrl));
            // Redirect
            Response.Redirect(newUrl, true);
        }
        else
        {
            // Default behavior
            base.Render(writer);
        }
 
    }
 
    // Flag render event
    protected void Freeze()
    {
        freeze = true;
    }
 
    protected void Freeze(string toUrl)
    {
        freeze = true;
        NewUrl = toUrl;
    }
 
    private bool freeze = false;
 
    private string newUrl;
 
    internal string NewUrl
    {
        get
        {
            return newUrl;
        }
        set
        {
            newUrl = value;
        }
 
    }
 
}
internal class MyHtmlFileCreator
{
    private StringWriter html;
    private MyHtmlTextWriter htmlWriter;
 
    // override the HtmlTextWriter to reach the constructor
    // the constructor in the base class is protected
    class MyHtmlTextWriter : HtmlTextWriter
    {
        internal MyHtmlTextWriter(TextWriter tw) : base(tw) { }
    }
 
 
    // publish the HTMLwriter
    internal HtmlTextWriter RenderHere
    {
        get { return htmlWriter; }
    }
 
 
    // constructor initializes stringwriter and htmlwriter based on that
    // initialize Url
    internal MyHtmlFileCreator()
    {
        html = new StringWriter();
        htmlWriter = new MyHtmlTextWriter(html);
    }
 
    internal void WriteHTMLFile(string virtualFileName)
    {
        // Stringreader reads output rendered by asp.net
        // Stringwriter writes html output file
        StringReader sr = new StringReader(html.ToString());
        StringWriter sw = new StringWriter();
 
        // Read from input
        string htmlLine = sr.ReadLine();
        while (htmlLine != null)
        {
            // Filter out ASp.net specific tags
            if (!((htmlLine.IndexOf("<form") > 0) ||
                  (htmlLine.IndexOf("__VIEWSTATE") > 0) ||
                  (htmlLine.IndexOf("</form>") > 0)))
            { sw.WriteLine(htmlLine); }
 
            htmlLine = sr.ReadLine();
        }
 
 
        // Write contents stringwriter to html file
        StreamWriter fs = new StreamWriter(virtualFileName);
        fs.Write(sw.ToString());
        fs.Close();
    }
 
}
 
点击下面的链接下载示例网站
 http://dl2.csdn.net/down4/20070919/19003848422.rar
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

如何将.aspx转换为.htm

aspx转换静态页面htm

【Javaweb】利用urlRewrite插件实现网站的伪静态与aspx,jsp,php三版齐发的邪门歪道

所谓网站的伪静态其实也不是什么高深名词,就是将*.asp,*.aspx,*.jsp,*.php这种动态URL页面伪装成静态的HTML页面。因为网上大部分搜索引擎都会优先考虑收录静态的HTML页面,而不...

如何将pdf文件转换成excel

  • 2014-08-20 17:24
  • 49.39MB
  • 下载

如何将pdf文件转换成txt

  • 2014-08-22 15:10
  • 49.39MB
  • 下载

如何将Java程序转换成exe文件?

最近发现一个软件exe4j可以将Java的jar打包转换成exe可执行程序 步骤: 1、打开下载安装好的exe4j,在bin目录下找到exe4j.exe,点击打开。 2、打开之后出现以下界面...

如何将PDF文件转换成Excel

如何将PDF文件转换成Excel 从事办公文书工作的朋友,经常要处理大量的PDF文件,有时候需要将PDF转换成Excel。遇到类似的PDF格式文件,通常来说,要对PDF文件进行编辑和修改的工作难度...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)