以前做CMS的時候都會根據模板來生成輸出HTML或者生成HTML文件。
常用的引擎有VTemplate、NVelocity等等,這個我就布做介紹了。
這里我想說的是。當mvc出現Razor模板引擎的時候。我就在想怎么利用這個MVC自帶的模板生產HTML文件。
想利用Razor模板引擎來生成文件,首先你該了解MVC的生命周期。這個在此我也不做多做介紹了。
入主題吧:
1.我的想法比較簡單,在一個control中進行模板生產。第一步就是找到你設定的模板。這個比較簡單,用mvc提供的方法,找到這個視圖。如果路徑和控制器的規則一樣的話你就寫個模板文件的名字,否則全路徑吧。
IView v = ViewEngines.Engines.FindView(cc, tempUrl, "").View;
2.傳入請求信息和初始化模板中頁面的變量值。
當找到模板后我們是不是要把模板中和我們設定的信息結合在一起生成我們想要的html呢?其實這個我們也不用考慮很多,既然用MVC的Razor模板引擎,那我們就考慮使用ViewContext
public static string OutHtml(ControllerContext cc, string tempUrl, ViewDataDictionary vd, TempDataDictionary td) { string html = string.Empty; IView v = ViewEngines.Engines.FindView(cc, tempUrl, "").View; using (StringWriter sw = new StringWriter()) { ViewContext vc = new ViewContext(cc, v, vd, td, sw); vc.View.Render(vc, sw); html = sw.ToString(); } return html; }
3.到這一步我們基本上就能獲取到加載模板后生產的html字符了。
在control中我們可以這些寫。
public ActionResult CreateHtml() { ViewBag.Title = "輸出的HTML頁面";//這個變量在模板頁中有聲明的話就會傳入模板頁最終替換模板頁面的變量(和mvc的razor一樣用) ViewBag.my = "動態生成,。。。。。"; string outHtml= RazorHtml.OutHtml(this.ControllerContext, "Title", this.ViewData, this.TempData); ViewBag.HtmlContent = outHtml; return View(); }
在模板中寫上我們定義好的參數
<html> <head><title>@ViewBag.Title</title></head> <body> <h2>@ViewBag.my<h2> </body> </html>
運行一下看一下結果
到了這一步生成也沒什么問題了吧。
4.接下來我們看頁面文件生成吧。這方面沒什么好說的直接貼上代碼,(很久以前的了文件生成代碼了。)
public static string OutHtml(ControllerContext cc, string tempUrl, ViewDataDictionary vd, TempDataDictionary td) { string html = string.Empty; IView v = ViewEngines.Engines.FindView(cc, tempUrl, "").View; using (StringWriter sw = new StringWriter()) { ViewContext vc = new ViewContext(cc, v, vd, td, sw); vc.View.Render(vc, sw); html = sw.ToString(); } return html; } public static void SaveHtml(ControllerContext cc, string tempUrl, ViewDataDictionary vd, TempDataDictionary td, string savePath, string fileName, string Extension, Encoding encoding) { string html = string.Empty; IView v = ViewEngines.Engines.FindView(cc, tempUrl, "").View; using (StringWriter sw = new StringWriter()) { ViewContext vc = new ViewContext(cc, v, vd, td, sw); vc.View.Render(vc, sw); html = sw.ToString(); } CreateSaveFile(savePath, encoding, html); } /// <summary> /// 寫入文件 /// </summary> /// <param name="filePath">保存地址</param> /// <param name="enconding">編碼類型</param> /// <param name="content">內容</param> /// <returns></returns> public static bool SaveFile(string filePath, Encoding enconding, string content) { try { File.SetAttributes(System.Web.HttpContext.Current.Server.MapPath(filePath), FileAttributes.Normal); using (FileStream fs = new FileStream(System.Web.HttpContext.Current.Server.MapPath(filePath), FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { //fs.a = fs.Attributes & ~FileAttributes.ReadOnly & ~FileAttributes.Hidden; Byte[] info = enconding.GetBytes(content); fs.Write(info, 0, info.Length); fs.Close(); return true; } } catch (Exception) { return false; } } /// <summary> /// 創建文件 /// </summary> /// <param name="filePath">保存地址</param> /// <param name="enconding">編碼類型</param> /// <param name="content">內容</param> /// <returns></returns> public static bool CreateSaveFile(string filePath, Encoding enconding, string content) { try { if (!File.Exists(System.Web.HttpContext.Current.Server.MapPath(filePath)))//如果不存在就創建file文件夾 { FileStream fs; fs = File.Create(System.Web.HttpContext.Current.Server.MapPath(filePath)); fs.Close(); fs.Dispose(); return true; } SaveFile(filePath, enconding, content); return true; } catch (Exception) { return false; } } }
控制器中寫上生成代碼
ViewBag.Title = "輸出的HTML頁面";//這個變量在模板頁中有聲明的話就會傳入模板頁最終替換模板頁面的變量(和mvc的razor一樣用) ViewBag.my = "動態生成,。。。。。"; string outHtml= RazorHtml.OutHtml(this.ControllerContext, "Title", this.ViewData, this.TempData); ViewBag.HtmlContent = outHtml; RazorHtml.SaveHtml(this.ControllerContext, "Title", this.ViewData, this.TempData, "/StaticHtml/Loui.html", "Loui.html", "html", Encoding.UTF8);//生成的HTML return View();
看一下結果,剛剛的
總結:只是一個突然的想法,也沒做過其他的測試,不過我知道每次修改模板的mvc也會動態更新生成模板的cs文件。就是說你修改過一次模板然后頁面的首次加載會很慢。以后就不會了。