2024年9月30日 星期一

使用scaffold功能設計Blazor應用程式 - 1

作 者:許薰尹

出刊日期:2024/9/4

Visual Studio 2022開發工具提供的最新.NET 8 Blazor Web App樣板專案可以搭配scaffold功能,快速地產生使用 Blazor 靜態伺服器端轉譯(Blazor static server rendering),和「QuickGrid」元件來顯示資料庫中表格式資料的程式碼。

Visual Studio 2022產生的.NET 8 Blazor Web App樣板預設以Entity Framework Core為基礎來產生資料模型的基本新增、讀取、修改和刪除 (CRUD) 頁面。根據需求,你可以單獨產成每一個頁面,或一次性生成所有 CRUD 的頁面。

不過要特注意的是:使用scaffold功能產生出的CRUD頁面只適用在伺服器轉譯(server-side rendering),不適用WebAssembly。

在這篇文章中,我們將使用一步步來說明如何使用scaffold功能產生資料模型的基本新增、讀取、修改和刪除 (CRUD) 頁面。



建立Blazor專案


首先使用Visual Studio 2022開發工具建立一個.NET 8 Web App專案,建立步驟如下:啟動Visual Studio 2022開發環境,從「開始」視窗選取「Create a new project」選項。從Visual Studio 2022開發工具的「Create a new project」對話盒中,選取 使用C# 語法的「Blazor Web App 」項目,然後按一下「Next」按鈕,請參考下圖所示:



圖 1:「Blazor Web App 」項目。


下一步,在「Configure your new project」視窗中,設定Blazor專案名稱與專案存放路徑,例如「RazorScaffold」,然後按下「Next」按鈕,請參考下圖所示:




圖 2:設定Blazor專案名稱與專案存放路徑。


下一步,在「Additional information」視窗中,設定「Target Framework」為「NET 8.0 (Long Term Support)」;將「Authentication Type」設為「None」;「Interactive render mode」選擇「Auto(Server and WebAssembly)」;「Interactivity location」設定為「Per page/component」,然後勾選「Include sample 」pages」,然後按下「Create」按鈕,請參考下圖所示:



圖 3:設定「Target Framework」為「NET 8.0 (Long Term Support)」。


設計資料模型(Data Models)


在專案中加入「Employee」資料模型(Data Models)描述員工資料。

在「RazorCRUD」專案建立「Models」資料夾。從「Solution Explorer」視窗 >專案名稱上方按滑鼠右鍵,從快捷選單選擇「Add」>「New Folder」選項,將資料夾名稱設定為「Models」。

加入一個模型類別(Model Class)描述圖書資料。從「Solution Explorer」視窗專案名稱「Models」資料夾上方按滑鼠右鍵,從快捷選單選擇「Add」> 「Class」項目,選取「Class」,將名稱設定為「Employee」,然後按下「Add 」按鈕,然後在「Employee」類別之中加入以下程式碼:

 

1
2
3
4
5
6
7
8
9
10
11
namespace BlazorScaffold.Models
{
    public class Employee
    {
        public int EmployeeId { get; set; }
        public string? EmployeeName { get; set; }
        public DateTime BirthDay { get; set; }
        public bool IsMarried { get; set; }
        public string? Department { get; set; }
    }
}





「Employee」類別用於表示員工的資訊。它具有以下屬性:

  • 「EmployeeId」:表示員工的編號,整數型別。
  • 「EmployeeName」:表示員工的姓名,型別為字串。這裡使用了可為空值的問號(?),表示該屬性可以為空值。
  • 「BirthDay」:表示員工的生日,型別為「DateTime」。
  • 「IsMarried」:表示員工是否已婚,型別為布林值。
  • 「Department」:表示員工所屬的部門,型別為字串。同樣地,這裡也使用了可為空值的問號(?)。

 


使用Scaffold功能產生程式


從「Solution Explorer」視窗 >「Pages」資料夾上方按滑鼠右鍵,從快捷選單選擇「Add」>「New Scaffolded Item」項目,請參考下圖所示:

 



圖 4:「New Scaffolded Item」項目。

在「Add NewScaffolded Item」視窗中選取「Razor Component using Entity Framework (CRUD)」項目,請參考下圖所示:




圖 5:「Razor Component using Entity Framework (CRUD)」項目。
在「Add Razor Components using Entity Framework (CRUD)」視窗中,「Template」項目選取「CRUD」;「Model class」項目選取「Employee」;點選「DbContext class」項目右方的「+」按鈕,新增「DbContext」類別,請參考下圖所示:



圖 6:新增「DbContext」類別。
接下來會出現「Add Data Context」視窗,為類別取一個名稱,例如本例的「BlazorScaffold.Data. BlazorScaffoldContext」類別,然後按「Add」按鈕,請參考下圖所示:



圖 7:定義「DbContext」類別名稱。


下一步會回到「Add Razor Components using Entity Framework (CRUD)」視窗,「Database provider」項目選取「SQL Server」項目,然後按「Add」按鈕,請參考下圖所示:




圖 8:「Database provider」項目選取「SQL Server」項目。

