学而实习之 不亦乐乎

ASP.NET 生成静态页面

2022-12-06 18:21:05

一、概述

在客户端访问动态页面的时候,有的时候为了提高服务器的性能,可以让其访问生成的静态页面(当然也可用缓存,可这样比较耗资源),这样可以大大的提高访问速度,也能减轻服务器的压力。在 ASP.NET 中,可以通过 Page 类的 Render() 方法来实现。

ASP.NET 中所有的控件都是从 System.Web.UI.Control 类,在 Control 类中定义了三个与呈现有关的方法,分别是 Render(),RenderChildren()和RenderControl().

Control.Render() 方法将服务器控件内容发送到提供的 HtmlTextWriter 对象,此对象编写将在客户端呈现的内容。RenderControl() 方法用于供外部类进行调用,以生成控件,如父控件调用子控件的 Rendercontrol() 方法.在 RenderControl() 方法只是作了是否显示该控件的判断,如果显示则调用控件的被保护方法Render. 

Render方法是呈现控件的核心方法,在现实性自定义控件中,我们一般都是通过重写Render方法来呈现控件的,如果控件是一个容器控件,就要重写 RenderChildren() 方法来呈现子控件.这三个方法的关系,可以去看源码。

二、实例:使用 Render() 方法生成静态页面

实例一:使用 RenderControl() 方法

void Page_Load(){

    Response.Charset="";
    this.EnableViewState =false;
    StringWriter stringWriter tw=new StringWriter();
    HtmlTextWriter htmlWriter wt =new HtmlTextWriter(stringWriter);

    string path=@"c:\test.htm";
    StreamWriter sw = File.CreateText(path);

    //输出所有信息
    this.RenderControl(htmlWriter);
    wter.Write(stringWriter.ToString());
    //Response.Write(stringWriter.ToString());
    sw.Close();

    htmlWriter.Close();
    stringWriter.Close();
    Response.End();
    //生成相应文件,然后定向到该文件
    Response.Redirect(path);
}

实例二:重写 Render() 

首先是基类继承至Page类,一般这种类也叫中间类,将共有的功能在此类中实现,然后让其他类去继承,将达到简化代码的目的。

namespace CommonLib.CreateStaticPage
{
    public abstract class StaticPage:Page
    {
        private StringWriter htmlPage;

        public StaticPage()
        { }

        protected override void Render(HtmlTextWriter writer)
        {
            htmlPage = new StringWriter();
            HtmlTextWriter htw = new HtmlTextWriter(htmlPage);
            base.Render(htw);  
            CreatePage(StaticPageFilePath());
            ReturnPage(StaticPageFileUrl());
        }

        protected override void OnInit(EventArgs e)
        {
            GetOnInit();
            if (!IsRefresh(StaticPageFilePath()))
            {
                ReturnPage(StaticPageFileUrl());
            }
            base.OnInit(e);
        }
       
        private void CreatePage(string filePath)
        {
                StreamWriter filesw = new StreamWriter(filePath, false, Encoding.GetEncoding("UTF-8"));
                filesw.Write(htmlPage);
                filesw.Close();
        }

        private bool IsRefresh(string filepath)
        {
            if (File.Exists(filepath) && GetRefreshMinute() == 0)
            {
                return false;
            }
            else if (File.Exists(filepath) && new FileInfo(filepath).LastWriteTime.AddMinutes(GetRefreshMinute()) >= DateTime.Now)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        private void ReturnPage(string pageUrl)
        {
            Response.Redirect(pageUrl);
        }
     
        protected abstract string StaticPageFilePath();

        protected abstract string StaticPageFileUrl();

        protected abstract double GetRefreshMinute();

        protected abstract void GetOnInit();
      
    }
}

现在看看子类吧,也就是具体的页面了。

public partial class _Default : CommonLib.CreateStaticPage.StaticPage  
{
    private string areaid = "";
    protected void Page_Load(object sender, EventArgs e)
    {
      Label1.Text= DateTime.Now.ToLongDateString()+DateTime.Now.ToLongTimeString();
    }

    // 实现父类中的抽象方法,返回具体存放静态页面的文件路径
    protected override string StaticPageFilePath()
    {
        return "D://Web//CommonLib//test//aa.htm";
    }

    // 实现父类中的抽象方法,返回访问静态页面时的URL
    protected override string StaticPageFileUrl()
    {
        return "~/aa.htm";
    }

    // 实现父类中的抽象方法,返回多长时间刷新静态页面,单位是分钟
    protected override double GetRefreshMinute()
    {
        return 10;
    }

    // 实现父类中的抽象方法,初始化某些资源
    protected override void GetOnInit()
    {
    }
}

经过上面的设置,当我们访问Default.aspx页面时,首先程序会将Default.aspx页面生成aa.htm,并用WEB/aa.heml的虚拟路径映射到此静态页面。并且相隔10分钟之后才会刷新动态页面,这样服务器每隔10分钟才会有一次交互,大大的减轻了服务器的压力哟!

实例三:生成静态化页面

public class StaticFileCachePageBase : System.Web.UI.Page
{
    bool IsValidCacheFile = false;          //是否为有效的缓存
    string CacheFilePath = string.Empty;    //缓存文件路径
    string CacheFolder = "/Cache/";         //设置缓存文件保存位置
    const int CacheSeconds = 3600;            //设置缓存保存的时间

    string encoding = "gb2312";

    void ClearTimeOutFile(string folder)
    {
        DateTime now = DateTime.Now;
        DirectoryInfo di = new DirectoryInfo(folder);
        FileInfo[] fis = di.GetFiles();
        foreach (FileInfo file in fis)
        {
            TimeSpan ts = now - file.LastWriteTime;
            if (ts.TotalSeconds > CacheSeconds)
            {
                file.Delete();
            }
        }
    }


    protected override void OnPreInit(EventArgs e)
    {
        string code = Encryption.Escape(Request.RawUrl);
        string folder = CacheFolder + code[0] + "/" + code[1] + "/";
        CacheFilePath = Server.MapPath(folder + code + ".html");

        if (File.Exists(CacheFilePath))
        {
            TimeSpan ts = DateTime.Now - File.GetLastWriteTime(CacheFilePath);
            if (ts.TotalSeconds <= CacheSeconds)
            {
                IsValidCacheFile = true;
                Response.ContentEncoding = System.Text.Encoding.GetEncoding(encoding);
                Response.TransmitFile(CacheFilePath);
                return;

            }
        }

        ClearTimeOutFile(folder);
        base.OnPreInit(e);
    }

    protected override void Render(HtmlTextWriter writer)
    {

        if (!IsValidCacheFile)
        {
            StringWriter sw = new StringWriter();
            HtmlTextWriter htmlTextWriter = new HtmlTextWriter(sw);

            base.Render(htmlTextWriter);
            htmlTextWriter.Flush();
            htmlTextWriter.Close();

            string pageContent = sw.ToString();
            Response.Write(pageContent);

            string folder = Path.GetDirectoryName(CacheFilePath);
            if (!Directory.Exists(folder))
            {
                Directory.CreateDirectory(folder);
            }

            using (var fs = File.Create(CacheFilePath))
            {
                byte[] data = System.Text.Encoding.GetEncoding(encoding).GetBytes(pageContent);
                fs.Write(data, 0, data.Length);
                fs.Close();
            }
        }
    }
}
public class Encryption
{
    public static string Escape(string content)
    {
        string base64 = EncodeBase64(content);
        string reverseString = ReverseString(base64);
        string crossString = EncodeCrossString(reverseString, 3);

        return crossString;
    }

    public static string UnEscape(string content)
    {
        string decodeCrossString = DecodeCrossString(content, 3);
        string reverseString = ReverseString(decodeCrossString);
        return DecodeBase64(reverseString);
    }

    public static string DecodeBase64(string str)
    {
        try
        {
            byte[] bytes = Convert.FromBase64String(str);
            return Encoding.Default.GetString(bytes);
        }
        catch
        {
            return str;
        }
    }

    public static string DecodeCrossString(string str, int bitNum)
    {
        int num3;
        StringBuilder builder = new StringBuilder();
        int num = str.Length % bitNum;
        int num2 = (str.Length - num) / bitNum;
        string str2 = str.Substring(str.Length - num);
        string[] strArray = new string[num2];
        for (num3 = 0; num3 < num2; num3++)
        {
            strArray[num3] = str.Substring(num3 * bitNum, bitNum);
        }
        string str3 = strArray[num2 - 1];
        for (num3 = num2 - 1; num3 > 0; num3--)
        {
            strArray[num3] = strArray[num3 - 1];
        }
        strArray[0] = str3;
        for (num3 = 0; num3 < num2; num3++)
        {
            strArray[num3] = strArray[num3].Substring(1) + strArray[num3].Substring(0, 1);
            builder.Append(strArray[num3]);
        }
        builder.Append(str2);
        return builder.ToString();
    }

    public static string EncodeBase64(string str)
    {
        return Convert.ToBase64String(Encoding.Default.GetBytes(str));
    }

    public static string EncodeCrossString(string str, int bitNum)
    {
        int num3;
        StringBuilder builder = new StringBuilder();
        int num = str.Length % bitNum;
        int num2 = (str.Length - num) / bitNum;
        string str2 = str.Substring(str.Length - num);
        string[] strArray = new string[num2];
        for (num3 = 0; num3 < num2; num3++)
        {
            strArray[num3] = str.Substring(num3 * bitNum, bitNum);
        }
        string str3 = strArray[0];
        for (num3 = 0; num3 < (num2 - 1); num3++)
        {
            strArray[num3] = strArray[num3 + 1];
        }
        strArray[num2 - 1] = str3;
        for (num3 = 0; num3 < num2; num3++)
        {
            strArray[num3] = strArray[num3].Substring(bitNum - 1) + strArray[num3].Substring(0, bitNum - 1);
            builder.Append(strArray[num3]);
        }
        builder.Append(str2);
        return builder.ToString();
    }

    public static string ReverseString(string str)
    {
        StringBuilder builder = new StringBuilder();
        for (int i = str.Length - 1; i >= 0; i--)
        {
            builder.Append(str[i]);
        }
        return builder.ToString();
    }
}