如何将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 处看到一篇文章比较完美的解决这个问题:
 不禁欣喜异常,特翻译如下,以飨各位同学:
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

方法一:根据模板生成,保持在html文件夹中 思路分析: 1.写一个自定义的HTM模板 其中需要替换的地方用$value$这样 包含起来 2.生成页面的ASPX中,用StreamReader读取...
  • lin_lujian
  • lin_lujian
  • 2011年11月03日 11:29
  • 300

ASP.NET中将.aspx页面转化成静态Html页面的方法

在开发中我们有时候需要将ASP.NET中的.aspx页面转化成静态的页面进行相关的业务处理,网上搜索了不少方法,有一些方法的确是蛮不错的,也帮助了我,在此谢谢那些网友啦。我现在将其中的一个方法整理出来...
  • gxwzmm
  • gxwzmm
  • 2013年02月05日 17:52
  • 8742

aspx页面导出成word文档

在网上 看见这段,可是,谁能帮我解释几个问题吗?这个 方法中的3个参数,第2个是导出的类型吧,第3个是导出的编码吧,第一个是什么呢?在后置代码中添加  public void ExpertContro...
  • xia411123129
  • xia411123129
  • 2010年07月05日 23:52
  • 532

Aspx页面转换成html 页面

有的网站出于各种各样的原因,在IIS中修改了动态页面的默认后缀,asp时代就有人在服务器上修改配置,把html后缀的文件当作asp文件来解析:也就是说,asp程序(后缀为.asp)可以保存为一个.ht...
  • lem12
  • lem12
  • 2007年05月25日 17:19
  • 6995

雷击程序(五)------生成雷击点

      生成雷击点的函数代码如下所示:      /// /// 生成sde数据库中的点 /// /// 要素类工作空间 ...
  • wap168
  • wap168
  • 2011年05月07日 06:21
  • 671

HTML格式的页面,改成ASPX格式一运行起来,页面样式就乱了。

上午同事说美工给他的页面,样式有问题。原来HTML格式的Demo什么问题都没有,但是把格式改成.aspx的,再一运行,发现有些样式失效了。我看了下,aspx页面看不出问题,就是html改个后缀名,而且...
  • lxlnet
  • lxlnet
  • 2010年09月06日 13:56
  • 2666

aspx视图转换成Razor视图

aspx视图转换成Razor视图的方法之一
  • bpanyiwei
  • bpanyiwei
  • 2015年07月30日 22:16
  • 563

将动态aspx页面转换成为静态html页面的几种方法

1.         模版法该方法历史悠久,具体处理流程为采用一个html模版,将其中的关键字替换为我们希望的信息。优点:缺点: 所有的信息都要采取字符串批凑的方式来实现,比如需要一个列表,就需要拼凑...
  • yashira
  • yashira
  • 2006年12月27日 14:55
  • 1033

在浏览器中用XSLT把XML转换为XHTML

XML文件XMLTree.xml:      000    b975d757-9dad-4fee-bd4f-78bd5459ba43    90        001    e4d72d64-45cd...
  • ahywg
  • ahywg
  • 2007年09月04日 13:35
  • 925

面向对象编程思想 (转自博客园的 supers)

新一篇: ]喜欢与爱的区别[ 前言:   整理这份资料的目的是为了帮助朋友们能够更直观的理解面向对象的编程。让后来者能够少走一些弯路。但其中不免有许多漏洞及错误,也还请前辈提出宝贵的更改意见,毕竟...
  • YYYYYellow
  • YYYYYellow
  • 2015年12月31日 16:32
  • 316
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:如何将ASPX 转换为静态文件。
举报原因:
原因补充:

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