[ASP.NET MVC]部分檢視詳解(partial,renderpartial,action,renderAction,renderPage...)

  • 14527
  • 0
  • 2015-12-07

摘要:[ASP.NET MVC]部分視圖詳解

在網路上介紹的這幾種部分檢視的用法五花八門,個人是認為這幾種的分界已經漸漸的越來越模糊了拉,所以只提出主觀的見解:

在開始介紹之前,先要準備一些檔案,首先是要一個Layout.cshtml當作樣版,

剛好最近在研究jquery mobile,就從這邊[JQM]常用空白範本直接複製過來吧,用行動版網頁實驗比較有趣,首先先新增一個新的樣版,取名叫做_LayoutResearchPartial.cshtml,內容如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    @Styles.Render("~/Content/Mobile/css", "~/Content/jquerymobile/css")
    @Scripts.Render("~/bundles/jquery", "~/bundles/jquerymobile")
    @*也可用官方的CDN,比nuget:jquery.mobile.mvc內建的新,嗚嗚*@
    @*<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />
        <script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
        <script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>*@

    <script>
        $(document).ready(function () {
            $.mobile.ajaxEnabled = false;
        });
    </script>
</head>
<body>

    <div data-role="page" data-theme="c">

        <div data-role="header">
            <h1>@ViewBag.Title</h1>
            @RenderSection("headerSection", false)
        </div>

        <div data-role="content">
            @RenderSection("contentSection", false)
            @RenderBody()
        </div>

    </div>

</body>
</html>

並且新增一個Controller叫做ResearchPartialController.cs,內容就先用預設內容就好。

並且在Views資料夾下面,新增一個資料夾叫做ResearchPartial,用來放我們等等要測試用的View。

nuget請安裝jquery.mobile.mvc套件,純粹是因為用行動版的網頁測試比較有趣,因此而安裝。

然後就開始介紹了:

那麼就先來介紹@html.partial, @Html.RenderPartial

從英文翻譯成中文的感覺來說,他就是單純的輸出一段已經寫好的html,就網路上的介紹來說,@html.partial, @Html.RenderPartial還是可以傳變數進去的,不過那樣會讓我感覺與@Html.Action,@Html.RenderAction的定位混淆,因此我寧願讓@html.partial, @Html.RenderPartial輸出單純的靜態html或是不用傳參數進去的Server端razor語法

為了測試@html.partial, @Html.RenderPartial,我們在剛剛新增的ResearchPartial資料夾新增一個View叫做TestPartialRenderPartial.cshtml,並且套用剛剛新增的_LayoutResearchPartial.cshtml為主版

然後在剛剛的Controller裡面加上這段來使用這個View:

public ActionResult TestPartialRenderPartial()
{
	return View();
}

目前為止建立出來的網頁是空白的,還沒加入任何內容,如下:

現在先在~/Views/ResearchPartial/新增一個PartialView叫做_EasyStaticHtmlPartial.cshtml:,包含是靜態的網頁html如下(通常是header或是footer的內容,或是用來include一些.js或.css)

這是一個<strong>靜態html</strong>的內容

並且利用@Html.Partial以及@Html.RenderPartial語法,在剛剛的TestPartialRenderPartial.cshtml測試剛剛新增的partialView:_EasyStaticHtmlPartial.cshtml

TestPartialRenderPartial.cshtml的程式碼片段為:

@{
    ViewBag.Title = "TestPartialRenderPartial";
    Layout = "~/Views/Shared/_LayoutResearchPartial.cshtml.cshtml";
}

<h2>TestPartialRenderPartial</h2>

這是用@@Html.Partial產生的靜態html內容:
<br/>
@Html.Partial("~/Views/ResearchPartial/_EasyStaticHtmlPartial.cshtml")
<br />
這是用@@Html.RenderPartial產生的靜態html內容:
<br/>
@{Html.RenderPartial("~/Views/ResearchPartial/_EasyStaticHtmlPartial.cshtml");}

然後就可以看執行結果了,電腦版+手機版網頁:成功的利用@html.partial, @Html.RenderPartial在網頁上顯示靜態html

而@Html.Partial以及@Html.RenderPartial語法雖然也可以傳入動態的資料並顯示在畫面上,但是這樣會導致與其他的部分檢視用法混淆(例如:@Html.Action)

因此這裡寧願採用靜態html以及靜態的伺服器端Razor語法(就是programmer不用傳參數進去的意思)為主,這裡就示範一個顯示靜態的伺服器端Razor語法的例子:在~/Views/ResearchPartial新增另一個partialView叫做_EasyStaticRazorPartial.cshtml,內容為不用傳參數進去的一堆html以及伺服器端的Razor語法,如下:

