Html.Action
、Html.RenderAction
、Html.Partial
、Html.RenderPartial
這四種方法都可以協助我們在 View 裡面渲染部分 HTML 內容,網路上針對這四種方式的差異說明大都著重在使用方式,但這次我們往下挖,看看這四種方式做了些什麼事?
有無 Render 字樣的差別
這四種方法都是 HtmlHelper 的擴充方法,Html.Partial、Html.RenderPartial 分別來自 PartialExtensions.cs 及 RenderPartialExtensions.cs,而 Html.Action、Html.RenderAction 而來自於 ChildActionExtensions.cs。
有無 Render 字樣的差別看 Source Code 就可以知道了,有 Render 字樣的方法會將 HTML 渲染結果直接寫入 ViewContext
的 Writer
,沒有 Render 字樣的方法則將 HTML 渲染結果裝入 MvcHtmlString
裡面回傳,也因此沒有 Render 字樣的方法效能會略遜一咪咪,但我個人覺得這個可以不必糾結,反而下面的這個差別才需要在意。
Partial 與 Action 的差別
Html.Action、Html.RenderAction、Html.Partial、Html.RenderPartial 這四種方法既然都可以協助我們在 View 裡面渲染部分 HTML 內容,往往我們操起鍵盤看哪個順眼就抓來用,但是我們知道它們背後是怎麼產生 HTML 內容的嗎?
Html.Partial、Html.RenderPartial 都呼叫了一個 RenderPartialInternal
的方法,它來自於 HtmlHelper.cs,方法裡面最後就透過 ViewEngineCollection
產生 View 直接渲染 HTML 結果。
Html.Action、Html.RenderAction 則是都呼叫了一個 ActionHelper
方法,它來自於與 Html.Action 及 Html.RenderAction 同一份原始碼檔,在方法最後產生了一個 ChildActionMvcHandler
用 HttpHandlerUtil.WrapForServerExecute
方法包裝成另一個 IHttpHandler
之後,再丟給 HttpContext.Server.Execute
方法執行以渲染 HTML 結果。
ChildActionMvcHandler 是誰?查看它的原始碼會發現它繼承了 MvcHandler
。
這表示了一件事情,Html.Action、Html.RenderAction 跑了從 Controller 建立到消滅的一整個生命週期,這包含了 Authentication Filters
、Authorization Filters
,以及 Action Filters
,而且不論目標 Action 是否定義在同一個 Controller 裡面,都會建立新的 Controller 實例,這生命週期有多長? 請看下圖:
知道了這件事之後,我們就要回頭想想,我們想要在 View 中渲染部分 HTML 內容,是否真的有需要透過 Action 來做?是否有需要跑整個 MvcHandler 的生命週期?Html.Partial 或 Html.RenderPartial 是否無法滿足我們的需要?