ASP.NET Core 十種方式擴展你的 Views

如今,已經有不少種方式來擴展Razor視圖了,咱們循循漸進,先從最簡單的開始。javascript

若是你以前熟悉MVC5(以及以前的MVC)中的視圖的話,有一部分你應該已經很熟悉了。在新的ASP.NET Core 中,那些你熟悉的方式有一部分仍然能用,只是Core版本針對視圖又添加了一些東西。這篇文章,咱們就來一塊兒看看吧。css

#1:數據視圖(Typed Views)

這是一個不具備動態內容的最基本的一個視圖,就是你定義一個ViewModel , 而後ViewModel具備一些默認值,在視圖上直接呈現而已。定死的ViewModel,好像不是很常見,以致於你使用Visual Studio新建一個默認的Web應用程序的話,都看不到它。它就看起來像一個*.cshtml結尾的HTML文件,可是,cshtml文件倒是服務端能夠解析的一種文件,因此你能夠在裏面使用一些Razor語法,好比HtmlHelpers,UrlHelpers等。一樣,你可使用ViewBag或者ViewData來從Controller的Action傳輸數據到View裏面,來讓它具備動態的內容。可是ViewBagViewData都是弱類型的,因此沒有智能提示,用起來略不爽。html

要在你的視圖中使用強類型數據對象,你須要定義一個Model來在視圖中使用。java

@model ExtendViews.ViewModels.AboutModel

<!-- usage: --->
@Model.FullName

這種方式是否是很常見的? 下一種方式是一個更好的方式來佈局咱們的視圖:asp.net

#2:佈局(Layouts):

至關於ASP.NET的WebForms的母版頁,不過它是定義Razor視圖的基本佈局的一種方式。它就是_Layout.cshtml, 位於 Views\Shared\ 文件夾裏 。一般狀況下這個文件一般包含HTML的header,body和公用的一些東西。你能夠多建幾個互相進行組合,來完成整個站點的佈局。其餘頁面引用佈局視圖頁的時候,是這樣子寫的(注意不須要擴展名):ide

@{
    Layout = "_Layout";
}

此調用須要在您的視圖的第一行中。但你不須要在每個視圖中定義佈局,若是你使用Visual Studio新建一個ASP.NET Core項目,Views文件夾有一個_ViewStart.cshtml,在運行的時候它會自動的導入到每一個視圖中去。函數

_Layout.cshtml有一個方法法叫 RenderBody(),它就是用來渲染詳細的視圖頁到模板佈局視圖中:佈局

@RenderBody()

在此方法的位置,詳情視圖就會被渲染到這裏。學習

#3: 區域(Sections)

有時候子視圖中想在主視圖中顯示一部分html代碼,好比javascript代碼或者是css,這個時候就可使用Sections,一般狀況下在頁面的結尾部分。ui

在主視圖中(_Layout.cshtml)定義一個Javascripts Section:

@RenderSection("scripts", required: false)

有一個required參數來聲明這個Section是否必須的。而後你就能夠在子視圖中這樣使用:

@section scripts
{
    <script>
        $(function() {
            // some more js code here;
        });
    </script>
}

若是你使用嵌套的佈局,你可能須要嵌套這個區域。意思就是你在Section裏面嵌套調用RenderSection():

@section scripts
{
    @RenderSection("scripts", required: false)
}

#4: 分部視圖( PartialViews)

你能夠提取html頁面中重用的部分,把它放到一個新的Razor視圖中,這個視圖沒有本身的Action,這種視圖就叫作分部視圖。 分部視圖一般也在Views\Shard\文件夾。

分部視圖一樣也能夠是一個數據視圖,它能夠從父視圖中獲取數據(但不是必須的):

@model IEnumerable<UserModel>
@if (Model.Any())
{
    <ul>
        @foreach (var user in Model)
        {
            <li>@user.FullName</li>
        }
    </ul>
}

這個分部視圖須要從父視圖中獲取用戶列表的數據

@{ await Html.RenderPartialAsync("Users", Model.Users);}

若是你的分部視圖沒有定義用戶模型,你就不須要傳第二個參數。

#5:視圖組件(ViewComponents)

這個 ASP.NET Core特有的。

譯者注:相似於之前的用戶控件

有時候你須要作一些分部視圖的事情,可是又包含一些業務邏輯在裏面。在過去,你可使用ChildAction渲染結果到一個視圖中,可是,在 ASP.NET Core中,有一種新的方式來作這件事情,它就是ViewComponents(我已經寫了一篇關於ViewComponents的博文)。它相似於在MVC中的一種迷你的MVC,也就是說他們能夠有本身的Controller,和單個的action以及view。ViewComponents是徹底獨立於你的當前視圖的,可是能夠經過你當前的視圖傳輸數據。

想這樣調用它,來渲染一個ViewComponents:

@Component.Invoke("Top10Articles");

能夠看個人博客來學習怎麼建立本身的ViewComponent

#6: HTML助手(HtmlHelpers)

