今天在看 Scott Guthrie 的一篇博文《Introducing ASP.NET 5》,在 MVC 6 中,發現有些之前不曉得的寫法,這邊簡單記錄下,算是對自己知識的補充,有些我並沒有進行嘗試,因為我使用的 Visual Studio 2015 CTP 5,但是有些並沒有支援(下面第一點),現在 Visual Studio 2015 已經更新到 CTP 6 了,本來還想嘗試下,看了下 4.6G 的大小,想想還是算了。
- Visual Studio 2015 CTP 6(說明及下載)
Scott Guthrie 博文中,大部分是對 ASP.NET 5 的綜述,有些內容之前微軟都已經發布過了,我只看了自己看興趣的地方,當然評論內容也是不能漏掉的,除了這篇博文,我還搜刮了其他博文的一些內容,下面簡單介紹下。
1. 統一開發模型
普通寫法:
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.UserName, "", new { @class = "text-danger" })
</div>
</div>
另類寫法:
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="UserName" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="UserName" class="form-control" />
<span asp-validation-for="UserName" class="text-danger"></span>
</div>
</div>
上面一般是我們在 View 寫表單程式碼時候的寫法,很明顯,第二種比第一種更加簡潔!
2. Dependency injection (DI) 寫法
在 MVC 6 中是支援 DI 的,像 services.AddMvc();
就是 MVC 6 使用自帶的 IoC 進行注入,當然,除了注入這些 MVC 系統元件,我是沒有在 ConfigureServices 中使用過自定義的物件注入,所以,我也是第一次曉得注入使用寫法,示例:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddTransient<TimeService>();
}
TimeService 是一個自定義的型別,使用 AddTransient 方法,在 ConfigureServices 中進行註冊。
public class HomeController : Controller
{
[Activate]
public TimeService TimeService { get; set; }
// Code removed for brevity
}
Activate 為注入物件屬性,當然,你也可以使用建構函式進行注入,只不過是麻煩些。
@using WebApplication23
@inject TimeService TimeSvc
<h3>@ViewBag.Message</h3>
<h3>
@TimeSvc.Ticks From Razor
</h3>
上面為獲取注入的物件,關鍵字為 inject。
3. View components 的一些內容
View components(VCs) ,我是第一次看到這個詞,當然更沒用過,component 是要素、組成、零件的意思,View components 可以理解為檢視的補充,微軟在介紹的時候,用到了一個詞 mini-controller,可以看作是“微型控制器”,其實,像 @Html.LabelFor
這種寫法也可以看作是 VC,說通俗一點,就是我們針對專案,寫的一些幫助類。
建立 ViewComponent:
using System.Linq;
using Microsoft.AspNet.Mvc;
using TodoList.Models;
namespace TodoList.ViewComponents
{
//[ViewComponent(Name = "PriorityList")]
public class PriorityListViewComponent : ViewComponent
{
private readonly ApplicationDbContext db;
public PriorityListViewComponent(ApplicationDbContext context)
{
db = context;
}
public IViewComponentResult Invoke(int maxPriority)
{
var items = db.TodoItems.Where(x => x.IsDone == false &&
x.Priority <= maxPriority);
return View(items);
}
}
}
建立的 PriorityListViewComponent 需要繼承 ViewComponent,ViewComponent 是對 ViewComponent 名字的重寫。
@{
ViewBag.Title = "ToDo Page";
}
<div class="jumbotron">
<h1>ASP.NET vNext</h1>
</div>
<div class="row">
<div class="col-md-4">
@Component.Invoke("PriorityList", 1)
</div>
</div>
上面是 ViewComponent 的呼叫程式碼,寫法是 Component.Invoke,第一個引數是 ViewComponent 的類名,也可以是屬性的重寫名,第二個引數是優先順序值,用於過濾我們要處理的項集合。
這是 ViewComponent Invoke 同步寫法,也是最簡單的一種,但是這種寫法,現在已經在 MVC 6 中被移除了,說明:The synchronous Invoke method has been removed. A best practice is to use asynchronous methods when calling a database.
InvokeAsync 寫法:
public async Task<IViewComponentResult> InvokeAsync(int maxPriority, bool isDone)
{
string MyView = "Default";
// If asking for all completed tasks, render with the "PVC" view.
if (maxPriority > 3 && isDone == true)
{
MyView = "PVC";
}
var items = await GetItemsAsync(maxPriority, isDone);
return View(MyView, items);
}
呼叫程式碼:
@model IEnumerable<TodoList.Models.TodoItem>
<h2> PVC Named Priority Component View</h2>
<h4>@ViewBag.PriorityMessage</h4>
<ul>
@foreach (var todo in Model)
{
<li>@todo.Title</li>
}
</ul>
@await Component.InvokeAsync("PriorityList", 4, true)
注意 ViewBag.PriorityMessage 的值,上面程式碼指定了檢視名稱。
4. 注入一個服務到檢視
服務注入到檢視,就是使用的上面第二點 DI 寫法,示例服務:
using System.Linq;
using System.Threading.Tasks;
using TodoList.Models;
namespace TodoList.Services
{
public class StatisticsService
{
private readonly ApplicationDbContext db;
public StatisticsService(ApplicationDbContext context)
{
db = context;
}
public async Task<int> GetCount()
{
return await Task.FromResult(db.TodoItems.Count());
}
public async Task<int> GetCompletedCount()
{
return await Task.FromResult(
db.TodoItems.Count(x => x.IsDone == true));
}
}
}
ConfigureServices 中註冊:
// This method gets called by the runtime.
public void ConfigureServices(IServiceCollection services)
{
// Add MVC services to the services container.
services.AddMvc();
services.AddTransient<TodoList.Services.StatisticsService>();
}
呼叫程式碼:
@inject TodoList.Services.StatisticsService Statistics
@{
ViewBag.Title = "Home Page";
}
<div class="jumbotron">
<h1>ASP.NET vNext</h1>
</div>
<div class="row">
<div class="col-md-4">
@await Component.InvokeAsync("PriorityList", 4, true)
<h3>Stats</h3>
<ul>
<li>Items: @await Statistics.GetCount()</li>
<li>Completed:@await Statistics.GetCompletedCount()</li>
<li>Average Priority:@await Statistics.GetAveragePriority()</li>
</ul>
</div>
</div>
參考資料: