ASP.NET 2.0生成HTML的三種方法

由數據庫驅動的動態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重寫方案等等,在以後的文章中再做討論。

有待解決的疑點

  • 瀏覽生成的HTML頁面時,ViewState如何處理(丟掉還是……)
  • 頁面PostBack如何處理(不PostBack還是……)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章