[鼠年全馬鐵人挑戰]Week05-ASP.NET Core 3.1 初心者入門(3)-Razor Pages

Nina Weng
9 min readMar 14, 2020

--

什麼是 Razor Pages ?

過去我們常用MVC的架構來建立我們的專案,但有時候我們的專案只是想要實現一個簡單的小功能,若使用 MVC 好像有點顯得過於複雜。這時,我們可以選擇 Razor Pages
MVC 代表著 Models、View、Controller。Model 存放我們的資料模型;View 是一個存放 HTML 與 Tag Helper 的cshtml檔;Controller 則存放邏輯。而 Razor Pages 就是一個讓我們可以將這三個元素定義在一起的 View。

實作要點

Startup.cs

首先我們在 Startup.cs 的 ConfigureServices method 中添加 Razor Pages。

public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages(); // 加入這行
services.AddSingleton<IConferenceService, ConferenceMemoryService>();
services.AddSingleton<IProposalService, ProposalMemoryService>();
}

而在 Configure method中,選擇使用 razor pages 來決定這個專案的 endpoint。所以加入了這行endpoints.MapRazorPages()程式後,專案的 endpoint 會由專案目錄底下的 Pages 目錄裡面的 cshtml 檔來決定。但網址並不需要加入.cshtml。舉例來說,目錄底下的 .../Pages/Index.cshtml 則對應到的URL為 .../Index 或是 .../

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}

Shard/_Layout.cshtml

定義我們常用共用的 layout。

_ViewStart.cshtml

而上面定義的 layouts 由 ViewStart 決定啟用哪個 layout 。

DisplayTemplates/xxx.cshtml

定義一些我們常用重複使到的 templates。

xxx.cshtml

@page
@using GlobomanticsRazorPages.Services
@using GlobomanticsRazorPages.Models
@inject IConferenceService conferenceService
<div class="row">
<div class="col-md-10 col-md-offset-2">
<table class="table">
<tr>
<th>Name</th>
<th>Location</th>
<th>Start of event</th>
<th>Attendees</th>
<th>Actions</th>
</tr>
@Html.DisplayFor(m => m.Conferences)
</table>
</div>
</div>
<div class="row">
<div class="col-md-4">
<a asp-page="Conferences/AddConference">Add</a>
</div>
</div>
@functions {
public IEnumerable<ConferenceModel> Conferences { get; private set; }
public async Task OnGet()
{
Conferences = await conferenceService.GetAll();
}
}

可以看到上面程式第四行 @inject IConferenceService conferenceService ,我們可以使用關鍵字@inject來注入我們的Service。
還有一點不同的是, <a asp-page="Conferences/AddConference">Add</a> ,可以看到我們使用的是 <a asp-page=...> 這個tag,來導向我們定義好的Pages。
而最下面我們可以看到由Razor定義的function @functions

若你是不喜歡把functions寫在HTML下面的人,你可以把這些function寫在 xxx.cshtml.cs 裡面,而這個cs檔繼承 PageModel 就可以囉,如下:

using System.Threading.Tasks;
using GlobomanticsRazorPages.Models;
using GlobomanticsRazorPages.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace GlobomanticsRazorPages.Pages
{
public class AddConferenceModel : PageModel
{
private readonly IConferenceService conferenceService;
[BindProperty]
public ConferenceModel Conference { get; set; }
public AddConferenceModel(IConferenceService conferenceService)
{
this.conferenceService = conferenceService;
}
public async Task<IActionResult> OnPost()
{
if (!ModelState.IsValid)
{
return Page();
}
await conferenceService.Add(Conference);
return RedirectToPage("/Index");
}
}

另外可以看到上面的ConferenceModel Conference,使用了BindProperty。這讓我們在cshtml可以直接去使用Conference。如下:

@page
@model GlobomanticsRazorPages.Pages.AddConferenceModel
<form method="post">
<div class="row form-group">
<div class="col-md-2 col-md-offset-2">
<label asp-for="Conference.Name"></label>
</div>
<div class="col-md-2">
<input class="form-control" asp-for="Conference.Name" />
</div>
</div>
<div class="row form-group">
<div class="col-md-2 col-md-offset-2">
<label asp-for="Conference.Location"></label>
</div>
<div class="col-md-2">
<input class="form-control" asp-for="Conference.Location" />
</div>
</div>
<div class="row form-group">
<div class="col-md-2 col-md-offset-2">
<label asp-for="Conference.Start"></label>
</div>
<div class="col-md-2">
<input class="form-control" type="date" asp-for="Conference.Start" />
</div>
</div>
<div class="row form-group">
<div class="col-md-2 col-md-offset-2">
<label asp-for="Conference.AttendeeTotal"></label>
</div>
<div class="col-md-2">
<input class="form-control" type="number" asp-for="Conference.AttendeeTotal" />
</div>
</div>
<div class="row">
<div class="col-md-2 col-md-offset-4">
<button type="submit" class="btn btn-primary">Add</button>
</div>
</div>
</form>

可以看到要存取Conference的值,只要用 Conference.xxx 就可以了,是不是很方便!

結語

今天小簡介了 Razor Pages 的架構。我也是邊學邊做筆記的,有錯誤還麻煩各位大大指正,感恩!!

--

--

Nina Weng
Nina Weng

Written by Nina Weng

一個技能雜亂點的菜鳥工程師。因為實在太菜,有太多東西要學而不知所措。與其把時間花在猶豫不決不知從何開始,不如先開始,然後再漸漸深入專研某一項技能吧!

No responses yet