問題
如何在ASP.NET Core 2.0中使用視圖組件?
答案
新建一個空項目,修改Startup類並添加MVC服務和中間件:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
添加一個模型類:
public class UserInfoViewModel
{
public int UserId { get; set; }
public string UserName { get; set; }
public string LastLogin { get; set; }
}
添加繼承自ViewComponent的自定義視圖組件:
public class UserInfoViewComponent : ViewComponent
{
public IViewComponentResult Invoke(int userId)
{
var model = new UserInfoViewModel
{
UserId = userId,
UserName = "james@bond.com",
LastLogin = DateTime.Now.ToString()
};
return View(model);
}
}
添加視圖組件對應的視圖文件(Views/Shared/Components/UserInfo/Default.cshtml):
@using ViewComponents.Models
@model UserInfoViewModel
<div style="border: 1px dotted blue; margin: 5px">
<h3>User Info</h3>
<p>UserId: @Model.UserId</p>
<p>UserName: @Model.UserName</p>
<p>Last Login: @Model.LastLogin</p>
</div>
添加一個控制器和相應的視圖文件:
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}
@using ViewComponents.Models
<div style="border: 1px solid black; margin: 5px">
<h2>Home/Index</h2>
@await Component.InvokeAsync("UserInfo", new { UserId = 5 })
</div>
現在,我們來看下解決方案的目錄層次:

運行,此時頁面顯示:

討論
視圖組件是渲染到其他視圖內部的一種特殊類型。對於重用視圖中的公共部分或者將大的視圖分隔成小組件都非常有用。
與部分視圖不同,視圖組件不依賴於控制器。它們有自己的類來控制組件用到的模型以及視圖模板來生成最終呈現的HTML/CSS。
我喜歡把它們看作是小型控制器,盡管這並不完全正確,但是有助於我們了解它們的用法。和控制器不同,視圖組件不處理HTTP請求,也沒有控制器的生命周期,這就意味着在視圖組件中不能使用過濾器和模型綁定。
視圖組件可以使用依賴注入,這使得它們更加強大和易於測試。
創建
有很多方法創建視圖組件,我們會討論最常用到的選項:
- 創建一個類(放到項目中的任意位置),使其繼承自抽象基類ViewComponent。
- 按照約定,請將類名以ViewComponent結尾。
- 創建一個返回IViewComponentResult的方法Invoke。
- 這個方法可以接受任意數量的參數,這些參數會在調用視圖組件時傳入。
- 將基類ViewComponent的方法View()作為Invoke的返回值,你也可以向其中傳入自定義模型。
- 可選的,你也可以在參數中指定視圖頁面的名稱。
基類ViewComponent通過屬性公開了很多有用的細節,比如HttpContext,RouteData,IUrlHelper,IPrincipal和ViewData。
調用
可以通過兩種方式調用視圖組件:
- 在視圖頁面中調用@await Component.InvokeAsync(component, parameters)
- 在控制器方法中,返回ViewComponent(component, parameters)
上面調用中的component是一個指向組件類的字符串。
當調用視圖組件時,InvokeAsync()方法可以接受任意數量的參數,這些參數可以通過匿名對象傳入。
發現
ASP.NET Core會按照如下順序查找視圖組件的Razor頁面:
- Views/[controller]/Components/[component]/[view].cshtml
- Views/Shared/Components/[component]/[view].cshtml
其中[component]匹配如下規則:
- 除去ViewComponent后綴的組件名。
- 視圖組件類上面[ViewComponent]特性所指定的值
其中[view]缺省值是Default,當然我們也可以在視圖組件的Invoke方法中返回特定的值。比如下面的組件指定視圖名稱為MyInfo.cshtml:
public IViewComponentResult Invoke(int userId)
{
var model = new UserInfoViewModel
{
UserId = userId,
UserName = "james@bond.com",
LastLogin = DateTime.Now.ToString()
};
return View("MyInfo", model);
}
本例中,如果我們刪除視圖組件對應的Razor頁面,此時會有異常,從而我們能夠清楚看到系統的查找順序:

源代碼下載
原文:https://tahirnaushad.com/2017/08/24/asp-net-core-2-0-mvc-view-components/
