由于搜索引擎对aspx页面收录和html页面收录率的差别以及页面资源占用问题,我们很多时候需要实现ASPX页面动态转静态。网上也有很多人讨论其实现方法,本人实践后总结两种主流方法如下:第一种方法:
使用模板转换,步骤如下:
1、建立MyConvert.cs类文件 
using System; 
//记得添加以下三引用 
using System.Text; 
using System.Web; 
using System.IO; 
namespace TesConvert 

 /// <summary> 
 /// MyConvert 的摘要说明。 
 /// </summary> 
 public class MyConvert 
 { 
  public MyConvert() 
  { 
   // 
   // TODO: 在此处添加构造函数逻辑 
   // 
  } 
  public bool WriteFile(string strText,string strContent,string strAuthor) 
  { 
   string path = HttpContext.Current.Server.MapPath("/TesConvert/news/");//定义html文件存放路径 
   Encoding code = Encoding.GetEncoding("gb2312");//定义文字编码 
   // 读取模板文件 
   string temp = HttpContext.Current.Server.MapPath("/TesConvert/text.html"); 
   StreamReader sr=null; 
   StreamWriter sw=null; 
   string str="";  
   try 
   { 
    sr = new StreamReader(temp, code); 
    str = sr.ReadToEnd(); // 读取文件 
   } 
   catch(Exception exp) 
   { 
    HttpContext.Current.Response.Write(exp.Message); 
    HttpContext.Current.Response.End(); 
    sr.Close(); 
   } 
   string htmlfilename=path + DateTime.Now.ToString("yyyyMMddHHmmss")+".html"; 
   // 替换内容 
   // 这时,模板文件已经读入到名称为str的变量中了 
   str = str.Replace("ShowArticle",strText); //模板页中的ShowArticle 
   str = str.Replace("title",strText); 
   str = str.Replace("content",strContent); 
   str = str.Replace("author",strAuthor); 
   // 写文件 
   try 
   { 
    sw = new StreamWriter(htmlfilename,false,code); 
    sw.Write(str); 
    sw.Flush(); 
   } 
   catch(Exception ex) 
   { 
    HttpContext.Current.Response.Write(ex.Message); 
    HttpContext.Current.Response.End(); 
   } 
   finally 
   { 
    sw.Close(); 
   } 
   return true; 
  } 
  } 

2、TestNews.aspx文件:
 添加三和TextBox分别为:tbx_Title、tbx_Content、tbx_Author和一个Button:btn_AddNews。 
TestNews.aspx.cs文件 
private void btn_AddNews_Click(object sender, System.EventArgs e) 
  { 
   MyConvert Hover = new MyConvert(); 
   if(Hover.WriteFile(this.txb_Title.Text.ToString(),Server.HtmlDecode(this.txb_Content.Value),this.txb_Author.Text.ToString())) 
   { 
    Response.Write("添加成功"); 
   } 
   else 
   { 
    Response.Write("生成HTML出错!"); 
   } 
  } 
3、添加模板text.html文件  
<head>ShowArticle</head>
<body>
title<br>
content<br>
author
</body>
说明:一.news文件夹必须赋予asp.net用户写入的权限。这是一个简单的实现例子,实际项目必须先将数据保存到数据库下面,在datagird中调用数据库下面html文件的URL地址。二.默认情况下,我们是不能向TextBox、TextArea中添加html语法的,必须修改config文件,在<system.web>下面添加<pages validateRequest="false" />,但是这样做的话,整个项目中都允许键入html标签了,暂时还不知道其他的方。 
缺点:这种方法是在ASP.net在页面所有内容生成后、输出内容前对页面内容进行操作以前曾说过用HttpModule来在Response前更改,不够灵活,每行修改response,比较费力。第二种方法:
重写AttributeCollection.Render,比较灵活(msdn如是说:“在呈现阶段,所有 ASP.NET 移动设备适配器都通过一个称为文本编写器的对象来编写它们的输出。文本编写器对象是从 TextWriter 基类创建的。”)
可以写个基类,如:
public class BasePage: System.Web.UI.Page
{
  public BasePage()
  {
  }
  protected override void Render(System.Web.UI.HtmlTextWriter writer)
  {
    string name=Request.Url.AbsolutePath.Substring(1,Request.Url.AbsolutePath.Length-1).Replace("aspx","htm");
    string newurl="";
    if(name.IndexOf("/")>0)
    {
      newurl=Server.MapPath("../") + name;
    }
    else
    {
      newurl=Server.MapPath("./") + name;
    }
    MemoryStream ms = new MemoryStream();
    StreamWriter sww = new StreamWriter(ms);
    StreamWriter swr = new StreamWriter(newurl);
    System.Web.UI.HtmlTextWriter htmlw = new HtmlTextWriter(swr);
    base.Render(htmlw);
    htmlw.Flush();
    htmlw.Close();
    string strLL = System.Text.Encoding.UTF8.GetString(ms.ToArray());
    Response.Write(strLL);
    Response.Redirect(Request.Url.AbsoluteUri.Replace("aspx","htm"), true);
  }
}
然后在需要生成静态页面的页面中继承就可以了。说明:这种办法是在Asp.net的生成动作完成之后,再进行一次转换。
缺点:觉得本质上应该还是属于频繁post的aspx页面。小弟目前还是菜鸟一只,请各路兄弟点评。