@{
    if(DateTime.Now.Month == 12)
    {
        <p>現在是12月</p>
    }
    else
    {
        <p>現在不是12月</p>
    }
    
}

並且在TestPartialRenderPartial.cshtml引用這個partialview, 程式碼片段為:

<br/>
<br/>
<div>
    這是用@@Html.Partial產生的非互動式(即免傳參數)razor內容:
    <br />
    @Html.Partial("~/Views/ResearchPartial/_EasyStaticRazorPartial.cshtml")
    <br />
    這是用@@Html.RenderPartial產生的非互動式(即免傳參數)razor內容:
    <br />
    @{Html.RenderPartial("~/Views/ResearchPartial/_EasyStaticRazorPartial.cshtml");}
</div>

執行結果為:

同時還有在@section裡面該用哪種部分檢視要注意,見參考文章第三篇

如何在@section裡面如何使用partialview也是很重要的,理論上說起來,@section裡面並不是@Html.Partial以及@Html.RenderPartial都可使用

因為@Html.RenderPartial產出來的是一般html string,而@section裡面的內容都是MVCHtmlString, 因此只有@Html.Partial能在@section裡面使用

但是實際上測試,卻是@Html.Partial 以及 @Html.RenderPartial皆可使用,真奇怪了...既然這樣就先不管理論,先示範一下範例,如何在@section裡面使用@Html.Partial 以及 @Html.RenderPartial:

TestPartialRenderPartial.cshtml內容改為如下:

程式碼會在section Header裡面示範@Html.Partial,且在section Content裡面示範@Html.RenderPartial

@{
    ViewBag.Title = "TestPartialRenderPartial";
    Layout = "~/Views/Shared/_LayoutResearchPartial.cshtml";
}

<h2>TestPartialRenderPartial</h2>


@section headerSection
{
    @Html.Partial("~/Views/ResearchPartial/_EasyStaticRazorPartial.cshtml")
}

@section contentSection
{
    @{Html.RenderPartial("~/Views/ResearchPartial/_EasyStaticRazorPartial.cshtml");}

}

執行結果如下:電腦版+手機版:

看到上面的執行結果,相信已經很清楚如何在@section裡面使用@Html.Partial以及@Html.RenderPartial了,學習這個的原因是因為只要是從asp.net web form出身的程式設計師,都一定會用過user control來顯示常常重複出現的程式碼,學習這個技巧就是為了在mvc的架構,達成相同的功用。

ps.補充:就目前的情況來看,@Html.Partial與@Html.RenderPartial的差別就只有效能而已,@Html.RenderPartial較好,因為直接輸出string,不用像是@Html.Partial輸出的MvcHtmlString還要暫存一下並且再轉換成string才輸出所以導致較慢

接下來介紹@Html.Action以及@Html.RenderAction

其實跟@Html.Partial, @Html.RenderPartial本質上的意義差不多,都是幫忙程式設計師避免一直寫重複的html用的html helper

只是@Html.Action以及@Html.RenderAction有到伺服器端(Controller)進行一些Server端的程式碼或是取得資料庫的資料,然後再輸出而已

接下來就開始示範如何使用@Html.Action以及@Html.RenderAction:

首先新增一個範例資料庫AdventureWork, 可參考這篇文章[SQL]如何使用微軟的範例資料庫AdventureWorksDB直接從微軟網站下載.mdf檔案之後,直接新增到本機的SQLServer即可

並且在專案的~/Views/Models資料夾新增一個Ado.net Entity model(.edmx)來存取這個資料庫:

然後在~/Views/ResearchPartial資料夾新增一個PartialView叫做:_EasyDynamicRazorPartial.cshtml

此PartialView將會顯示範例資料庫的聯絡人資料表裡面的資料,內容程式碼如下:

@model IEnumerable<JQueryMobileMVC.Models.Contact>

<ul data-role="listview">
    @foreach (var item in Model)
    {
        <li>
            <h2>@Html.DisplayFor(modelItem => item.LastName)</h2>
            <p>@Html.DisplayFor(modelItem => item.EmailAddress)</p>
        </li>
    }

</ul>

然後在ResearchPartialController.cs加入1個ActionResult, 

這個Action取得從.cshtml傳過來的字串參數以及數字參數,並且隨便取得5筆資料庫抓出來的聯絡人資料,並以PartialView的形式回傳

