ASP.NET MVC Render View Save To File

2023-02-19

說明如何將 View 藉由 Razor 語法的渲染結果以字串方式儲存為 html 格式,從而可以進階的將 html 檔案轉換為 pdf 作為網頁庫存、網頁歸檔的應用情境需求。

logo

說明

本次的範例使用 ASP.NET MVC 進行示範:

public ActionResult GeneratePdf()
{
    var htmlContent = RenderViewToString("ViewName", 
    new UploadFile { FileId = 1, FileName = "example", Extension = ".pdf", UploadDateTime = DateTime.Now});

    // 取得檔案路徑,將 htmlContent 寫入指定的檔案
    var filePath = Server.MapPath("~/App_Data/" + "render.html");
    System.IO.File.WriteAllText(filePath, htmlContent);

    // 將 HTML 內容直接回傳至 Client 端,ContentType 預設為 text/plain
    return Content(htmlContent);
}

// 產生 View 的 HTML 內容並轉為字串
private string RenderViewToString(string viewName, object model, bool partialView = true)
{
    // 取得目前的 ControllerContext
    var context = ControllerContext;

    // 設定 ViewData.Model 屬性為傳入的 model
    context.Controller.ViewData.Model = model;

    // 使用 StringWriter 將 View 輸出到字串
    using (var sw = new StringWriter())
    {
        // 利用 ViewEngines.Engines 物件來取得 ViewResult 物件
        // partialView 為 true 表示這是個部分檢視,否則是個完整的 View
        var viewResult = partialView ?
            ViewEngines.Engines.FindPartialView(context, viewName) : 
            ViewEngines.Engines.FindView(context, viewName, null);

        // 使用 ViewContext 來呈現 ViewResult 物件的 View
        var viewContext = new ViewContext(
          context, 
          viewResult.View, context.Controller.ViewData, 
          context.Controller.TempData, sw);
        viewResult.View.Render(viewContext, sw);

        // 釋放 View 物件
        viewResult.ViewEngine.ReleaseView(context, viewResult.View);

        // 回傳 StringWriter 所持有的字串
        return sw.GetStringBuilder().ToString();
    }
}

需要注意的是 ViewEngines.Engines.FindPartialView 或者是 FindView 所使用的 ViewName 不支援路徑形式,只能在 Controller 對應的 View 資料夾下進行搜尋或者是尋找在 Shared 資料夾當中的 View,邏輯與 View 的尋找邏輯相同。