以前做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文件。就是说你修改过一次模板然后页面的首次加载会很慢。以后就不会了。