Visual Studio 2022開發工具會自動在專案之中安裝「Microsoft.EntityFrameworkCore.SqlServer」、「Microsoft.EntityFrameworkCore.Tools」與「Microsoft.VisualStudio.Web.CodeGeneration.Design」等等開發所需的套件,你可以從專案檔案的內容來得知相關資訊,參考如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<Project Sdk = "Microsoft.NET.Sdk.Web">
 
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>
 
  <ItemGroup>
    <ProjectReference Include = "..\BlazorScaffold.Client\BlazorScaffold.Client.csproj" />
    <PackageReference Include = "Microsoft.AspNetCore.Components.QuickGrid.EntityFrameworkAdapter" Version = "8.0.4" />
    <PackageReference Include = "Microsoft.AspNetCore.Components.WebAssembly.Server" Version = "8.0.6" />
    <PackageReference Include = "Microsoft.EntityFrameworkCore.SqlServer" Version = "8.0.4" />
    <PackageReference Include = "Microsoft.EntityFrameworkCore.Tools" Version = "8.0.4">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include = "Microsoft.VisualStudio.Web.CodeGeneration.Design" Version = "8.0.2" />
  </ItemGroup>
 
</Project>



此外Visual Studio 2022開發工具會自動修改「Program.cs」檔案,註冊Entity Framework Core服務,參考以下程式碼叫用「IServiceCollection」的「AddDbContext」方法,註冊「BlazorScaffoldContext」類別,並使用「Configuration.GetConnectionString」方法讀取「appsettings.json」檔案中的連接字串,以連結到SQL Server Express伺服器的資料庫。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
using BlazorScaffold.Client.Pages;
using BlazorScaffold.Components;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using BlazorScaffold.Data;
using Microsoft.AspNetCore.Identity;
 
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<BlazorScaffoldContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("BlazorScaffoldContext") ?? throw new InvalidOperationException("Connection string 'BlazorScaffoldContext' not found.")));
 
builder.Services.AddQuickGridEntityFrameworkAdapter();;
 
// Add services to the container.
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents()
    .AddInteractiveWebAssemblyComponents();
 
var app = builder.Build();
 
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseWebAssemblyDebugging();
}
else
{
    app.UseExceptionHandler("/Error", createScopeForErrors: true);
    // 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.UseAntiforgery();
 
app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode()
    .AddInteractiveWebAssemblyRenderMode()
    .AddAdditionalAssemblies(typeof(BlazorScaffold.Client._Imports).Assembly);
 
app.Run();

 


Visual Studio 2022開發工具預設會在「appsettings.json」檔案產生連接到Localdb的連接字串,參考以下「appsettings.json」檔案程式碼,讓我們修改連接字串指向想用的SQL Server Express伺服器的資料庫,設定連接字串的資料庫伺服器為「.\sqlexpress」;資料庫為「BlazorScaffoldDb」,並使用Windows驗證連接到資料庫:

 

1
2
3
4
5
6
7
8
9
10
11
12
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "BlazorScaffoldContext": "Server=.\\sqlexpress;;Database=BlazorScaffoldDb;TrustServerCertificate=True;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}




Visual Studio 2022開發工具會自「Data」資料夾產生一個「BlazorScaffoldContext.cs」檔案,其中的程式碼在「BlazorScaffoldContext」類別的上方引用「Microsoft.EntityFrameworkCore」命名空間;而「BlazorScaffoldContext」類別繼承自「DbContext」類別。類別中定義一個名為「Employees」、型別為「DbSet」的屬性,並且使用相依性插入(Depenency Injection)在建構函式中插入服務,以取得「DbContextOptions」,此物件將包含從組態檔案(appsettings.json)取得的資料庫連線字相關資訊。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using Microsoft.EntityFrameworkCore;
 
namespace BlazorScaffold.Data
{
    public class BlazorScaffoldContext : DbContext
    {
        public BlazorScaffoldContext( DbContextOptions<BlazorScaffoldContext> options )
            : base( options )
        {
        }
 
        public DbSet<BlazorScaffold.Models.Employee> Employees { get; set; } = default!;
    }
 
}

 

設計選單


為了方便操作,修改「NavMenu.razor」檔案程式碼,在應用程式的導覽選單中建立一個導覽項目,定義了一個指向員工列表頁面「employees」的連結:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<div class = "top-row ps-3 navbar navbar-dark">
    <div class = "container-fluid">
        <a class = "navbar-brand" href = "">BlazorScaffold</a>
    </div>
</div>
 
<input type = "checkbox" title = "Navigation menu" class = "navbar-toggler" />
 
<div class = "nav-scrollable" onclick = "document.querySelector('.navbar-toggler').click()">
    <nav class = "flex-column">
        <div class = "nav-item px-3">
            <NavLink class = "nav-link" href = "" Match = "NavLinkMatch.All">
                <span class = "bi bi-house-door-fill-nav-menu" aria-hidden = "true"></span> Home
            </NavLink>
        </div>
        <div class = "nav-item px-3">
            <NavLink class = "nav-link" href = "employees">
                <span class = "bi bi-plus-square-fill-nav-menu" aria-hidden = "true"></span> Employees
            </NavLink>
        </div>
 
        <div class = "nav-item px-3">
            <NavLink class = "nav-link" href = "counter">
                <span class = "bi bi-plus-square-fill-nav-menu" aria-hidden = "true"></span> Counter
            </NavLink>
        </div>
 
        <div class = "nav-item px-3">
            <NavLink class = "nav-link" href = "weather">
                <span class = "bi bi-list-nested-nav-menu" aria-hidden = "true"></span> Weather
            </NavLink>
        </div>
    </nav>
</div>

0 意見:

張貼留言