在web開發中經常會遇到在內部代碼中獲取Html,這些Html是需要和數據進行一起渲染。並不是直接把Html代碼返回給客戶端。這樣的做法有很多應用場景,例如分頁、Ajax一次性獲取幾段Html片段、生成郵件發送模板、生成Html靜態頁面等等。比較簡單的或者容易想到的做法就是直接拼接Html,當然這肯 ...
在web開發中經常會遇到在內部代碼中獲取Html,這些Html是需要和數據進行一起渲染。並不是直接把Html代碼返回給客戶端。這樣的做法有很多應用場景,例如分頁、Ajax一次性獲取幾段Html片段、生成郵件發送模板、生成Html靜態頁面等等。比較簡單的或者容易想到的做法就是直接拼接Html,當然這肯定不是最合適的做法。
應用場景
1、在分頁中,有一種做法是用ajax獲取table的html代碼和一些分頁信息的Json
var json = { "table": "<table><tr/><td>1</td></tr></table>", "pageSize": 10, "currentIndex": 1, "count": 100 }
2、Ajax一次性獲取幾段Html片段
var json = { "leftHtml": "<div><h1>HHHHHHHHHH</h1></div>", "rightHtml": "<table><tr/><td>1</td></tr></table>" }
3、生成郵件發送模板、生成Html靜態頁面
我們經常會生成一些郵件模板,比如推廣一些產品的html代碼。
生成Html靜態頁面就更加常用了。
應用場景分析
我們這些應用都是在內部代碼中生成html,然後在對html代碼進行處理,比如拼接成json,或者發送郵件,在或者生成靜態html頁面。
生成Html在asp.net中莫過於Razor引擎,總之就是很好用,語法也很強大,如果我們把需要生成的html用Razor引擎生成豈不是很好,如果熟悉asp.net mvc 管道的話就可以很簡單的解決這個問題。
1、查找View(cshtml)
可以用ViewEngines.Engines.FindView查找View。
public virtual ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName);
FindView需要ControllerContext、viewName和masterName,其中masterName是母版視圖的名稱目前可以忽略。
viewName就是我們需要查找的View,查找View的方式和在Action中return View(string viewName)的方式一致,也就是說有兩種方式,一個是全路徑,如:"~/Views/Home/Html1.cshtml",必須帶尾碼名cshtml。還有一種方式是直接寫"Html1",也就是相對路徑, 如果cshtml文件的位置不在Controller所對應的文件夾中,則可以寫"../Folder/Html1"。此方式同樣適應於普通執行Controller中Action直接return View(string viewName)。
ControllerContext是封裝有關與指定的 System.Web.Routing.RouteBase 和 System.Web.Mvc.ControllerBase 請求的信息
public ControllerContext(RequestContext requestContext, ControllerBase controller);
在構造函數中需要RequestContext和ControllerBase,ControllerBase就是this,RequstContext可以在Action中和容易的獲取。
最終查找View的代碼
ControllerContext context = new ControllerContext(Request.RequestContext, this); ViewEngineResult result = ViewEngines.Engines.FindView(context, "Html1", "");
2、Render View
最終我們需要執行View的Render方法,來獲取生成的html
void Render(ViewContext viewContext, TextWriter writer);
Render 代碼
using (var sw = new StringWriter()) { var viewContext = new ViewContext(context, result.View, context.Controller.ViewData, context.Controller.TempData, sw); result.View.Render(viewContext, sw); string html = sw.ToString(); }
代碼中html就是我們需要獲取的html。
傳遞數據至View
如何傳遞數據至View,這個和普通的Action執行一致,也就是說我們熟悉的ViewBag,ViewData,TempData以及Model都可以用。
1、設置數據
在調用View.Render前設置數據即可。
context.Controller.ViewBag.Name = "Emrys"; context.Controller.ViewData["Age"] = 10; context.Controller.TempData["City"] = "上海"; context.Controller.ViewData.Model = new UserInfo { Name = "Emrys", Age = 10, City = "上海" };
2、在View(html)獲取數據,也就是Html1.cshtml中的Razor代碼。
@{ Layout = null; } @model UserInfo Name:@ViewBag.Name<br /> Age:@ViewData["Age"]<br /> City:@TempData["City"]<br /> Name:@Model.Name<br /> Age:@Model.Age<br /> City:@Model.City
總結
最終Action中的代碼
ControllerContext context = new ControllerContext(Request.RequestContext, this); ViewEngineResult result = ViewEngines.Engines.FindView(context, "Html1", ""); context.Controller.ViewBag.Name = "Emrys"; context.Controller.ViewData["Age"] = 10; context.Controller.TempData["City"] = "上海"; context.Controller.ViewData.Model = new UserInfo { Name = "Emrys", Age = 10, City = "上海" }; using (var sw = new StringWriter()) { var viewContext = new ViewContext(context, result.View, context.Controller.ViewData, context.Controller.TempData, sw); result.View.Render(viewContext, sw); string html = sw.ToString(); }
這樣我們就可以巧用Razor獲取我們需要和數據組合的html代碼,以供我們使用。
最後望對各位有所幫助,本文原創,歡迎拍磚和推薦。