HTMLHelper類中,你能夠建立你本身的擴展方法來擴展Razor語法:

public static class HtmlHelperExtensions
{
    public static HtmlString MyOwnHtmlHelper(this HtmlHelper helper, string message)
    {
        return new HtmlString($"<span>{message}<span>");
    }
}

在你的視圖中,建立一個可重用的部分是很是有用的,它比分部視圖多包含了一些業務邏輯。比HTMLHelpers擴展更好的是新的TagHelpers,可是在擴展你視圖的時候,HTMLHelpers仍然有它本身的一些適用的地方。

#7: 標籤助手(TagHelper)

這是 ASP.NET Core 很是好的一個新特性。

一個擴展你視圖的小助手,它看起來像一個原生的HTML標籤同樣。 在ASP.NET Core MVC中你應該使用 TagHelpers 來替換 HtmlHelpers,由於它們更加的簡潔和容易使用。另外一個巨大的好處就是依賴注入,在HtmlHelpers中是使用不了的,由於HtmlHelpers 擴展的都是靜態內容。 但TagHelpers是一個公共類,咱們能夠很容易的在它的構造函數中注入服務。

下面是一個很簡單的小示例,來展現怎麼樣定義一個TagHelper:

[TargetElement("hi")] 
public class HelloTagHelper : TagHelper 
{ 
    public override void Process(TagHelperContext context, TagHelperOutput output) 
    { 
        output.TagName = "p"; 
        output.Attributes.Add("id", context.UniqueId); 

        output.PreContent.SetContent("Hello "); 
        output.PostContent.SetContent(string.Format(", time is now: {0}",  
                DateTime.Now.ToString("HH:mm"))); 
    } 
}

這裏定義了一個叫作hi的標籤,它以HTML標記來呈現,p標籤的內容是當前時間。

使用:

<hi>John Smith</hi>

結果:

<p>Hello John Smith, time is now: 18:55</p>

ASP.NET Core MVC 已經默認提供了不少TagHelpers來替換之前的HtmlHelpers。例如ActionLink已經被新的TagHelper所替換:

@Html.ActionLink(「About me」, 「About」, 「Home」)

新的TagHelper像這樣來建立一個link:

<a asp-controller=」Home」 asp-action=」About」>About me</a>

以上兩種方式來建立一個a標籤的結果:

<a href=」/Home/About」>About me</a>

能夠看到,TagHelpers看起來更像原生的HTML,他們在視圖中更加的直觀,更高的可讀性,而且更容易使用。

#8: 依賴注入(Dependency Injection)

這也是ASP.NET Core的新特性。

在擴展你的視圖的時候,可使用依賴注入了,這是一個很是大改進。是的,你能夠在你的視圖中使用DI了。

在StackOverflow和reddit有人這樣問?
這真的有意義嗎? 這不是會搞亂個人視圖嗎? 這不是與MVC模式背離嗎?

我認爲,不是這樣的。 的確,在真正須要的地方你才使用,而且,你使用的時候須要很是當心。 有這樣一個有效的場景:你建立一個表單來編輯用戶的資料信息(User Profile), 用戶能夠添加他的公司位置,地址, 國家城市等等,我不肯意從Action到View中傳輸公司位置 ,地址和國家城市。我只願意經過用戶資料自己(User Profile), 我只想在 Action 中處理用戶資料(User Profile)。這時候能夠注入服務來給我查詢數據,這就是爲何這種狀況下它是很是有用的。它可讓咱們的Action和ViewModel 保持很是的乾淨。

Startup.cs中的ConfigureServices來註冊你具體的服務,而後你就能夠在視圖中這樣來使用,只須要一行代碼:

@inject DiViews.Services.ICountryService CountryService;

如今你能夠在你的視圖中使用ContryService來填充國家下拉列表。

我在這篇博客中寫了不少關於依賴注入的博文。

#9: 函數(Functions)

在一個ASP.NET MVC 項目中,我歷來沒有真正的使用過函數這個功能。我只在一個Umbraco的CMS系統中用過一次。無論怎麼說,這也是擴展你視圖的另外一種小技巧。也許你有很複雜視圖方面的業務邏輯,在這種狀況下,你能夠在你的視圖中寫C#方法:

@functions
{
    public string ReverseString(string input)
    {
        return String.Join("", input.Reverse());
    }
}

#10: 配置全局視圖(Global view configuration)

最後一點,你能夠在_ViewImports.cshtml文件中,來配置你其餘視圖中使用的一些比較公用的 using 引用,依賴注入等。

總結

不論是之前的MVC仍是新的Core MVC, 都有不少方法來擴展視圖,雖然擴展這些視圖的方式有些相似,可是每一種都有它最適合的地方,因此咱們在使用這些特性來解決咱們的問題的時候,咱們應該多加思考,找到最合適的方式。

譯者注:本文翻譯並不是逐字翻譯,因爲水平有限,不免出現一些錯誤和翻譯不許確的地方,但願讀者可以指出並堪正,不勝感激。

相關文章
相關標籤/搜索