public ActionResult GetActionRenderActionInfo(string stringValue, int intValue)
{
	string stringValueGet = stringValue;
	int intValueGet = intValue;
	AdventureWorksEntities1 db = new AdventureWorksEntities1();
	var contacts = db.Contact.Take(5);//隨便取得五筆聯絡人的資料
	return PartialView("_EasyDynamicRazorPartial",contacts.ToList());
}

在~/Views/ResearchPartial資料夾下面新增一個View叫做TestActionRenderAction.cshtml, 主版版面一樣套用剛剛新增的_LayoutResearchPartial即可:

這個view的html如下:他示範了@Html.Action傳參數的用法,傳入字串777以及數字888,並且指定ResearchPartialController的GetActionRenderActionInfor這個Action來

執行伺服器端行為

@{
    ViewBag.Title = "TestActionRenderAction";
    Layout = "~/Views/Shared/_LayoutResearchPartial.cshtml";
}

<h2>TestActionRenderAction</h2>
<p>以下是@@Html.Action以partialview的方式到Controller取得的資料庫資料:</p>
@Html.Action("GetActionRenderActionInfo", "ResearchPartial", new { stringValue = "777", intValue = 888 })

<p>以下是@@Html.RenderAction以partialview的方式到Controller取得的資料庫資料</p>
@{
    Html.RenderAction("GetActionRenderActionInfo", "ResearchPartial", new { stringValue = "777", intValue = 888 });
}

執行結果很順利的:電腦版+手機版:

然後當然也要介紹在@section裡面如何使用@Html.Action以及@Html.RenderAction:

經過實驗證明,在@section裡面只能用@Html.Action,不能使用@Html.RenderAction,網路上的說明是因為@Html.Action是直接輸出string,不是mvchtmlstring, 因此無法使用

但是這樣的理由在@Html.Partial, @Html.RenderPartial便無法成立,因此...我也不知道為什麼無法使用@Html.RenderAction  XD

總之至少要知道如何使用@Html.Action,請看範例囉,以下是TestActionRenderAction.cshtml的html(避免畫面太過混亂,把剛剛部分的程式碼註解掉了):

@{
    ViewBag.Title = "TestActionRenderAction";
    Layout = "~/Views/Shared/_LayoutResearchPartial.cshtml";
}

<h2>TestActionRenderAction</h2>
@*<p>以下是@@Html.Action以partialview的方式到Controller取得的資料庫資料:</p>
@Html.Action("GetActionRenderActionInfo", "ResearchPartial", new { stringValue = "777", intValue = 888 })

<p>以下是@@Html.RenderAction以partialview的方式到Controller取得的資料庫資料</p>
@{
    Html.RenderAction("GetActionRenderActionInfo", "ResearchPartial", new { stringValue = "777", intValue = 888 });
}*@

@section contentSection
{
    @Html.Action("GetActionRenderActionInfo", "ResearchPartial", new { stringValue = "777", intValue = 888 });
    @*無法使用Html.RenderAction,網路上說是因為他是直接輸出string,不是mvchtmlstring, 因此無法使用*@
    @*Html.RenderAction("GetActionRenderActionInfo", "ResearchPartial", new { stringValue = "777", intValue = 888 });*@

}

執行結果為:電腦版+手機版:

最後是RenderPage

功用與RenderPartial完全一樣,差異處只在於,RenderPartial可以傳入整個model或是使用ViewData(Session), 而RenderPage只能使用傳入的參數。然而,本文中為了讓各種部分檢視的定位分明,因此暫且當成RenderPage與RenderPartial是一樣的部分檢視,同樣為不傳入任何參數的HtmlHelper,功用既然相同,因此便不再做範例囉。

本篇大概是這樣。

 

參考文章:

ASP.NET MVC 部分视图详解

http://www.guzii.com/?p=67

Html.Partial vs Html.RenderPartial & Html.Action vs Html.RenderAction

http://stackoverflow.com/questions/5248183/html-partial-vs-html-renderpartial-html-action-vs-html-renderaction

ASP.NET MVC 3: Multiple Html.RenderAction() Problem

http://stackoverflow.com/questions/6590767/asp-net-mvc-3-multiple-html-renderaction-problem

ASP.NET MVC - Html.Partial 與 Html.RenderPartial

http://kevintsengtw.blogspot.tw/2013/07/aspnet-mvc-htmlpartial-htmlrenderpartial.html

Razor: @Html.Partial() vs @RenderPage()

http://stackoverflow.com/questions/4501736/razor-html-partial-vs-renderpage