解决方案 »

  1.   

    ASPNET_ASPNET() ( ) 信誉:100    Blog 
    应用xml+模式转换。----你说得是 XML+xsl 吧。本人最近做了两个相关项目,不喜欢。
    页面全是htm,使用xml,xsl,javascript 转换,只有webservice用c#写。
    觉得不好调,开发效率慢。累。
      

  2.   

    对于你说的第二种方法,需要配合“自动查找静态文件”方法。在页面的page_init事件中,首先查找本地是否已经有静态文件了,如果有,就直接重定向(例如 Server.Transfer(...))到那个页面。当需要重建哪一个页面的时候,删除其静态文件的就可以了,下次访问的时候会自动重建。不过不论第一种还是第二种,我认为意义都不大,特别是与页面缓冲或者Ajax相比之下。如果你转换的时候将所有url都自动转换为指向静态文件的,并且静态文件是真的静态也就是当asp.net被从服务器上删除的时候仍然可以通过web服务器浏览整个网站,似乎还有一点意义。
      

  3.   

    对这个不清楚。动态转静态,看资料好象更快点,但我不明白,从动态转为静态肯定要话时间的。为什么不直接是动态呢。
    看网上有人直接在后台输入HMTL代码,着难道也是动态转静态吗
    文章收藏了,好好看看。
      

  4.   

    大家平常都是怎样实现ASPX转静态页面的???
      

  5.   

    我是这样做的新闻正文内容用你说的那个替换方法
    我还采用了下面的生成方法,可是有个问题如果你是用datagrid或datalist等东西绑顶的数据库的话,生成的静态页样式表有问题,很严重的说
    public class GetPageHtml : System.Web.UI.Page
    {
    protected System.Web.UI.WebControls.Button WebClientButton;
    protected System.Web.UI.WebControls.Button WebRequestButton;
    protected System.Web.UI.WebControls.TextBox ContentHtml;
    protected System.Web.UI.WebControls.TextBox UrlText;
    private string PageUrl = ""; private void Page_Load(object sender, System.EventArgs e)
    {} #region Web Form Designer generated code
    override protected void OnInit(EventArgs e)
    {
    InitializeComponent();
    base.OnInit(e);
    } /// <summary>
    /// 设计器支持所需的方法 - 不要使用代码编辑器修改
    /// 此方法的内容。
    /// </summary>
    private void InitializeComponent()

    this.WebClientButton.Click += new System.EventHandler(this.WebClientButton_Click);
    this.WebRequestButton.Click += new System.EventHandler(this.WebRequestButton_Click);
    this.Load += new System.EventHandler(this.Page_Load);
    }
    #endregion private void WebClientButton_Click(object sender, System.EventArgs e)
    {
    PageUrl = UrlText.Text;
    WebClient wc = new WebClient();
    wc.Credentials = CredentialCache.DefaultCredentials; ///方法一:
    Byte[] pageData = wc.DownloadData(PageUrl);
    ContentHtml.Text = Encoding.Default.GetString(pageData); /// 方法二:
    /// ***************代码开始**********
    /// Stream resStream = wc.OpenRead(PageUrl);
    /// StreamReader sr = new StreamReader(resStream,System.Text.Encoding.Default);
    /// ContentHtml.Text = sr.ReadToEnd();
    /// resStream.Close();
    /// **************代码结束********
    /// 
    wc.Dispose(); 
    } private void WebRequestButton_Click(object sender, System.EventArgs e)
    {
    PageUrl = UrlText.Text;
    WebRequest request = WebRequest.Create(PageUrl);
    WebResponse response = request.GetResponse();
    Stream resStream = response.GetResponseStream(); 
    StreamReader sr = new StreamReader(resStream, System.Text.Encoding.Default);
    ContentHtml.Text = sr.ReadToEnd();
    resStream.Close(); 
    sr.Close();
    }
    }
      

  6.   

    末班应该好一写,但缺乏灵活性,最后将数据保存为静态的文件,如果不是考虑搜索引擎,我得考虑方法是UI分层:基本界面层,自定义,模块界面层,比如一个显示新闻的头,背景、间隔等,第三层XML数据,javascript实现,这样数据除非被更改,否则在浏览时是HTML框架访问模块静态框架,然后访问XML数据,也能实现复杂的界面,并且数据的更改(XML)不会影响界面,界面也会模块化的实现,不会在阅读上浪费服务器CPU和内存资源,个人观点,仅供参考!
      

  7.   

    xslt + xml 但始终觉得没有完美的方法  http://edzh.vicp.net
      

  8.   

    我觉得比较折中的是使用cache
      

  9.   

    生成静态的 xml+xsl这种感觉还可以了,如果想url转成html类的话,我正看 url转向问题,看介绍说 可以把asp.net转成html的,但我一直没试用成功,像a.aspx?id=3转成a/3.aspx这还可以!
      

  10.   

    URLRewrite技术http://xxx.photo.abc.com-> http://www.abc.com/xxx.aspx
      

  11.   

    个人感觉.生成静态页面.用XML+XSL比较麻烦.直接读取模板,替换比较简单.或着用URL重写.不过URL重写没成功过..
      

  12.   

    我是用xml + xsl来实现的在xml文档里定义需要的取出的数据程序遍历xml文档,取出数据加入当前xml文档中再使用xsl转换为html并输出xsl转html是比较耗CPU的,如果访问量比较大,可以考虑用.net remoting把xsl转html放到另外的服务器上处理
      

  13.   

    来msdn就象来了图书馆,每天都有好帖子,学习,都怕学不过来了 
      

  14.   

    推荐使用IHttpHandleFactory,先捕获url地址,再生成页面,超级简单
    public class HttpHand:IHttpHandlerFactory
    {
    #region 创建Http工厂 public void ReleaseHandler(IHttpHandler handler)
    {

    } public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
    {
    //获取随意定义的文件的名字,包含扩展
    string name = url.Substring(url.LastIndexOf('/')+1);
    string filename = name.Substring(0,name.LastIndexOf('.'));
    filename="CommonFactory."+filename; object obj = null; //一个类型,用于转IhttpHandler为抽象类型 //创建Http
    try
    {
    Type tp = Type.GetType(filename);
        obj = System.Activator.CreateInstance(tp);
    }
    catch
    {  }
    return (IHttpHandler)obj;
    } #endregion
    }-----------------------------------------------------------------------
    public class LoginOut:IHttpHandler
    { SqlFactory.Operation opea = new SqlFactory.Operation();
    public void ProcessRequest(HttpContext context)
    {
    if(context.User.Identity.Name!=string.Empty)
    {
    string path =context.Request.QueryString["P"];

    //清除用户登录表信息
    opea.voidDelSinLogin(context.User.Identity.Name);
                    opea.voidAddWork(context.User.Identity.Name+"注销用户","注销成功");
    Sec.FormsAuthentication.SignOut();
    AlertStr.AlertBackWindow(context.Response,"注销成功,欢迎再来!",path); }
    else
    {
    opea.voidAddWork("匿名用户注销","注销失败,原因:没有登录");
    AlertStr.AlertBackWindow(context.Response,"没有登录,无法注销",context.Request);
    }
    } public bool IsReusable
    {
    get
    {
    // TODO:  添加 LoginOut.IsReusable getter 实现
    return true;
    }
    } }
      

  15.   

    我也在研究这个呢  www.ige.com  做很好的 不知道怎么实现的 QQ 46114663
      

  16.   

    ruanjob(dfd) 这位仁兄做什么》???