預先轉譯並整合 ASP.NET Core Razor 元件
注意
這不是這篇文章的最新版本。 如需本文的最新版本,請參閱 .NET 7 版本。
本文說明 Blazor 應用程式的 Razor 元件整合案例,包括預先轉譯伺服器上的 Razor 元件。
重要
不同 ASP.NET Core 版本的架構變更,導致本文提供了不同的指示集。 使用本文的指引之前,請確認此頁面上的文件版本選取器符合您要用於應用程式的 ASP.NET Core 版本。
Razor 元件可整合至託管 Blazor WebAssembly解決方案中的 Razor Pages 與 MVC 應用程式。 轉譯頁面或檢視時,可以同時預先轉譯元件。
預先轉譯可藉由轉譯初始 HTTP 回應的內容來改善搜尋引擎最佳化 (SEO),讓搜尋引擎可使用該回應來計算頁面排名。
解決方案設定
預先轉譯設定
若要為託管 Blazor WebAssembly 應用程式設定預先轉譯:
在 ASP.NET Core 應用程式中裝載 Blazor WebAssembly 應用程式。 獨立 Blazor WebAssembly 應用程式可新增至 ASP.NET Core 解決方案,或者,您可以使用透過託管選項從 Blazor WebAssembly 專案範本建立的託管 Blazor WebAssembly 應用程式:
- Visual Studio:建立 Blazor WebAssembly 應用程式時,在 [其他資訊] 對話方塊中選取 [已託管 ASP.NET Core] 核取方塊。 在本文中的範例中,解決方案的名稱為
BlazorHosted
。 - Visual Studio Code/.NET CLI 命令殼層:
dotnet new blazorwasm -ho
(使用-ho|--hosted
選項)。 使用-o|--output {LOCATION}
選項建立解決方案的資料夾,並設定解決方案的專案命名空間。 在本文中的範例中,解決方案的名稱為BlazorHosted
(dotnet new blazorwasm -ho -o BlazorHosted
)。
在本文的範例中,託管解決方案的名稱 (組件名稱) 為
BlazorHosted
。 用戶端專案的命名空間為BlazorHosted.Client
,而伺服器專案的命名空間為BlazorHosted.Server
。- Visual Studio:建立 Blazor WebAssembly 應用程式時,在 [其他資訊] 對話方塊中選取 [已託管 ASP.NET Core] 核取方塊。 在本文中的範例中,解決方案的名稱為
從 Blazor WebAssemblyClient 專案中刪除
wwwroot/index.html
檔案。在 Client 專案中,刪除
Program.cs
中的以下幾行:- builder.RootComponents.Add<App>("#app"); - builder.RootComponents.Add<HeadOutlet>("head::after");
將
_Host.cshtml
檔案新增至 Server 專案的Pages
資料夾。 您可以使用 Visual Studio 從透過 Blazor Server 範本建立的專案中取得檔案,或使用 .NET CLI 搭配命令殼層中的dotnet new blazorserver -o BlazorServer
命令來取得 (-o BlazorServer
選項會建立專案的資料夾)。 將檔案放入 Server 專案的Pages
資料夾中後,請對檔案進行下列變更。對
_Host.cshtml
檔案進行下列變更:更新檔案頂端的
Pages
命名空間,以符合 Server 應用程式頁面的命名空間。 下列範例中的{APP NAMESPACE}
預留位置代表提供_Host.cshtml
檔案的捐贈者應用程式頁面的命名空間:刪除:
- @namespace {APP NAMESPACE}.Pages
新增:
@namespace BlazorHosted.Server.Pages
在檔案頂端為 Client 專案新增
@using
指示詞:@using BlazorHosted.Client
更新樣式表連結,以指向 WebAssembly 專案的樣式表。 在下列範例中,用戶端專案的命名空間為
BlazorHosted.Client
。{APP NAMESPACE}
預留位置代表提供_Host.cshtml
檔案的捐贈者應用程式的命名空間。 更新HeadOutlet
元件的元件標籤協助程式 (<component>
標籤),以預先轉譯元件。刪除:
- <link href="css/site.css" rel="stylesheet" /> - <link href="{APP NAMESPACE}.styles.css" rel="stylesheet" /> - <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
新增:
<link href="css/app.css" rel="stylesheet" /> <link href="BlazorHosted.Client.styles.css" rel="stylesheet" /> <component type="typeof(HeadOutlet)" render-mode="WebAssemblyPrerendered" />
注意
將要求 Bootstrap 樣式表 (
css/bootstrap/bootstrap.min.css
) 的<link>
元素保留在原處。更新 Blazor 指令碼來源以使用用戶端 Blazor WebAssembly 指令碼:
刪除:
- <script src="_framework/blazor.server.js"></script>
新增:
<script src="_framework/blazor.webassembly.js"></script>
更新元件標籤協助程式的
render-mode
,以使用 WebAssemblyPrerendered 預先轉譯根App
元件:刪除:
- <component type="typeof(App)" render-mode="ServerPrerendered" />
新增:
<component type="typeof(App)" render-mode="WebAssemblyPrerendered" />
重要
驗證端點 (
/authentication/
路徑線段) 不支援預先轉譯。 如需詳細資訊,請參閱 ASP.NET Core Blazor WebAssembly 的其他安全性案例。
在 Server 專案的
Program.cs
檔案中,將後援端點從index.html
檔案變更為_Host.cshtml
頁面:刪除:
- app.MapFallbackToFile("index.html");
新增:
app.MapFallbackToPage("/_Host");
如果 Client 和 Server 專案在預先轉譯期間使用一或多個一般服務,請將服務註冊納入可從這兩個專案呼叫的方法中。 如需詳細資訊,請參閱 ASP.NET Core Blazor 相依性插入。
執行 Server 專案。 託管 Blazor WebAssembly 應用程式會由用戶端的 Server 專案預先轉譯。
將 Razor 元件內嵌至頁面和檢視中的設定
在下列各節和範例中,將 Razor 元件從 ClientBlazor WebAssembly 應用程式內嵌至伺服器應用程式的頁面和檢視中,需要額外的設定。
Server 專案必須具有下列檔案和資料夾。
Razor Pages:
Pages/Shared/_Layout.cshtml
Pages/Shared/_Layout.cshtml.css
Pages/_ViewImports.cshtml
Pages/_ViewStart.cshtml
MVC:
Views/Shared/_Layout.cshtml
Views/Shared/_Layout.cshtml.css
Views/_ViewImports.cshtml
Views/_ViewStart.cshtml
使用下列途徑從 ASP.NET Core 專案範本產生應用程式,可取得上述檔案:
- Visual Studio 新的專案建立工具。
- 開啟命令殼層並執行
dotnet new webapp -o {PROJECT NAME}
(Razor Pages) 或dotnet new mvc -o {PROJECT NAME}
(MVC)。 具有{PROJECT NAME}
預留位置值的選項-o|--output
會提供應用程式的名稱,並且為應用程式建立資料夾。
在匯入的 _ViewImports.cshtml
檔案中更新命名空間,以符合接收檔案的 Server 專案所使用的命名空間。
Pages/_ViewImports.cshtml
(Razor Pages):
@using BlazorHosted.Server
@namespace BlazorHosted.Server.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
Views/_ViewImports.cshtml
(MVC):
@using BlazorHosted.Server
@using BlazorHosted.Server.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
更新匯入的配置檔案,即適用於 Razor Pages 的 Pages/Shared/_Layout.cshtml
或適用於 MVC 的 Views/Shared/_Layout.cshtml
。
首先,從捐贈者專案中刪除標題和樣式表 (在下列範例中為 RPDonor.styles.css
)。 {PROJECT NAME}
預留位置代表捐贈者專案的應用程式名稱。
- <title>@ViewData["Title"] - {PROJECT NAME}</title>
- <link rel="stylesheet" href="~/RPDonor.styles.css" asp-append-version="true" />
在配置檔案中包含 Client 專案的樣式。 在下列範例中,Client 專案的命名空間為 BlazorHosted.Client
。 <title>
元素可以同時更新。
將以下幾行放在配置檔案的 <head>
內容中:
<title>@ViewData["Title"] - BlazorHosted</title>
<link href="css/app.css" rel="stylesheet" />
<link rel="stylesheet" href="BlazorHosted.Client.styles.css" asp-append-version="true" />
<component type="typeof(HeadOutlet)" render-mode="WebAssemblyPrerendered" />
匯入的配置包含兩個 Home
(Index
頁面) 和 Privacy
瀏覽連結。 若要使 Home
連結指向託管 Blazor WebAssembly 應用程式,請變更超連結:
- <a class="navbar-brand" asp-area="" asp-page="/Index">{PROJECT NAME}</a>
+ <a class="navbar-brand" href="/">BlazorHosted</a>
- <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>
在 MVC 配置檔案中:
- <a class="navbar-brand" asp-area="" asp-controller="Home"
- asp-action="Index">{PROJECT NAME}</a>
+ <a class="navbar-brand" href="/">BlazorHosted</a>
- <a class="nav-link text-dark" asp-area="" asp-controller="Home"
- asp-action="Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>
更新 <footer>
元素的應用程式名稱。 下列範例使用應用程式名稱 BlazorHosted
:
- © {DATE} - {DONOR NAME} - <a asp-area="" asp-page="/Privacy">Privacy</a>
+ © {DATE} - BlazorHosted - <a asp-area="" asp-page="/Privacy">Privacy</a>
在上述範例中,{DATE}
預留位置代表從 Razor Pages 或 MVC 專案範本產生的應用程式中的著作權日期。
若要使 Privacy
連結導向 privacy 頁面 (Razor 頁面),請將 privacy 頁面新增至 Server 專案。
Server 專案中的 Pages/Privacy.cshtml
:
@page
@model PrivacyModel
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
<p>Use this page to detail your site's privacy policy.</p>
針對以 MVC 為基礎的 privacy 檢視,請在 Server 專案中建立 privacy 檢視。
Server 專案中的 View/Home/Privacy.cshtml
:
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
<p>Use this page to detail your site's privacy policy.</p>
在 MVC 應用程式的 Home
控制器中,傳回檢視。
將下列程式碼新增至 Controllers/HomeController.cs
:
public IActionResult Privacy()
{
return View();
}
如果您從捐贈者應用程式中匯入檔案,請務必更新檔案中的任何命名空間,以符合 Server 專案的命名空間 (例如 BlazorHosted.Server
)。
從捐贈者專案的 wwwroot
資料夾中,將靜態資產匯入至 Server 專案:
wwwroot/css
資料夾和內容wwwroot/js
資料夾和內容wwwroot/lib
資料夾和內容
如果捐贈者專案是從 ASP.NET Core 專案範本建立的,且檔案並未修改,您可以將整個 wwwroot
資料夾從捐贈者專案複製到 Server 專案中,並移除 favicon 圖示檔案。
警告
請避免將靜態資產同時放入 Client 和 Server wwwroot
資料夾中。 如果這兩個資料夾中有相同的檔案,將會擲回例外狀況,因為靜態資產會共用相同的 Web 根目錄路徑。 因此,應在任一 wwwroot
資料夾 (而不是兩者) 中裝載靜態資產。
採用上述設定之後,將 Razor 元件內嵌至 Server 專案的頁面或檢視中。 使用本文中以下幾節的指引:
- 使用元件標籤協助程式在頁面或檢視中轉譯元件
- 使用 CSS 選取器在頁面或檢視中轉譯元件
使用元件標籤協助程式在頁面或檢視中轉譯元件
設定解決方案 (包括其他設定) 之後,元件標籤協助程式支援以兩種轉譯模式在頁面或檢視中轉譯 Blazor WebAssembly 應用程式中的元件:
在下列 Razor Pages 範例中,Counter
元件會在頁面中轉譯。 為了使元件具有互動性,頁面的轉譯區段中包含了 Blazor WebAssembly 指令碼。 若要避免將 Counter
元件的完整命名空間搭配用於元件標籤協助程式 ({ASSEMBLY NAME}.Pages.Counter
),請為用戶端專案的 Pages
命名空間新增 @using
指示詞。 在下列範例中,Client 專案的命名空間為 BlazorHosted.Client
。
在 Server 專案中,Pages/RazorPagesCounter1.cshtml
:
@page
@using BlazorHosted.Client.Pages
<component type="typeof(Counter)" render-mode="WebAssemblyPrerendered" />
@section Scripts {
<script src="_framework/blazor.webassembly.js"></script>
}
執行 Server 專案。 瀏覽至位於 /razorpagescounter1
的 Razor 頁面。 預先轉譯的 Counter
元件會內嵌在頁面中。
RenderMode 設定元件:
- 預先轉譯至頁面。
- 在頁面上轉譯為靜態 HTML,或包含從使用者代理程式啟動 Blazor 應用程式所需的資訊。
如需元件標籤協助程式的詳細資訊 (包括傳遞參數和 RenderMode 設定),請參閱 ASP.NET Core 中的元件標籤協助程式。
依據元件所使用的靜態資源,以及配置頁面在應用程式中的組織方式,可能需要額外的工作。 一般而言,指令碼會新增至頁面或檢視的 Scripts
轉譯區段,而樣式表會新增至版面配置的 <head>
元素內容。
透過轉譯片段設定子內容
元件標籤協助程式不支援接收子內容的 RenderFragment
委派 (例如 param-ChildContent="..."
)。 建議您建立一個 Razor 元件 (.razor
),參考您想要轉譯的元件以及要傳遞的子內容,然後從頁面或檢視叫用 Razor 元件。
確定發佈時不會修剪最上層的預先轉譯元件
如果元件標籤協助程式直接參考程式庫中在發佈時有可能修剪的元件,該元件在發佈期間可能會被修剪,因為用戶端應用程式程式碼並未參考該元件。 因此,元件不會預先轉譯,從而在輸出中留下空白。 如果發生這種情況,請在用戶端應用程式中的任何類別中新增 DynamicDependency
屬性,以指示修剪器保留程式庫元件。 若要保留名為 SomeLibraryComponentToBePreserved
的元件,請將下列內容新增至任何元件:
@using System.Diagnostics.CodeAnalysis
@attribute [DynamicDependency(DynamicallyAccessedMemberTypes.All,
typeof(SomeLibraryComponentToBePreserved))]
上述方法通常用不上,因為在多數情況下,應用程式會預先轉譯其元件 (未修剪),而這些元件隨後又會參考程式庫中的元件 (致使其也不會被修剪)。 只有在程式庫有可能修剪時,才需要明確使用 DynamicDependency
預先轉譯程式庫元件。
使用 CSS 選取器在頁面或檢視中轉譯元件
設定解決方案 (包括其他設定) 之後,請將根元件新增至 Program.cs
檔案中的託管 Blazor WebAssembly 解決方案的 Client 專案。 在下列範例中,Counter
元件會宣告為根元件,且有 CSS 選取器可選取 id
符合 counter-component
的元素。 在下列範例中,Client 專案的命名空間為 BlazorHosted.Client
。
在 Client 專案的 Program.cs
檔案中,將專案的 Razor 元件命名空間新增至檔案頂端:
using BlazorHosted.Client.Pages;
在 Program.cs
中建立 builder
之後,請將 Counter
元件新增為根元件:
builder.RootComponents.Add<Counter>("#counter-component");
在下列 Razor Pages 範例中,Counter
元件會在頁面中轉譯。 為了使元件具有互動性,頁面的轉譯區段中包含了 Blazor WebAssembly 指令碼。
在 Server 專案中,Pages/RazorPagesCounter2.cshtml
:
@page
<div id="counter-component">Loading...</div>
@section Scripts {
<script src="_framework/blazor.webassembly.js"></script>
}
執行 Server 專案。 瀏覽至位於 /razorpagescounter2
的 Razor 頁面。 預先轉譯的 Counter
元件會內嵌在頁面中。
依據元件所使用的靜態資源,以及配置頁面在應用程式中的組織方式,可能需要額外的工作。 一般而言,指令碼會新增至頁面或檢視的 Scripts
轉譯區段,而樣式表會新增至版面配置的 <head>
元素內容。
注意
在上述範例中,如果 Blazor WebAssembly 應用程式在使用 CSS 選取器的同時預先轉譯並整合至 Razor Pages 或 MVC 應用程式中,則會擲回 JSException。 瀏覽至其中一個 Client 專案的 Razor 元件,或瀏覽至具有內嵌元件的 Server 頁面或檢視,將會擲回一或多個 JSException。
這是正常行為,因為預先轉譯應用程式以及整合 Blazor WebAssembly 應用程式與可路由傳送的 Razor 元件,與使用 CSS 選取器並不相容。
如果您已完成以上幾節中的範例,而想了解一下 CSS 選取器在您範例應用程式中的運作情形,請在 Client 專案的 Program.cs
檔案中將 App
根元件的規格註解化:
- builder.RootComponents.Add<App>("#app");
+ //builder.RootComponents.Add<App>("#app");
瀏覽至有內嵌的 Razor 元件使用 CSS 選取器的頁面或檢視 (例如,上述範例的 /razorpagescounter2
)。 頁面或檢視會載入內嵌元件,且內嵌元件會如預期運作。
可以將 Razor 元件整合至 Razor Pages 與 MVC 應用程式中。 轉譯頁面或檢視時,可以同時預先轉譯元件。
預先轉譯可藉由轉譯初始 HTTP 回應的內容來改善搜尋引擎最佳化 (SEO),讓搜尋引擎可使用該回應來計算頁面排名。
設定專案之後,請根據專案的需求使用以下幾節中的指引:
- 對於可直接從使用者要求路由傳送的元件。 請遵循本指導,使訪客應該可在瀏覽器中對具有
@page
指示詞的元件提出 HTTP 要求。 - 對於無法直接從使用者要求路由傳送的元件,請參閱從頁面或檢視轉譯元件一節。 當應用程式使用元件標記協助程式將元件內嵌至現有的頁面和檢視時,請遵循此指導。
組態
使用下列指引,將 Razor 元件整合至現有 Razor Pages 或 MVC 應用程式的頁面和檢視中。
將具有下列內容的匯入檔案新增至專案的根資料夾。 將
{APP NAMESPACE}
預留位置變更為專案的命名空間。_Imports.razor
:@using System.Net.Http @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.JSInterop @using {APP NAMESPACE}
在專案的配置檔案 (在 Razor Pages 應用程式中的
Pages/Shared/_Layout.cshtml
或 MVC 應用程式中的Views/Shared/_Layout.cshtml
) 中:將下列
<base>
標籤和 HeadOutlet 元件標籤協助程式新增至<head>
元素:<base href="~/" /> <component type="typeof(Microsoft.AspNetCore.Components.Web.HeadOutlet)" render-mode="ServerPrerendered" />
上述範例中的
href
值 ( 應用程式基本路徑) 假設應用程式位於根 URL 路徑 (/
) 中。 如果應用程式是子應用程式,請遵循裝載及部署 ASP.NET Core Blazor (部分機器翻譯) 文章之應用程式基本路徑一節中的指導。HeadOutlet 元件是用來轉譯頁面標題 (PageTitle 元件) 和其他由 Razor 元件所設定之標題元素 (HeadContent 元件) 的標題 (
<head>
) 內容。 如需詳細資訊,請參閱在 ASP.NET Core Blazor 應用程式中控制標題內容 (部分機器翻譯)。在
Scripts
轉譯區段 (@await RenderSectionAsync(...)
) 之前立即新增blazor.server.js
指令碼的<script>
標記:<script src="_framework/blazor.server.js"></script>
架構會將
blazor.server.js
指令碼新增至應用程式。 無須手動將blazor.server.js
指令碼檔案新增至應用程式。
注意
通常配置會透過
_ViewStart.cshtml
檔案載入。在註冊服務的
Program.cs
中註冊 Blazor Server 服務:builder.Services.AddServerSideBlazor();
將 Blazor 中樞端點新增至對應路由的
Program.cs
的端點。 在MapRazorPages
(Razor Pages) 或MapControllerRoute
(MVC) 的呼叫後面放置以下這一行:app.MapBlazorHub();
將元件整合至任何頁面或檢視中。 例如,將
Counter
元件新增至專案的Shared
資料夾。Pages/Shared/Counter.razor
(Razor Pages) 或Views/Shared/Counter.razor
(MVC):<h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Razor Pages:
在專案的 Razor Pages 應用程式
Index
頁面中,新增Counter
元件的命名空間,並將元件內嵌至頁面中。 當Index
頁面載入時,系統會在頁面中轉譯Counter
元件。 在下列範例中,將{APP NAMESPACE}
預留位置以專案的命名空間取代。Pages/Index.cshtml
:@page @using {APP NAMESPACE}.Pages.Shared @model IndexModel @{ ViewData["Title"] = "Home page"; } <component type="typeof(Counter)" render-mode="ServerPrerendered" />
MVC:
在專案的 MVC 應用程式
Index
檢視中,新增Counter
元件的命名空間,並將元件內嵌至檢視中。 當Index
檢視載入時,系統會在頁面中轉譯Counter
元件。 在下列範例中,將{APP NAMESPACE}
預留位置以專案的命名空間取代。Views/Home/Index.cshtml
:@using {APP NAMESPACE}.Views.Shared @{ ViewData["Title"] = "Home Page"; } <component type="typeof(Counter)" render-mode="ServerPrerendered" />
如需詳細資訊,請參閱從頁面或檢視轉譯元件一節。
在 Razor Pages 應用程式中使用可路由傳送的元件
本節說明如何新增可直接從使用者要求路由傳送的元件。
若要在 Razor Pages 應用程式中支援可路由傳送的 Razor 元件 :
將具有下列內容的
App
元件新增至專案根目錄。App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(App).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <PageTitle>Not found</PageTitle> <p role="alert">Sorry, there's nothing at this address.</p> </NotFound> </Router>
將具有下列內容的
_Host
頁面新增至專案。 將{APP NAMESPACE}
預留位置取代為應用程式的命名空間。Pages/_Host.cshtml
:@page @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers <component type="typeof(App)" render-mode="ServerPrerendered" />
注意
上述範例假設 HeadOutlet 元件和 Blazor 指令碼 (
_framework/blazor.server.js
) 是由應用程式的配置所轉譯的。 如需詳細資訊,請參閱設定一節。RenderMode 會設定
App
元件是否:- 預先轉譯至頁面。
- 在頁面上轉譯為靜態 HTML,或包含從使用者代理程式啟動 Blazor 應用程式所需的資訊。
如需元件標籤協助程式的詳細資訊 (包括傳遞參數和 RenderMode 設定),請參閱 ASP.NET Core 中的元件標籤協助程式。
在
Program.cs
端點中,將_Host
頁面的低優先順序路由新增為最後一個端點:app.MapFallbackToPage("/_Host");
將可路由傳送的元件新增至專案。 下列範例是以 Blazor 專案範本中
Counter
元件為基礎的RoutableCounter
元件。Pages/RoutableCounter.razor
:@page "/routable-counter" <PageTitle>Routable Counter</PageTitle> <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
執行專案並瀏覽至位於
/routable-counter
之可路由傳送的RoutableCounter
元件。
如需命名空間的詳細資訊,請參閱元件命名空間一節。
在 MVC 應用程式中使用可路由傳送的元件
本節說明如何新增可直接從使用者要求路由傳送的元件。
若要在 MVC 應用程式中支援可路由傳送的 Razor 元件:
將具有下列內容的
App
元件新增至專案根目錄。App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(App).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <PageTitle>Not found</PageTitle> <p role="alert">Sorry, there's nothing at this address.</p> </NotFound> </Router>
將具有下列內容的
_Host
檢視新增至專案。 將{APP NAMESPACE}
預留位置取代為應用程式的命名空間。Views/Home/_Host.cshtml
:@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers <component type="typeof(App)" render-mode="ServerPrerendered" />
注意
上述範例假設 HeadOutlet 元件和 Blazor 指令碼 (
_framework/blazor.server.js
) 是由應用程式的配置所轉譯的。 如需詳細資訊,請參閱設定一節。RenderMode 會設定
App
元件是否:- 預先轉譯至頁面。
- 在頁面上轉譯為靜態 HTML,或包含從使用者代理程式啟動 Blazor 應用程式所需的資訊。
如需元件標籤協助程式的詳細資訊 (包括傳遞參數和 RenderMode 設定),請參閱 ASP.NET Core 中的元件標籤協助程式。
將動作新增至 Home 控制器。
Controllers/HomeController.cs
:public IActionResult Blazor() { return View("_Host"); }
在
Program.cs
端點中,為傳回_Host
檢視的控制器動作新增低優先順序路由:app.MapFallbackToController("Blazor", "Home");
在 MVC 應用程式中建立
Pages
資料夾,並新增可路由傳送的元件。 下列範例是以 Blazor 專案範本中Counter
元件為基礎的RoutableCounter
元件。Pages/RoutableCounter.razor
:@page "/routable-counter" <PageTitle>Routable Counter</PageTitle> <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
執行專案並瀏覽至位於
/routable-counter
之可路由傳送的RoutableCounter
元件。
如需命名空間的詳細資訊,請參閱元件命名空間一節。
從頁面或檢視轉譯元件
本節說明在無法直接從使用者要求路由傳送元件的情況下,如何將元件新增至頁面或檢視。
若要從頁面或檢視轉譯元件,請使用元件標籤協助程式。
轉譯具狀態互動式元件
具狀態互動式元件可以新增至 Razor 頁面或檢視。
當頁面或檢視轉譯時:
- 元件會與頁面或檢視一起預先轉譯。
- 用於預先轉譯的初始元件狀態會遺失。
- 在建立 SignalR 連線時會隨即建立新的元件狀態。
下列 Razor 頁面會轉譯 Counter
元件:
<h1>Razor Page</h1>
<component type="typeof(Counter)" render-mode="ServerPrerendered"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
如需詳細資訊,請參閱 ASP.NET Core 中的元件標籤協助程式。
轉譯非互動式元件
在下列 Razor 頁面中,Counter
元件會以使用表單指定的初始值,以靜態方式轉譯。 由於元件以靜態方式轉譯,因此元件不具互動性:
<h1>Razor Page</h1>
<form>
<input type="number" asp-for="InitialValue" />
<button type="submit">Set initial value</button>
</form>
<component type="typeof(Counter)" render-mode="Static"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
如需詳細資訊,請參閱 ASP.NET Core 中的元件標籤協助程式。
元件命名空間
在使用自訂資料夾來保存專案的 Razor 元件時,請將代表資料夾的命名空間新增至頁面/檢視或 _ViewImports.cshtml
檔案中。 在以下範例中:
- 元件會儲存在專案的
Components
資料夾中。 {APP NAMESPACE}
預留位置是專案的命名空間。Components
代表資料夾的名稱。
@using {APP NAMESPACE}.Components
_ViewImports.cshtml
檔案位於 Razor Pages 應用程式的 Pages
資料夾或 MVC 應用程式的 Views
資料夾中。
如需詳細資訊,請參閱 ASP.NET Core Razor 元件。
保存預先轉譯的狀態
若未保存預先轉譯的狀態,在預先轉譯期間所使用的狀態會遺失,而且必須在應用程式完全載入時重建。 如果以非同步方式設定了任何狀態,UI 可能會閃動,因為預先轉譯的 UI 會取代為暫時的預留位置,然後再次完整轉譯。
若要保存預先轉譯元件的狀態,請使用保存元件狀態標記協助程式 (參考來源)。 在預先轉譯元件的應用程式中 _Host
頁面的結尾 </body>
標記內,新增標記協助程式的標記 <persist-component-state />
。
注意
.NET 參考來源的文件連結通常會載入存放庫的預設分支,這表示下一版 .NET 的目前開發。 若要選取特定版本的標籤,請使用 [切換分支或標籤] 下拉式清單。 如需詳細資訊,請參閱如何選取 ASP.NET Core 原始程式碼 (dotnet/AspNetCore.Docs #26205) 的版本標籤。
在 Blazor 應用程式的 Pages/_Host.cshtml
中,而這些應用程式在裝載的 Blazor WebAssembly 應用程式中為 WebAssembly 預先轉譯 (WebAssemblyPrerendered
) 或在 Blazor Server 應用程式中為 ServerPrerendered
:
<body>
...
<persist-component-state />
</body>
使用 PersistentComponentState 服務決定要保存哪個狀態。 PersistentComponentState.RegisterOnPersisting
會註冊回呼,以在應用程式暫停前保存元件狀態。 應用程式繼續時會擷取此狀態。
在以下範例中:
{TYPE}
預留位置代表要保存的資料類型 (例如WeatherForecast[]
)。{TOKEN}
預留位置是狀態識別碼字串 (例如fetchdata
)。
@implements IDisposable
@inject PersistentComponentState ApplicationState
...
@code {
private {TYPE} data;
private PersistingComponentStateSubscription persistingSubscription;
protected override async Task OnInitializedAsync()
{
persistingSubscription =
ApplicationState.RegisterOnPersisting(PersistData);
if (!ApplicationState.TryTakeFromJson<{TYPE}>(
"{TOKEN}", out var restored))
{
data = await ...;
}
else
{
data = restored!;
}
}
private Task PersistData()
{
ApplicationState.PersistAsJson("{TOKEN}", data);
return Task.CompletedTask;
}
void IDisposable.Dispose()
{
persistingSubscription.Dispose();
}
}
下列範例是以 Blazor 專案範本為基礎的託管 Blazor WebAssembly 應用程式中更新版本的 FetchData
元件。 WeatherForecastPreserveState
元件會在預先轉譯期間保存氣象預報狀態,然後擷取該狀態以初始化元件。 保存元件狀態標籤協助程式會在所有元件叫用之後保存元件狀態。
Pages/WeatherForecastPreserveState.razor
:
@page "/weather-forecast-preserve-state"
@using BlazorSample.Shared
@implements IDisposable
@inject IWeatherForecastService WeatherForecastService
@inject PersistentComponentState ApplicationState
<PageTitle>Weather Forecast</PageTitle>
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from the server.</p>
@if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
}
@code {
private WeatherForecast[] forecasts = Array.Empty<WeatherForecast>();
private PersistingComponentStateSubscription persistingSubscription;
protected override async Task OnInitializedAsync()
{
persistingSubscription =
ApplicationState.RegisterOnPersisting(PersistForecasts);
if (!ApplicationState.TryTakeFromJson<WeatherForecast[]>(
"fetchdata", out var restored))
{
forecasts =
await WeatherForecastService.GetForecastAsync(DateOnly.FromDateTime(DateTime.Now));
}
else
{
forecasts = restored!;
}
}
private Task PersistForecasts()
{
ApplicationState.PersistAsJson("fetchdata", forecasts);
return Task.CompletedTask;
}
void IDisposable.Dispose()
{
persistingSubscription.Dispose();
}
}
在預先轉譯期間使用相同的狀態初始化元件,任何昂貴的初始化步驟只會執行一次。 轉譯的 UI 也會符合預先轉譯的 UI,因此瀏覽器中不會發生閃爍。
其他 Blazor WebAssembly 資源
- 狀態管理:處理預先轉譯
- 組件延遲載入的預先轉譯支援
- 與預先轉譯相關的 Razor 元件生命週期主題
- 元件初始化 (
OnInitialized{Async}
) - 元件轉譯之後 (
OnAfterRender{Async}
) - 預先轉譯之後的具狀態重新連線:雖然本節內容著重於 Blazor Server 和具狀態的 SignalR重新連線,但託管 Blazor WebAssembly 應用程式 (WebAssemblyPrerendered) 中的預先轉譯案例涉及類似條件和方法,以防止開發人員程式碼執行兩次。 若要在預先轉譯時執行初始化程式碼期間保留狀態,請參閱本文的保存預先轉譯的狀態一節。
- 使用 JavaScript Interop 預先轉譯
- 元件初始化 (
- 關於預先轉譯的驗證和授權主題
- 裝載和部署:Blazor WebAssembly
- 處理錯誤:預先轉譯
- OnNavigateAsync 會在預先轉譯時執行兩次:使用
OnNavigateAsync
處理非同步導覽事件
預先轉譯狀態大小和 SignalR 訊息大小限制
大型預先轉譯狀態大小可能超過 SignalR 線路訊息大小限制,這會導致下列結果:
- SignalR 線路無法初始化,且用戶端發生錯誤:Circuit host not initialized.
- 當線路發生中斷時,用戶端會出現重新連線的 UI。 不可能復原。
若要解決該問題,請使用下列任一種方法:
- 減少放入預先轉譯狀態的資料量。
- 新增 SignalR 訊息大小限制。 警告:增加限制可能會增加拒絕服務 (DoS) 攻擊的風險。
其他 Blazor Server 資源
Razor 元件可整合至託管 Blazor WebAssembly解決方案中的 Razor Pages 與 MVC 應用程式。 轉譯頁面或檢視時,可以同時預先轉譯元件。
預先轉譯可藉由轉譯初始 HTTP 回應的內容來改善搜尋引擎最佳化 (SEO),讓搜尋引擎可使用該回應來計算頁面排名。
解決方案設定
預先轉譯設定
若要為託管 Blazor WebAssembly 應用程式設定預先轉譯:
在 ASP.NET Core 應用程式中裝載 Blazor WebAssembly 應用程式。 獨立 Blazor WebAssembly 應用程式可新增至 ASP.NET Core 解決方案,或者,您可以使用透過託管選項從 Blazor WebAssembly 專案範本建立的託管 Blazor WebAssembly 應用程式:
- Visual Studio:建立 Blazor WebAssembly 應用程式時,在 [其他資訊] 對話方塊中選取 [已託管 ASP.NET Core] 核取方塊。 在本文中的範例中,解決方案的名稱為
BlazorHosted
。 - Visual Studio Code/.NET CLI 命令殼層:
dotnet new blazorwasm -ho
(使用-ho|--hosted
選項)。 使用-o|--output {LOCATION}
選項建立解決方案的資料夾,並設定解決方案的專案命名空間。 在本文中的範例中,解決方案的名稱為BlazorHosted
(dotnet new blazorwasm -ho -o BlazorHosted
)。
在本文的範例中,用戶端專案的命名空間為
BlazorHosted.Client
,而伺服器專案的命名空間為BlazorHosted.Server
。- Visual Studio:建立 Blazor WebAssembly 應用程式時,在 [其他資訊] 對話方塊中選取 [已託管 ASP.NET Core] 核取方塊。 在本文中的範例中,解決方案的名稱為
從 Blazor WebAssemblyClient 專案中刪除
wwwroot/index.html
檔案。在 Client 專案中,刪除
Program.cs
中的以下幾行:- builder.RootComponents.Add<App>("#app"); - builder.RootComponents.Add<HeadOutlet>("head::after");
將
_Host.cshtml
和_Layout.cshtml
檔案新增至 Server 專案的Pages
資料夾。 您可以使用 Visual Studio 從透過 Blazor Server 範本建立的專案中取得檔案,或使用 .NET CLI 搭配命令殼層中的dotnet new blazorserver -o BlazorServer
命令來取得 (-o BlazorServer
選項會建立專案的資料夾)。 將檔案放入 Server 專案的Pages
資料夾中後,請對檔案進行下列變更。重要
必須使用配置頁面 (
_Layout.cshtml
) 搭配 HeadOutlet 元件的元件標籤協助程式,以控制<head>
內容,例如頁面的標題 (PageTitle 元件) 和其他標頭元素 (HeadContent 元件)。 如需詳細資訊,請參閱在 ASP.NET Core Blazor 應用程式中控制標題內容 (部分機器翻譯)。對
_Layout.cshtml
檔案進行下列變更:更新檔案頂端的
Pages
命名空間,以符合 Server 應用程式頁面的命名空間。 下列範例中的{APP NAMESPACE}
預留位置代表提供_Layout.cshtml
檔案的捐贈者應用程式頁面的命名空間:刪除:
- @namespace {APP NAMESPACE}.Pages
新增:
@namespace BlazorHosted.Server.Pages
在檔案頂端為 Client 專案新增
@using
指示詞:@using BlazorHosted.Client
更新樣式表連結,以指向 WebAssembly 專案的樣式表。 在下列範例中,用戶端專案的命名空間為
BlazorHosted.Client
。{APP NAMESPACE}
預留位置代表提供_Layout.cshtml
檔案的捐贈者應用程式的命名空間。 更新HeadOutlet
元件的元件標籤協助程式 (<component>
標籤),以預先轉譯元件。刪除:
- <link href="css/site.css" rel="stylesheet" /> - <link href="{APP NAMESPACE}.styles.css" rel="stylesheet" /> - <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
新增:
<link href="css/app.css" rel="stylesheet" /> <link href="BlazorHosted.Client.styles.css" rel="stylesheet" /> <component type="typeof(HeadOutlet)" render-mode="WebAssemblyPrerendered" />
注意
將要求 Bootstrap 樣式表 (
css/bootstrap/bootstrap.min.css
) 的<link>
元素保留在原處。更新 Blazor 指令碼來源以使用用戶端 Blazor WebAssembly 指令碼:
刪除:
- <script src="_framework/blazor.server.js"></script>
新增:
<script src="_framework/blazor.webassembly.js"></script>
在
_Host.cshtml
檔案中:將
Pages
命名空間變更為 Client 專案的命名空間。{APP NAMESPACE}
預留位置代表提供_Host.cshtml
檔案的捐贈者應用程式頁面的命名空間:刪除:
- @namespace {APP NAMESPACE}.Pages
新增:
@namespace BlazorHosted.Client
更新元件標籤協助程式的
render-mode
,以使用 WebAssemblyPrerendered 預先轉譯根App
元件:刪除:
- <component type="typeof(App)" render-mode="ServerPrerendered" />
新增:
<component type="typeof(App)" render-mode="WebAssemblyPrerendered" />
重要
驗證端點 (
/authentication/
路徑線段) 不支援預先轉譯。 如需詳細資訊,請參閱 ASP.NET Core Blazor WebAssembly 的其他安全性案例。
在
Program.cs
中 Server 專案的端點對應中,將後援從index.html
檔案變更為_Host.cshtml
頁面:刪除:
- app.MapFallbackToFile("index.html");
新增:
app.MapFallbackToPage("/_Host");
如果 Client 和 Server 專案在預先轉譯期間使用一或多個一般服務,請將服務註冊納入可從這兩個專案呼叫的方法中。 如需詳細資訊,請參閱 ASP.NET Core Blazor 相依性插入。
執行 Server 專案。 託管 Blazor WebAssembly 應用程式會由用戶端的 Server 專案預先轉譯。
將 Razor 元件內嵌至頁面和檢視中的設定
在下列各節和範例中,將 Razor 元件從 ClientBlazor WebAssembly 應用程式內嵌至伺服器應用程式的頁面和檢視中,需要額外的設定。
Server 專案必須具有下列檔案和資料夾。
Razor Pages:
Pages/Shared/_Layout.cshtml
Pages/Shared/_Layout.cshtml.css
Pages/_ViewImports.cshtml
Pages/_ViewStart.cshtml
MVC:
Views/Shared/_Layout.cshtml
Views/Shared/_Layout.cshtml.css
Views/_ViewImports.cshtml
Views/_ViewStart.cshtml
重要
必須使用配置頁面 (_Layout.cshtml
) 搭配 HeadOutlet 元件的元件標籤協助程式,以控制 <head>
內容,例如頁面的標題 (PageTitle 元件) 和其他標頭元素 (HeadContent 元件)。 如需詳細資訊,請參閱在 ASP.NET Core Blazor 應用程式中控制標題內容 (部分機器翻譯)。
使用下列途徑從 ASP.NET Core 專案範本產生應用程式,可取得上述檔案:
- Visual Studio 新的專案建立工具。
- 開啟命令殼層並執行
dotnet new webapp -o {PROJECT NAME}
(Razor Pages) 或dotnet new mvc -o {PROJECT NAME}
(MVC)。 具有{PROJECT NAME}
預留位置值的選項-o|--output
會提供應用程式的名稱,並且為應用程式建立資料夾。
在匯入的 _ViewImports.cshtml
檔案中更新命名空間,以符合接收檔案的 Server 專案所使用的命名空間。
Pages/_ViewImports.cshtml
(Razor Pages):
@using BlazorHosted.Server
@namespace BlazorHosted.Server.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
Views/_ViewImports.cshtml
(MVC):
@using BlazorHosted.Server
@using BlazorHosted.Server.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
更新匯入的配置檔案,即適用於 Razor Pages 的 Pages/Shared/_Layout.cshtml
或適用於 MVC 的 Views/Shared/_Layout.cshtml
。
首先,從捐贈者專案中刪除標題和樣式表 (在下列範例中為 RPDonor.styles.css
)。 {PROJECT NAME}
預留位置代表捐贈者專案的應用程式名稱。
- <title>@ViewData["Title"] - {PROJECT NAME}</title>
- <link rel="stylesheet" href="~/RPDonor.styles.css" asp-append-version="true" />
在配置檔案中包含 Client 專案的樣式。 在下列範例中,Client 專案的命名空間為 BlazorHosted.Client
。 <title>
元素可以同時更新。
將以下幾行放在配置檔案的 <head>
內容中:
<title>@ViewData["Title"] - BlazorHosted</title>
<link href="css/app.css" rel="stylesheet" />
<link rel="stylesheet" href="BlazorHosted.Client.styles.css" asp-append-version="true" />
<component type="typeof(HeadOutlet)" render-mode="WebAssemblyPrerendered" />
匯入的配置包含兩個 Home
(Index
頁面) 和 Privacy
瀏覽連結。 若要使 Home
連結指向託管 Blazor WebAssembly 應用程式,請變更超連結:
- <a class="navbar-brand" asp-area="" asp-page="/Index">{PROJECT NAME}</a>
+ <a class="navbar-brand" href="/">BlazorHosted</a>
- <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>
在 MVC 配置檔案中:
- <a class="navbar-brand" asp-area="" asp-controller="Home"
- asp-action="Index">{PROJECT NAME}</a>
+ <a class="navbar-brand" href="/">BlazorHosted</a>
- <a class="nav-link text-dark" asp-area="" asp-controller="Home"
- asp-action="Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>
更新 <footer>
元素的應用程式名稱。 下列範例使用應用程式名稱 BlazorHosted
:
- © {DATE} - {DONOR NAME} - <a asp-area="" asp-page="/Privacy">Privacy</a>
+ © {DATE} - BlazorHosted - <a asp-area="" asp-page="/Privacy">Privacy</a>
在上述範例中,{DATE}
預留位置代表從 Razor Pages 或 MVC 專案範本產生的應用程式中的著作權日期。
若要使 Privacy
連結導向 privacy 頁面 (Razor 頁面),請將 privacy 頁面新增至 Server 專案。
Server 專案中的 Pages/Privacy.cshtml
:
@page
@model PrivacyModel
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
<p>Use this page to detail your site's privacy policy.</p>
針對以 MVC 為基礎的 privacy 檢視,請在 Server 專案中建立 privacy 檢視。
Server 專案中的 View/Home/Privacy.cshtml
:
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
<p>Use this page to detail your site's privacy policy.</p>
在 MVC 應用程式的 Home
控制器中,傳回檢視。
將下列程式碼新增至 Controllers/HomeController.cs
:
public IActionResult Privacy()
{
return View();
}
如果您從捐贈者應用程式中匯入檔案,請務必更新檔案中的任何命名空間,以符合 Server 專案的命名空間 (例如 BlazorHosted.Server
)。
從捐贈者專案的 wwwroot
資料夾中,將靜態資產匯入至 Server 專案:
wwwroot/css
資料夾和內容wwwroot/js
資料夾和內容wwwroot/lib
資料夾和內容
如果捐贈者專案是從 ASP.NET Core 專案範本建立的,且檔案並未修改,您可以將整個 wwwroot
資料夾從捐贈者專案複製到 Server 專案中,並移除 favicon 圖示檔案。
警告
請避免將靜態資產同時放入 Client 和 Server wwwroot
資料夾中。 如果這兩個資料夾中有相同的檔案,將會擲回例外狀況,因為各個資料夾中的靜態資產會共用相同的 Web 根目錄路徑。 因此,應在任一 wwwroot
資料夾 (而不是兩者) 中裝載靜態資產。
採用上述設定之後,將 Razor 元件內嵌至 Server 專案的頁面或檢視中。 使用本文中以下幾節的指引:
- 使用元件標籤協助程式在頁面或檢視中轉譯元件
- 使用 CSS 選取器在頁面或檢視中轉譯元件
使用元件標籤協助程式在頁面或檢視中轉譯元件
設定解決方案 (包括其他設定) 之後,元件標籤協助程式支援以兩種轉譯模式在頁面或檢視中轉譯 Blazor WebAssembly 應用程式中的元件:
在下列 Razor Pages 範例中,Counter
元件會在頁面中轉譯。 為了使元件具有互動性,頁面的轉譯區段中包含了 Blazor WebAssembly 指令碼。 若要避免將 Counter
元件的完整命名空間搭配用於元件標籤協助程式 ({ASSEMBLY NAME}.Pages.Counter
),請為用戶端專案的 Pages
命名空間新增 @using
指示詞。 在下列範例中,Client 專案的命名空間為 BlazorHosted.Client
。
在 Server 專案中,Pages/RazorPagesCounter1.cshtml
:
@page
@using BlazorHosted.Client.Pages
<component type="typeof(Counter)" render-mode="WebAssemblyPrerendered" />
@section Scripts {
<script src="_framework/blazor.webassembly.js"></script>
}
執行 Server 專案。 瀏覽至位於 /razorpagescounter1
的 Razor 頁面。 預先轉譯的 Counter
元件會內嵌在頁面中。
RenderMode 設定元件:
- 預先轉譯至頁面。
- 在頁面上轉譯為靜態 HTML,或包含從使用者代理程式啟動 Blazor 應用程式所需的資訊。
如需元件標籤協助程式的詳細資訊 (包括傳遞參數和 RenderMode 設定),請參閱 ASP.NET Core 中的元件標籤協助程式。
依據元件所使用的靜態資源,以及配置頁面在應用程式中的組織方式,可能需要額外的工作。 一般而言,指令碼會新增至頁面或檢視的 Scripts
轉譯區段,而樣式表會新增至版面配置的 <head>
元素內容。
透過轉譯片段設定子內容
元件標籤協助程式不支援接收子內容的 RenderFragment
委派 (例如 param-ChildContent="..."
)。 建議您建立一個 Razor 元件 (.razor
),參考您想要轉譯的元件以及要傳遞的子內容,然後從頁面或檢視叫用 Razor 元件。
確定發佈時不會修剪最上層的預先轉譯元件
如果元件標籤協助程式直接參考程式庫中在發佈時有可能修剪的元件,該元件在發佈期間可能會被修剪,因為用戶端應用程式程式碼並未參考該元件。 因此,元件不會預先轉譯,從而在輸出中留下空白。 如果發生這種情況,請在用戶端應用程式中的任何類別中新增 DynamicDependency
屬性,以指示修剪器保留程式庫元件。 若要保留名為 SomeLibraryComponentToBePreserved
的元件,請將下列內容新增至任何元件:
@using System.Diagnostics.CodeAnalysis
@attribute [DynamicDependency(DynamicallyAccessedMemberTypes.All,
typeof(SomeLibraryComponentToBePreserved))]
上述方法通常用不上,因為在多數情況下,應用程式會預先轉譯其元件 (未修剪),而這些元件隨後又會參考程式庫中的元件 (致使其也不會被修剪)。 只有在程式庫有可能修剪時,才需要明確使用 DynamicDependency
預先轉譯程式庫元件。
使用 CSS 選取器在頁面或檢視中轉譯元件
設定解決方案 (包括其他設定) 之後,請將根元件新增至 Program.cs
檔案中的託管 Blazor WebAssembly 解決方案的 Client 專案。 在下列範例中,Counter
元件會宣告為根元件,且有 CSS 選取器可選取 id
符合 counter-component
的元素。 在下列範例中,Client 專案的命名空間為 BlazorHosted.Client
。
在 Client 專案的 Program.cs
檔案中,將專案的 Razor 元件命名空間新增至檔案頂端:
using BlazorHosted.Client.Pages;
在 Program.cs
中建立 builder
之後,請將 Counter
元件新增為根元件:
builder.RootComponents.Add<Counter>("#counter-component");
在下列 Razor Pages 範例中,Counter
元件會在頁面中轉譯。 為了使元件具有互動性,頁面的轉譯區段中包含了 Blazor WebAssembly 指令碼。
在 Server 專案中,Pages/RazorPagesCounter2.cshtml
:
@page
<div id="counter-component">Loading...</div>
@section Scripts {
<script src="_framework/blazor.webassembly.js"></script>
}
執行 Server 專案。 瀏覽至位於 /razorpagescounter2
的 Razor 頁面。 預先轉譯的 Counter
元件會內嵌在頁面中。
依據元件所使用的靜態資源,以及配置頁面在應用程式中的組織方式,可能需要額外的工作。 一般而言,指令碼會新增至頁面或檢視的 Scripts
轉譯區段,而樣式表會新增至版面配置的 <head>
元素內容。
注意
在上述範例中,如果 Blazor WebAssembly 應用程式在使用 CSS 選取器的同時預先轉譯並整合至 Razor Pages 或 MVC 應用程式中,則會擲回 JSException。 瀏覽至其中一個 Client 專案的 Razor 元件,或瀏覽至具有內嵌元件的 Server 頁面或檢視,將會擲回一或多個 JSException。
這是正常行為,因為預先轉譯應用程式以及整合 Blazor WebAssembly 應用程式與可路由傳送的 Razor 元件,與使用 CSS 選取器並不相容。
如果您已完成以上幾節中的範例,而想了解一下 CSS 選取器在您範例應用程式中的運作情形,請在 Client 專案的 Program.cs
檔案中將 App
根元件的規格註解化:
- builder.RootComponents.Add<App>("#app");
+ //builder.RootComponents.Add<App>("#app");
瀏覽至有內嵌的 Razor 元件使用 CSS 選取器的頁面或檢視 (例如,上述範例的 /razorpagescounter2
)。 頁面或檢視會載入內嵌元件,且內嵌元件會如預期運作。
可以將 Razor 元件整合至 Razor Pages 與 MVC 應用程式中。 轉譯頁面或檢視時,可以同時預先轉譯元件。
預先轉譯可藉由轉譯初始 HTTP 回應的內容來改善搜尋引擎最佳化 (SEO),讓搜尋引擎可使用該回應來計算頁面排名。
設定專案之後,請根據專案的需求使用以下幾節中的指引:
- 可路由傳送的元件:對於可直接從使用者要求路由傳送的元件。 請遵循本指導,使訪客應該可在瀏覽器中對具有
@page
指示詞的元件提出 HTTP 要求。 - 從頁面或檢視轉譯元件:對於無法直接從使用者要求路由傳送的元件。 當應用程式使用元件標記協助程式將元件內嵌至現有的頁面和檢視時,請遵循此指導。
組態
使用下列指引,將 Razor 元件整合至現有 Razor Pages 或 MVC 應用程式的頁面和檢視中。
重要
必須使用配置頁面 (_Layout.cshtml
) 搭配 HeadOutlet 元件的元件標籤協助程式,以控制 <head>
內容,例如頁面的標題 (PageTitle 元件) 和其他標頭元素 (HeadContent 元件)。 如需詳細資訊,請參閱在 ASP.NET Core Blazor 應用程式中控制標題內容 (部分機器翻譯)。
在專案的配置檔案中:
將下列
<base>
標籤和 HeadOutlet 元件標籤協助程式新增至Pages/Shared/_Layout.cshtml
(Razor Pages) 或Views/Shared/_Layout.cshtml
(MVC) 中的<head>
元素:<base href="~/" /> <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
上述範例中的
href
值 ( 應用程式基本路徑) 假設應用程式位於根 URL 路徑 (/
) 中。 如果應用程式是子應用程式,請遵循裝載及部署 ASP.NET Core Blazor (部分機器翻譯) 文章之應用程式基本路徑一節中的指導。HeadOutlet 元件是用來轉譯頁面標題 (PageTitle 元件) 和其他由 Razor 元件所設定之標題元素 (HeadContent 元件) 的標題 (
<head>
) 內容。 如需詳細資訊,請參閱在 ASP.NET Core Blazor 應用程式中控制標題內容 (部分機器翻譯)。在應用程式的配置中,在
Scripts
轉譯區段 (@await RenderSectionAsync(...)
) 前面新增blazor.server.js
指令碼的<script>
標籤。Pages/Shared/_Layout.cshtml
(Razor Pages) 或Views/Shared/_Layout.cshtml
(MVC):<script src="_framework/blazor.server.js"></script>
架構會將
blazor.server.js
指令碼新增至應用程式。 無須手動將blazor.server.js
指令碼檔案新增至應用程式。
將具有下列內容的匯入檔案新增至專案的根資料夾。 將
{APP NAMESPACE}
預留位置變更為專案的命名空間。_Imports.razor
:@using System.Net.Http @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.JSInterop @using {APP NAMESPACE}
在註冊服務的
Program.cs
中註冊 Blazor Server 服務:builder.Services.AddServerSideBlazor();
將 Blazor 中樞端點新增至對應路由的
Program.cs
的端點。在
MapRazorPages
(Razor Pages) 或MapControllerRoute
(MVC) 的呼叫後面放置以下這一行:app.MapBlazorHub();
將元件整合至任何頁面或檢視中。 例如,將
Counter
元件新增至專案的Shared
資料夾。Pages/Shared/Counter.razor
(Razor Pages) 或Views/Shared/Counter.razor
(MVC):<h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Razor Pages:
在專案的 Razor Pages 應用程式
Index
頁面中,新增Counter
元件的命名空間,並將元件內嵌至頁面中。 當Index
頁面載入時,系統會在頁面中轉譯Counter
元件。 在下列範例中,將{APP NAMESPACE}
預留位置以專案的命名空間取代。Pages/Index.cshtml
:@page @using {APP NAMESPACE}.Pages.Shared @model IndexModel @{ ViewData["Title"] = "Home page"; } <component type="typeof(Counter)" render-mode="ServerPrerendered" />
MVC:
在專案的 MVC 應用程式
Index
檢視中,新增Counter
元件的命名空間,並將元件內嵌至檢視中。 當Index
檢視載入時,系統會在頁面中轉譯Counter
元件。 在下列範例中,將{APP NAMESPACE}
預留位置以專案的命名空間取代。Views/Home/Index.cshtml
:@using {APP NAMESPACE}.Views.Shared @{ ViewData["Title"] = "Home Page"; } <component type="typeof(Counter)" render-mode="ServerPrerendered" />
如需詳細資訊,請參閱從頁面或檢視轉譯元件一節。
在 Razor Pages 應用程式中使用可路由傳送的元件
本節說明如何新增可直接從使用者要求路由傳送的元件。
若要在 Razor Pages 應用程式中支援可路由傳送的 Razor 元件 :
將具有下列內容的
App
元件新增至專案根目錄。App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(App).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <PageTitle>Not found</PageTitle> <p role="alert">Sorry, there's nothing at this address.</p> </NotFound> </Router>
將具有下列內容的
_Host
頁面新增至專案。Pages/_Host.cshtml
:@page "/blazor" @namespace {APP NAMESPACE}.Pages.Shared @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @{ Layout = "_Layout"; } <component type="typeof(App)" render-mode="ServerPrerendered" />
在此案例中,元件會使用共用的
_Layout.cshtml
檔案進行其配置。重要
必須使用配置頁面 (
_Layout.cshtml
) 搭配 HeadOutlet 元件的元件標籤協助程式,以控制<head>
內容,例如頁面的標題 (PageTitle 元件) 和其他標頭元素 (HeadContent 元件)。 如需詳細資訊,請參閱在 ASP.NET Core Blazor 應用程式中控制標題內容 (部分機器翻譯)。RenderMode 會設定
App
元件是否:- 預先轉譯至頁面。
- 在頁面上轉譯為靜態 HTML,或包含從使用者代理程式啟動 Blazor 應用程式所需的資訊。
如需元件標籤協助程式的詳細資訊 (包括傳遞參數和 RenderMode 設定),請參閱 ASP.NET Core 中的元件標籤協助程式。
在
Program.cs
端點中,將_Host
頁面的低優先順序路由新增為最後一個端點:app.MapFallbackToPage("/_Host");
將可路由傳送的元件新增至專案。 下列範例是以 Blazor 專案範本中
Counter
元件為基礎的RoutableCounter
元件。Pages/RoutableCounter.razor
:@page "/routable-counter" <PageTitle>Routable Counter</PageTitle> <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
執行專案並瀏覽至位於
/routable-counter
之可路由傳送的RoutableCounter
元件。
如需命名空間的詳細資訊,請參閱元件命名空間一節。
在 MVC 應用程式中使用可路由傳送的元件
本節說明如何新增可直接從使用者要求路由傳送的元件。
若要在 MVC 應用程式中支援可路由傳送的 Razor 元件:
將具有下列內容的
App
元件新增至專案根目錄。App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(App).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <PageTitle>Not found</PageTitle> <p role="alert">Sorry, there's nothing at this address.</p> </NotFound> </Router>
將具有下列內容的
_Host
檢視新增至專案。Views/Home/_Host.cshtml
:@namespace {APP NAMESPACE}.Views.Shared @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @{ Layout = "_Layout"; } <component type="typeof(App)" render-mode="ServerPrerendered" />
元件會使用共用的
_Layout.cshtml
檔案進行其配置。重要
必須使用配置頁面 (
_Layout.cshtml
) 搭配 HeadOutlet 元件的元件標籤協助程式,以控制<head>
內容,例如頁面的標題 (PageTitle 元件) 和其他標頭元素 (HeadContent 元件)。 如需詳細資訊,請參閱在 ASP.NET Core Blazor 應用程式中控制標題內容 (部分機器翻譯)。RenderMode 會設定
App
元件是否:- 預先轉譯至頁面。
- 在頁面上轉譯為靜態 HTML,或包含從使用者代理程式啟動 Blazor 應用程式所需的資訊。
如需元件標籤協助程式的詳細資訊 (包括傳遞參數和 RenderMode 設定),請參閱 ASP.NET Core 中的元件標籤協助程式。
將動作新增至 Home 控制器。
Controllers/HomeController.cs
:public IActionResult Blazor() { return View("_Host"); }
在
Program.cs
端點中,為傳回_Host
檢視的控制器動作新增低優先順序路由:app.MapFallbackToController("Blazor", "Home");
在 MVC 應用程式中建立
Pages
資料夾,並新增可路由傳送的元件。 下列範例是以 Blazor 專案範本中Counter
元件為基礎的RoutableCounter
元件。Pages/RoutableCounter.razor
:@page "/routable-counter" <PageTitle>Routable Counter</PageTitle> <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
執行專案並瀏覽至位於
/routable-counter
之可路由傳送的RoutableCounter
元件。
如需命名空間的詳細資訊,請參閱元件命名空間一節。
從頁面或檢視轉譯元件
本節說明在無法直接從使用者要求路由傳送元件的情況下,如何將元件新增至頁面或檢視。
若要從頁面或檢視轉譯元件,請使用元件標籤協助程式。
轉譯具狀態互動式元件
具狀態互動式元件可以新增至 Razor 頁面或檢視。
當頁面或檢視轉譯時:
- 元件會與頁面或檢視一起預先轉譯。
- 用於預先轉譯的初始元件狀態會遺失。
- 在建立 SignalR 連線時會隨即建立新的元件狀態。
下列 Razor 頁面會轉譯 Counter
元件:
<h1>Razor Page</h1>
<component type="typeof(Counter)" render-mode="ServerPrerendered"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
如需詳細資訊,請參閱 ASP.NET Core 中的元件標籤協助程式。
重要
必須使用配置頁面 (_Layout.cshtml
) 搭配 HeadOutlet 元件的元件標籤協助程式,以控制 <head>
內容,例如頁面的標題 (PageTitle 元件) 和其他標頭元素 (HeadContent 元件)。 如需詳細資訊,請參閱在 ASP.NET Core Blazor 應用程式中控制標題內容 (部分機器翻譯)。
轉譯非互動式元件
在下列 Razor 頁面中,Counter
元件會以使用表單指定的初始值,以靜態方式轉譯。 由於元件以靜態方式轉譯,因此元件不具互動性:
<h1>Razor Page</h1>
<form>
<input type="number" asp-for="InitialValue" />
<button type="submit">Set initial value</button>
</form>
<component type="typeof(Counter)" render-mode="Static"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
如需詳細資訊,請參閱 ASP.NET Core 中的元件標籤協助程式。
重要
必須使用配置頁面 (_Layout.cshtml
) 搭配 HeadOutlet 元件的元件標籤協助程式,以控制 <head>
內容,例如頁面的標題 (PageTitle 元件) 和其他標頭元素 (HeadContent 元件)。 如需詳細資訊,請參閱在 ASP.NET Core Blazor 應用程式中控制標題內容 (部分機器翻譯)。
元件命名空間
在使用自訂資料夾來保存專案的 Razor 元件時,請將代表資料夾的命名空間新增至頁面/檢視或 _ViewImports.cshtml
檔案中。 在以下範例中:
- 元件會儲存在專案的
Components
資料夾中。 {APP NAMESPACE}
預留位置是專案的命名空間。Components
代表資料夾的名稱。
@using {APP NAMESPACE}.Components
_ViewImports.cshtml
檔案位於 Razor Pages 應用程式的 Pages
資料夾或 MVC 應用程式的 Views
資料夾中。
如需詳細資訊,請參閱 ASP.NET Core Razor 元件。
保存預先轉譯的狀態
若未保存預先轉譯的狀態,在預先轉譯期間所使用的狀態會遺失,而且必須在應用程式完全載入時重建。 如果以非同步方式設定了任何狀態,UI 可能會閃動,因為預先轉譯的 UI 會取代為暫時的預留位置,然後再次完整轉譯。
為了解決這些問題,Blazor 支援使用保存元件狀態標籤協助程式在預先轉譯的頁面中保存狀態。 在結尾 </body>
標籤內新增標籤協助程式的標籤 <persist-component-state />
。
Pages/_Layout.cshtml
:
<body>
...
<persist-component-state />
</body>
使用 PersistentComponentState 服務決定要保存哪個狀態。 PersistentComponentState.RegisterOnPersisting
會註冊回呼,以在應用程式暫停前保存元件狀態。 應用程式繼續時會擷取此狀態。
下列範例是以 Blazor 專案範本為基礎的託管 Blazor WebAssembly 應用程式中更新版本的 FetchData
元件。 WeatherForecastPreserveState
元件會在預先轉譯期間保存氣象預報狀態,然後擷取該狀態以初始化元件。 保存元件狀態標籤協助程式會在所有元件叫用之後保存元件狀態。
Pages/WeatherForecastPreserveState.razor
:
@page "/weather-forecast-preserve-state"
@implements IDisposable
@using BlazorSample.Shared
@inject IWeatherForecastService WeatherForecastService
@inject PersistentComponentState ApplicationState
<PageTitle>Weather Forecast</PageTitle>
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from the server.</p>
@if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
}
@code {
private WeatherForecast[] forecasts = Array.Empty<WeatherForecast>();
private PersistingComponentStateSubscription persistingSubscription;
protected override async Task OnInitializedAsync()
{
persistingSubscription =
ApplicationState.RegisterOnPersisting(PersistForecasts);
if (!ApplicationState.TryTakeFromJson<WeatherForecast[]>(
"fetchdata", out var restored))
{
forecasts =
await WeatherForecastService.GetForecastAsync(DateTime.Now);
}
else
{
forecasts = restored!;
}
}
private Task PersistForecasts()
{
ApplicationState.PersistAsJson("fetchdata", forecasts);
return Task.CompletedTask;
}
void IDisposable.Dispose()
{
persistingSubscription.Dispose();
}
}
在預先轉譯期間使用相同的狀態初始化元件,任何昂貴的初始化步驟只會執行一次。 轉譯的 UI 也會符合預先轉譯的 UI,因此瀏覽器中不會發生閃爍。
其他 Blazor WebAssembly 資源
- 狀態管理:處理預先轉譯
- 組件延遲載入的預先轉譯支援
- 與預先轉譯相關的 Razor 元件生命週期主題
- 元件初始化 (
OnInitialized{Async}
) - 元件轉譯之後 (
OnAfterRender{Async}
) - 預先轉譯之後的具狀態重新連線:雖然本節內容著重於 Blazor Server 和具狀態的 SignalR重新連線,但託管 Blazor WebAssembly 應用程式 (WebAssemblyPrerendered) 中的預先轉譯案例涉及類似條件和方法,以防止開發人員程式碼執行兩次。 若要在預先轉譯時執行初始化程式碼期間保留狀態,請參閱本文的保存預先轉譯的狀態一節。
- 使用 JavaScript Interop 預先轉譯
- 元件初始化 (
- 關於預先轉譯的驗證和授權主題
- 裝載和部署:Blazor WebAssembly
預先轉譯狀態大小和 SignalR 訊息大小限制
大型預先轉譯狀態大小可能超過 SignalR 線路訊息大小限制,這會導致下列結果:
- SignalR 線路無法初始化,且用戶端發生錯誤:Circuit host not initialized.
- 當線路發生中斷時,用戶端會出現重新連線的 UI。 不可能復原。
若要解決該問題,請使用下列任一種方法:
- 減少放入預先轉譯狀態的資料量。
- 新增 SignalR 訊息大小限制。 警告:增加限制可能會增加拒絕服務 (DoS) 攻擊的風險。
其他 Blazor Server 資源
Razor 元件可整合至託管 Blazor WebAssembly解決方案中的 Razor Pages 與 MVC 應用程式。 轉譯頁面或檢視時,可以同時預先轉譯元件。
預先轉譯可藉由轉譯初始 HTTP 回應的內容來改善搜尋引擎最佳化 (SEO),讓搜尋引擎可使用該回應來計算頁面排名。
解決方案設定
預先轉譯設定
若要為託管 Blazor WebAssembly 應用程式設定預先轉譯:
在 ASP.NET Core 應用程式中裝載 Blazor WebAssembly 應用程式。 獨立 Blazor WebAssembly 應用程式可新增至 ASP.NET Core 解決方案,或者,您可以使用透過託管選項從 Blazor WebAssembly 專案範本建立的託管 Blazor WebAssembly 應用程式:
- Visual Studio:建立 Blazor WebAssembly 應用程式時,在 [其他資訊] 對話方塊中選取 [已託管 ASP.NET Core] 核取方塊。 在本文中的範例中,解決方案的名稱為
BlazorHosted
。 - Visual Studio Code/.NET CLI 命令殼層:
dotnet new blazorwasm -ho
(使用-ho|--hosted
選項)。 使用-o|--output {LOCATION}
選項建立解決方案的資料夾,並設定解決方案的專案命名空間。 在本文中的範例中,解決方案的名稱為BlazorHosted
(dotnet new blazorwasm -ho -o BlazorHosted
)。
在本文的範例中,用戶端專案的命名空間為
BlazorHosted.Client
,而伺服器專案的命名空間為BlazorHosted.Server
。- Visual Studio:建立 Blazor WebAssembly 應用程式時,在 [其他資訊] 對話方塊中選取 [已託管 ASP.NET Core] 核取方塊。 在本文中的範例中,解決方案的名稱為
從 Blazor WebAssemblyClient 專案中刪除
wwwroot/index.html
檔案。在 Client 專案中,刪除
Program.cs
中的以下這一行:- builder.RootComponents.Add<App>("#app");
將
Pages/_Host.cshtml
檔案新增至 Server 專案的Pages
資料夾。 您可以在命令殼層中使用dotnet new blazorserver -o BlazorServer
命令,從使用_Host.cshtml
範本建立的專案中取得 Blazor Server 檔案 (-o BlazorServer
選項會為專案建立資料夾)。 將Pages/_Host.cshtml
檔案放入託管 Blazor WebAssembly 解決方案的 Server 專案之後,請對檔案進行下列變更:為 Client 專案提供
@using
指示詞 (例如@using BlazorHosted.Client
)。更新樣式表連結,以指向 WebAssembly 專案的樣式表。 在下列範例中,用戶端專案的命名空間為
BlazorHosted.Client
:- <link href="css/site.css" rel="stylesheet" /> - <link href="_content/BlazorServer/_framework/scoped.styles.css" rel="stylesheet" /> + <link href="css/app.css" rel="stylesheet" /> + <link href="BlazorHosted.Client.styles.css" rel="stylesheet" />
注意
將要求 Bootstrap 樣式表 (
css/bootstrap/bootstrap.min.css
) 的<link>
元素保留在原處。更新元件標籤協助程式的
render-mode
,以使用 WebAssemblyPrerendered 預先轉譯根App
元件:- <component type="typeof(App)" render-mode="ServerPrerendered" /> + <component type="typeof(App)" render-mode="WebAssemblyPrerendered" />
更新 Blazor 指令碼來源以使用用戶端 Blazor WebAssembly 指令碼:
- <script src="_framework/blazor.server.js"></script> + <script src="_framework/blazor.webassembly.js"></script>
在 Server 專案的
Startup.Configure
中,將後援從index.html
檔案變更為_Host.cshtml
頁面。Startup.cs
:- endpoints.MapFallbackToFile("index.html"); + endpoints.MapFallbackToPage("/_Host");
如果 Client 和 Server 專案在預先轉譯期間使用一或多個一般服務,請將服務註冊納入可從這兩個專案呼叫的方法中。 如需詳細資訊,請參閱 ASP.NET Core Blazor 相依性插入。
執行 Server 專案。 託管 Blazor WebAssembly 應用程式會由用戶端的 Server 專案預先轉譯。
將 Razor 元件內嵌至頁面和檢視中的設定
在本文的下列各節和範例中,將用戶端 Blazor WebAssembly 應用程式的 Razor 元件內嵌至伺服器應用程式的頁面和檢視中,需要額外的設定。
在 Server 專案中使用預設的 Razor Pages 或 MVC 配置檔案。 Server 專案必須具有下列檔案和資料夾。
Razor Pages:
Pages/Shared/_Layout.cshtml
Pages/_ViewImports.cshtml
Pages/_ViewStart.cshtml
MVC:
Views/Shared/_Layout.cshtml
Views/_ViewImports.cshtml
Views/_ViewStart.cshtml
從使用 Razor Pages 或 MVC 專案範本建立的應用程式中取得上述檔案。 如需詳細資訊,請參閱教學課程:開始使用 ASP.NET Core 中的 Razor Pages 或開始使用 ASP.NET Core MVC。
在匯入的 _ViewImports.cshtml
檔案中更新命名空間,以符合接收檔案的 Server 專案所使用的命名空間。
更新匯入的配置檔案 (_Layout.cshtml
) 以納入 Client 專案的樣式。 在下列範例中,Client 專案的命名空間為 BlazorHosted.Client
。 <title>
元素可以同時更新。
Pages/Shared/_Layout.cshtml
(Razor Pages) 或 Views/Shared/_Layout.cshtml
(MVC):
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>@ViewData["Title"] - DonorProject</title>
+ <title>@ViewData["Title"] - BlazorHosted</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" />
+ <link href="css/app.css" rel="stylesheet" />
+ <link href="BlazorHosted.Client.styles.css" rel="stylesheet" />
</head>
匯入的配置包含 Home
和 Privacy
導覽連結。 若要使 Home
連結指向託管 Blazor WebAssembly 應用程式,請變更超連結:
- <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>
在 MVC 配置檔案中:
- <a class="nav-link text-dark" asp-area="" asp-controller="Home"
- asp-action="Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>
若要讓 Privacy
連結導向 privacy 頁面,請將 privacy 頁面新增至 Server 專案。
Server 專案中的 Pages/Privacy.cshtml
:
@page
@model BlazorHosted.Server.Pages.PrivacyModel
@{
}
<h1>Privacy Policy</h1>
如果偏好使用以 MVC 為基礎的 privacy 檢視,請在 Server 專案中建立 privacy 檢視。
View/Home/Privacy.cshtml
:
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
在 Home
控制器中,傳回檢視。
Controllers/HomeController.cs
:
public IActionResult Privacy()
{
return View();
}
從捐贈者專案的 wwwroot
資料夾中,將靜態資產匯入至 Server 專案:
wwwroot/css
資料夾和內容wwwroot/js
資料夾和內容wwwroot/lib
資料夾和內容
如果捐贈者專案是從 ASP.NET Core 專案範本建立的,且檔案並未修改,您可以將整個 wwwroot
資料夾從捐贈者專案複製到 Server 專案中,並移除 favicon 圖示檔案。
警告
請避免將靜態資產同時放入 Client 和 Server wwwroot
資料夾中。 如果這兩個資料夾中有相同的檔案,將會擲回例外狀況,因為各個資料夾中的靜態資產會共用相同的 Web 根目錄路徑。 因此,應在任一 wwwroot
資料夾 (而不是兩者) 中裝載靜態資產。
使用元件標籤協助程式在頁面或檢視中轉譯元件
設定解決方案 (包括其他設定) 之後,元件標籤協助程式支援以兩種轉譯模式在頁面或檢視中轉譯 Blazor WebAssembly 應用程式中的元件:
在下列 Razor Pages 範例中,Counter
元件會在頁面中轉譯。 為了使元件具有互動性,頁面的轉譯區段中包含了 Blazor WebAssembly 指令碼。 若要避免將 Counter
元件的完整命名空間搭配用於元件標籤協助程式 ({ASSEMBLY NAME}.Pages.Counter
),請為用戶端專案的 Pages
命名空間新增 @using
指示詞。 在下列範例中,Client 專案的命名空間為 BlazorHosted.Client
。
在 Server 專案中,Pages/RazorPagesCounter1.cshtml
:
@page
@using BlazorHosted.Client.Pages
<component type="typeof(Counter)" render-mode="WebAssemblyPrerendered" />
@section Scripts {
<script src="_framework/blazor.webassembly.js"></script>
}
執行 Server 專案。 瀏覽至位於 /razorpagescounter1
的 Razor 頁面。 預先轉譯的 Counter
元件會內嵌在頁面中。
RenderMode 設定元件:
- 預先轉譯至頁面。
- 在頁面上轉譯為靜態 HTML,或包含從使用者代理程式啟動 Blazor 應用程式所需的資訊。
如需元件標籤協助程式的詳細資訊 (包括傳遞參數和 RenderMode 設定),請參閱 ASP.NET Core 中的元件標籤協助程式。
依據元件所使用的靜態資源,以及配置頁面在應用程式中的組織方式,可能需要額外的工作。 一般而言,指令碼會新增至頁面或檢視的 Scripts
轉譯區段,而樣式表會新增至版面配置的 <head>
元素內容。
使用 CSS 選取器在頁面或檢視中轉譯元件
設定解決方案 (包括其他設定) 之後,請將根元件新增至 Program.cs
中的託管 Blazor WebAssembly 解決方案的 Client 專案。 在下列範例中,Counter
元件會宣告為根元件,且有 CSS 選取器可選取 id
符合 counter-component
的元素。 在下列範例中,Client 專案的命名空間為 BlazorHosted.Client
。
在 Client 專案的 Program.cs
中,將專案的 Razor 元件命名空間新增至檔案頂端:
using BlazorHosted.Client.Pages;
在 Program.cs
中建立 builder
之後,請將 Counter
元件新增為根元件:
builder.RootComponents.Add<Counter>("#counter-component");
在下列 Razor Pages 範例中,Counter
元件會在頁面中轉譯。 為了使元件具有互動性,頁面的轉譯區段中包含了 Blazor WebAssembly 指令碼。
在 Server 專案中,Pages/RazorPagesCounter2.cshtml
:
@page
<div id="counter-component">Loading...</div>
@section Scripts {
<script src="_framework/blazor.webassembly.js"></script>
}
執行 Server 專案。 瀏覽至位於 /razorpagescounter2
的 Razor 頁面。 預先轉譯的 Counter
元件會內嵌在頁面中。
依據元件所使用的靜態資源,以及配置頁面在應用程式中的組織方式,可能需要額外的工作。 一般而言,指令碼會新增至頁面或檢視的 Scripts
轉譯區段,而樣式表會新增至版面配置的 <head>
元素內容。
注意
在上述範例中,如果 Blazor WebAssembly 應用程式在使用 CSS 選取器的同時預先轉譯並整合至 Razor Pages 或 MVC 應用程式中,則會擲回 JSException。 瀏覽至其中一個 Client 專案的 Razor 元件,會擲回下列例外狀況:
Microsoft.JSInterop.JSException:找不到任何符合選取器「#counter-component」的元素。
這是正常行為,因為預先轉譯應用程式以及整合 Blazor WebAssembly 應用程式與可路由傳送的 Razor 元件,與使用 CSS 選取器並不相容。
可以將 Razor 元件整合至 Razor Pages 與 MVC 應用程式中。 轉譯頁面或檢視時,可以同時預先轉譯元件。
預先轉譯可藉由轉譯初始 HTTP 回應的內容來改善搜尋引擎最佳化 (SEO),讓搜尋引擎可使用該回應來計算頁面排名。
設定專案之後,請根據專案的需求使用以下幾節中的指引:
- 可路由傳送的元件:對於可直接從使用者要求路由傳送的元件。 請遵循本指導,使訪客應該可在瀏覽器中對具有
@page
指示詞的元件提出 HTTP 要求。 - 從頁面或檢視轉譯元件:對於無法直接從使用者要求路由傳送的元件。 當應用程式使用元件標記協助程式將元件內嵌至現有的頁面和檢視時,請遵循此指導。
組態
現有的 Razor Pages 或 MVC 應用程式可將 Razor 元件整合至頁面和檢視中:
在專案的配置檔案中:
將下列
<base>
標籤新增至Pages/Shared/_Layout.cshtml
(Razor Pages) 或Views/Shared/_Layout.cshtml
(MVC) 中的<head>
元素:<base href="~/" />
上述範例中的
href
值 ( 應用程式基本路徑) 假設應用程式位於根 URL 路徑 (/
) 中。 如果應用程式是子應用程式,請遵循裝載及部署 ASP.NET Core Blazor (部分機器翻譯) 文章之應用程式基本路徑一節中的指導。在
Scripts
轉譯區段前面新增blazor.server.js
指令碼的<script>
標籤。Pages/Shared/_Layout.cshtml
(Razor Pages) 或Views/Shared/_Layout.cshtml
(MVC):... <script src="_framework/blazor.server.js"></script> @await RenderSectionAsync("Scripts", required: false) </body>
架構會將
blazor.server.js
指令碼新增至應用程式。 無須手動將blazor.server.js
指令碼檔案新增至應用程式。
將具有下列內容的匯入檔案新增至專案的根資料夾。 將
{APP NAMESPACE}
預留位置變更為專案的命名空間。_Imports.razor
:@using System.Net.Http @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @using Microsoft.JSInterop @using {APP NAMESPACE}
在
Startup.ConfigureServices
中註冊 Blazor Server 服務。在
Startup.cs
中:services.AddServerSideBlazor();
將 Blazor 中樞端點新增至
Startup.Configure
的端點 (app.UseEndpoints
)。Startup.cs
:endpoints.MapBlazorHub();
將元件整合至任何頁面或檢視中。 例如,將
Counter
元件新增至專案的Shared
資料夾。Pages/Shared/Counter.razor
(Razor Pages) 或Views/Shared/Counter.razor
(MVC):<h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Razor Pages:
在專案的 Razor Pages 應用程式
Index
頁面中,新增Counter
元件的命名空間,並將元件內嵌至頁面中。 當Index
頁面載入時,系統會在頁面中轉譯Counter
元件。 在下列範例中,將{APP NAMESPACE}
預留位置以專案的命名空間取代。Pages/Index.cshtml
:@page @using {APP NAMESPACE}.Pages.Shared @model IndexModel @{ ViewData["Title"] = "Home page"; } <div> <component type="typeof(Counter)" render-mode="ServerPrerendered" /> </div>
在上述範例中,將
{APP NAMESPACE}
預留位置取代為應用程式的命名空間。MVC:
在專案的 MVC 應用程式
Index
檢視中,新增Counter
元件的命名空間,並將元件內嵌至檢視中。 當Index
檢視載入時,系統會在頁面中轉譯Counter
元件。 在下列範例中,將{APP NAMESPACE}
預留位置以專案的命名空間取代。Views/Home/Index.cshtml
:@using {APP NAMESPACE}.Views.Shared @{ ViewData["Title"] = "Home Page"; } <div> <component type="typeof(Counter)" render-mode="ServerPrerendered" /> </div>
如需詳細資訊,請參閱從頁面或檢視轉譯元件一節。
在 Razor Pages 應用程式中使用可路由傳送的元件
本節說明如何新增可直接從使用者要求路由傳送的元件。
若要在 Razor Pages 應用程式中支援可路由傳送的 Razor 元件 :
將具有下列內容的
App
元件新增至專案根目錄。App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(Program).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <h1>Page not found</h1> <p>Sorry, but there's nothing here!</p> </NotFound> </Router>
注意
隨著 ASP.NET Core 5.0.1 的發行以及在任何其他 5.x 版中,
Router
元件會包含設定為@true
的PreferExactMatches
參數。 如需詳細資訊,請參閱從 ASP.NET Core 3.1 移轉至 5.0。將具有下列內容的
_Host
頁面新增至專案。Pages/_Host.cshtml
:@page "/blazor" @{ Layout = "_Layout"; } <app> <component type="typeof(App)" render-mode="ServerPrerendered" /> </app>
元件會使用共用的
_Layout.cshtml
檔案進行其配置。RenderMode 會設定
App
元件是否:- 預先轉譯至頁面。
- 在頁面上轉譯為靜態 HTML,或包含從使用者代理程式啟動 Blazor 應用程式所需的資訊。
如需元件標籤協助程式的詳細資訊 (包括傳遞參數和 RenderMode 設定),請參閱 ASP.NET Core 中的元件標籤協助程式。
在
Startup.cs
的Startup.Configure
端點中,將_Host
頁面的低優先順序路由新增為最後一個端點:endpoints.MapFallbackToPage("/_Host");
下列範例顯示一般應用程式端點設定中新增的行:
app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); endpoints.MapBlazorHub(); endpoints.MapFallbackToPage("/_Host"); });
將可路由傳送的元件新增至專案。
Pages/RoutableCounter.razor
:@page "/routable-counter" <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
執行專案並瀏覽至位於
/routable-counter
之可路由傳送的RoutableCounter
元件。
如需命名空間的詳細資訊,請參閱元件命名空間一節。
在 MVC 應用程式中使用可路由傳送的元件
本節說明如何新增可直接從使用者要求路由傳送的元件。
若要在 MVC 應用程式中支援可路由傳送的 Razor 元件:
將具有下列內容的
App
元件新增至專案根目錄。App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(Program).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <h1>Page not found</h1> <p>Sorry, but there's nothing here!</p> </NotFound> </Router>
注意
隨著 ASP.NET Core 5.0.1 的發行以及在任何其他 5.x 版中,
Router
元件會包含設定為@true
的PreferExactMatches
參數。 如需詳細資訊,請參閱從 ASP.NET Core 3.1 移轉至 5.0。將具有下列內容的
_Host
檢視新增至專案。Views/Home/_Host.cshtml
:@{ Layout = "_Layout"; } <app> <component type="typeof(App)" render-mode="ServerPrerendered" /> </app>
元件會使用共用的
_Layout.cshtml
檔案進行其配置。RenderMode 會設定
App
元件是否:- 預先轉譯至頁面。
- 在頁面上轉譯為靜態 HTML,或包含從使用者代理程式啟動 Blazor 應用程式所需的資訊。
如需元件標籤協助程式的詳細資訊 (包括傳遞參數和 RenderMode 設定),請參閱 ASP.NET Core 中的元件標籤協助程式。
將動作新增至 Home 控制器。
Controllers/HomeController.cs
:public IActionResult Blazor() { return View("_Host"); }
在
Startup.cs
的Startup.Configure
端點中,為傳回_Host
檢視的控制器動作新增低優先順序路由:endpoints.MapFallbackToController("Blazor", "Home");
下列範例顯示一般應用程式端點設定中新增的行:
app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); endpoints.MapBlazorHub(); endpoints.MapFallbackToController("Blazor", "Home"); });
將可路由傳送的元件新增至專案。
Pages/RoutableCounter.razor
:@page "/routable-counter" <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
執行專案並瀏覽至位於
/routable-counter
之可路由傳送的RoutableCounter
元件。
如需命名空間的詳細資訊,請參閱元件命名空間一節。
從頁面或檢視轉譯元件
本節說明在無法直接從使用者要求路由傳送元件的情況下,如何將元件新增至頁面或檢視。
若要從頁面或檢視轉譯元件,請使用元件標籤協助程式。
轉譯具狀態互動式元件
具狀態互動式元件可以新增至 Razor 頁面或檢視。
當頁面或檢視轉譯時:
- 元件會與頁面或檢視一起預先轉譯。
- 用於預先轉譯的初始元件狀態會遺失。
- 在建立 SignalR 連線時會隨即建立新的元件狀態。
下列 Razor 頁面會轉譯 Counter
元件:
<h1>My Razor Page</h1>
<component type="typeof(Counter)" render-mode="ServerPrerendered"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
如需詳細資訊,請參閱 ASP.NET Core 中的元件標籤協助程式。
轉譯非互動式元件
在下列 Razor 頁面中,Counter
元件會以使用表單指定的初始值,以靜態方式轉譯。 由於元件以靜態方式轉譯,因此元件不具互動性:
<h1>My Razor Page</h1>
<form>
<input type="number" asp-for="InitialValue" />
<button type="submit">Set initial value</button>
</form>
<component type="typeof(Counter)" render-mode="Static"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
如需詳細資訊,請參閱 ASP.NET Core 中的元件標籤協助程式。
元件命名空間
在使用自訂資料夾來保存專案的 Razor 元件時,請將代表資料夾的命名空間新增至頁面/檢視或 _ViewImports.cshtml
檔案中。 在以下範例中:
- 元件會儲存在專案的
Components
資料夾中。 {APP NAMESPACE}
預留位置是專案的命名空間。Components
代表資料夾的名稱。
@using {APP NAMESPACE}.Components
_ViewImports.cshtml
檔案位於 Razor Pages 應用程式的 Pages
資料夾或 MVC 應用程式的 Views
資料夾中。
如需詳細資訊,請參閱 ASP.NET Core Razor 元件。
其他 Blazor WebAssembly 資源
- 狀態管理:處理預先轉譯
- 組件延遲載入的預先轉譯支援
- 與預先轉譯相關的 Razor 元件生命週期主題
- 元件初始化 (
OnInitialized{Async}
) - 元件轉譯之後 (
OnAfterRender{Async}
) - 預先轉譯之後的具狀態重新連線:雖然本節內容著重於 Blazor Server 和具狀態的 SignalR重新連線,但託管 Blazor WebAssembly 應用程式 (WebAssemblyPrerendered) 中的預先轉譯案例涉及類似條件和方法,以防止開發人員程式碼執行兩次。 若要在預先轉譯時執行初始化程式碼期間保留狀態,請參閱本文的保存預先轉譯的狀態一節。
- 使用 JavaScript Interop 預先轉譯
- 元件初始化 (
- 關於預先轉譯的驗證和授權主題
- 裝載和部署:Blazor WebAssembly
預先轉譯狀態大小和 SignalR 訊息大小限制
大型預先轉譯狀態大小可能超過 SignalR 線路訊息大小限制,這會導致下列結果:
- SignalR 線路無法初始化,且用戶端發生錯誤:Circuit host not initialized.
- 當線路發生中斷時,用戶端會出現重新連線的 UI。 不可能復原。
若要解決該問題,請使用下列任一種方法:
- 減少放入預先轉譯狀態的資料量。
- 新增 SignalR 訊息大小限制。 警告:增加限制可能會增加拒絕服務 (DoS) 攻擊的風險。
其他 Blazor Server 資源
將 Razor 元件整合到託管 Blazor WebAssembly解決方案中的 Razor Pages 和 MVC 應用程式,在 .NET 5 或更新版本的 ASP.NET Core 中受支援。 選取本文的 .NET 5 或更新版本。
可以將 Razor 元件整合至 Razor Pages 與 MVC 應用程式中。 轉譯頁面或檢視時,可以同時預先轉譯元件。
預先轉譯可藉由轉譯初始 HTTP 回應的內容來改善搜尋引擎最佳化 (SEO),讓搜尋引擎可使用該回應來計算頁面排名。
設定專案之後,請根據專案的需求使用以下幾節中的指引:
- 可路由傳送的元件:對於可直接從使用者要求路由傳送的元件。 請遵循本指導,使訪客應該可在瀏覽器中對具有
@page
指示詞的元件提出 HTTP 要求。 - 從頁面或檢視轉譯元件:對於無法直接從使用者要求路由傳送的元件。 當應用程式使用元件標記協助程式將元件內嵌至現有的頁面和檢視時,請遵循此指導。
組態
現有的 Razor Pages 或 MVC 應用程式可將 Razor 元件整合至頁面和檢視中:
在專案的配置檔案中:
將下列
<base>
標籤新增至Pages/Shared/_Layout.cshtml
(Razor Pages) 或Views/Shared/_Layout.cshtml
(MVC) 中的<head>
元素:+ <base href="~/" />
上述範例中的
href
值 ( 應用程式基本路徑) 假設應用程式位於根 URL 路徑 (/
) 中。 如果應用程式是子應用程式,請遵循裝載及部署 ASP.NET Core Blazor (部分機器翻譯) 文章之應用程式基本路徑一節中的指導。在
Scripts
轉譯區段前面新增blazor.server.js
指令碼的<script>
標籤。Pages/Shared/_Layout.cshtml
(Razor Pages) 或Views/Shared/_Layout.cshtml
(MVC):... <script src="_framework/blazor.server.js"></script> @await RenderSectionAsync("Scripts", required: false) </body>
架構會將
blazor.server.js
指令碼新增至應用程式。 無須手動將blazor.server.js
指令碼檔案新增至應用程式。
將具有下列內容的匯入檔案新增至專案的根資料夾。 將
{APP NAMESPACE}
預留位置變更為專案的命名空間。_Imports.razor
:@using System.Net.Http @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @using Microsoft.JSInterop @using {APP NAMESPACE}
在
Startup.ConfigureServices
中註冊 Blazor Server 服務。Startup.cs
:services.AddServerSideBlazor();
將 Blazor 中樞端點新增至
Startup.Configure
的端點 (app.UseEndpoints
)。Startup.cs
:endpoints.MapBlazorHub();
將元件整合至任何頁面或檢視中。 例如,將
Counter
元件新增至專案的Shared
資料夾。Pages/Shared/Counter.razor
(Razor Pages) 或Views/Shared/Counter.razor
(MVC):<h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Razor Pages:
在專案的 Razor Pages 應用程式
Index
頁面中,新增Counter
元件的命名空間,並將元件內嵌至頁面中。 當Index
頁面載入時,系統會在頁面中轉譯Counter
元件。 在下列範例中,將{APP NAMESPACE}
預留位置以專案的命名空間取代。Pages/Index.cshtml
:@page @using {APP NAMESPACE}.Pages.Shared @model IndexModel @{ ViewData["Title"] = "Home page"; } <div> <component type="typeof(Counter)" render-mode="ServerPrerendered" /> </div>
在上述範例中,將
{APP NAMESPACE}
預留位置取代為應用程式的命名空間。MVC:
在專案的 MVC 應用程式
Index
檢視中,新增Counter
元件的命名空間,並將元件內嵌至檢視中。 當Index
檢視載入時,系統會在頁面中轉譯Counter
元件。 在下列範例中,將{APP NAMESPACE}
預留位置以專案的命名空間取代。Views/Home/Index.cshtml
:@using {APP NAMESPACE}.Views.Shared @{ ViewData["Title"] = "Home Page"; } <div> <component type="typeof(Counter)" render-mode="ServerPrerendered" /> </div>
如需詳細資訊,請參閱從頁面或檢視轉譯元件一節。
在 Razor Pages 應用程式中使用可路由傳送的元件
本節說明如何新增可直接從使用者要求路由傳送的元件。
若要在 Razor Pages 應用程式中支援可路由傳送的 Razor 元件 :
將具有下列內容的
App
元件新增至專案根目錄。App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(Program).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <h1>Page not found</h1> <p>Sorry, but there's nothing here!</p> </NotFound> </Router>
將具有下列內容的
_Host
頁面新增至專案。Pages/_Host.cshtml
:@page "/blazor" @{ Layout = "_Layout"; } <app> <component type="typeof(App)" render-mode="ServerPrerendered" /> </app>
元件會使用共用的
_Layout.cshtml
檔案進行其配置。RenderMode 會設定
App
元件是否:- 預先轉譯至頁面。
- 在頁面上轉譯為靜態 HTML,或包含從使用者代理程式啟動 Blazor 應用程式所需的資訊。
如需元件標籤協助程式的詳細資訊 (包括傳遞參數和 RenderMode 設定),請參閱 ASP.NET Core 中的元件標籤協助程式。
在
Startup.cs
的Startup.Configure
端點中,將_Host
頁面的低優先順序路由新增為最後一個端點:endpoints.MapFallbackToPage("/_Host");
下列範例顯示一般應用程式端點設定中新增的行:
app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); endpoints.MapBlazorHub(); endpoints.MapFallbackToPage("/_Host"); });
將可路由傳送的元件新增至專案。
Pages/RoutableCounter.razor
:@page "/routable-counter" <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
執行專案並瀏覽至位於
/routable-counter
之可路由傳送的RoutableCounter
元件。
如需命名空間的詳細資訊,請參閱元件命名空間一節。
在 MVC 應用程式中使用可路由傳送的元件
本節說明如何新增可直接從使用者要求路由傳送的元件。
若要在 MVC 應用程式中支援可路由傳送的 Razor 元件:
將具有下列內容的
App
元件新增至專案根目錄。App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(Program).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <h1>Page not found</h1> <p>Sorry, but there's nothing here!</p> </NotFound> </Router>
將具有下列內容的
_Host
檢視新增至專案。Views/Home/_Host.cshtml
:@{ Layout = "_Layout"; } <app> <component type="typeof(App)" render-mode="ServerPrerendered" /> </app>
元件會使用共用的
_Layout.cshtml
檔案進行其配置。RenderMode 會設定
App
元件是否:- 預先轉譯至頁面。
- 在頁面上轉譯為靜態 HTML,或包含從使用者代理程式啟動 Blazor 應用程式所需的資訊。
如需元件標籤協助程式的詳細資訊 (包括傳遞參數和 RenderMode 設定),請參閱 ASP.NET Core 中的元件標籤協助程式。
將動作新增至 Home 控制器。
Controllers/HomeController.cs
:public IActionResult Blazor() { return View("_Host"); }
在
Startup.cs
的Startup.Configure
端點中,為傳回_Host
檢視的控制器動作新增低優先順序路由:endpoints.MapFallbackToController("Blazor", "Home");
下列範例顯示一般應用程式端點設定中新增的行:
app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); endpoints.MapBlazorHub(); endpoints.MapFallbackToController("Blazor", "Home"); });
將可路由傳送的元件新增至專案。
Pages/RoutableCounter.razor
:@page "/routable-counter" <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
執行專案並瀏覽至位於
/routable-counter
之可路由傳送的RoutableCounter
元件。
如需命名空間的詳細資訊,請參閱元件命名空間一節。
從頁面或檢視轉譯元件
本節說明在無法直接從使用者要求路由傳送元件的情況下,如何將元件新增至頁面或檢視。
若要從頁面或檢視轉譯元件,請使用元件標籤協助程式。
轉譯具狀態互動式元件
具狀態互動式元件可以新增至 Razor 頁面或檢視。
當頁面或檢視轉譯時:
- 元件會與頁面或檢視一起預先轉譯。
- 用於預先轉譯的初始元件狀態會遺失。
- 在建立 SignalR 連線時會隨即建立新的元件狀態。
下列 Razor 頁面會轉譯 Counter
元件:
<h1>My Razor Page</h1>
<component type="typeof(Counter)" render-mode="ServerPrerendered"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
如需詳細資訊,請參閱 ASP.NET Core 中的元件標籤協助程式。
轉譯非互動式元件
在下列 Razor 頁面中,Counter
元件會以使用表單指定的初始值,以靜態方式轉譯。 由於元件以靜態方式轉譯,因此元件不具互動性:
<h1>My Razor Page</h1>
<form>
<input type="number" asp-for="InitialValue" />
<button type="submit">Set initial value</button>
</form>
<component type="typeof(Counter)" render-mode="Static"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
如需詳細資訊,請參閱 ASP.NET Core 中的元件標籤協助程式。
元件命名空間
在使用自訂資料夾來保存專案的 Razor 元件時,請將代表資料夾的命名空間新增至頁面/檢視或 _ViewImports.cshtml
檔案中。 在以下範例中:
- 元件會儲存在專案的
Components
資料夾中。 {APP NAMESPACE}
預留位置是專案的命名空間。Components
代表資料夾的名稱。
@using {APP NAMESPACE}.Components
_ViewImports.cshtml
檔案位於 Razor Pages 應用程式的 Pages
資料夾或 MVC 應用程式的 Views
資料夾中。
如需詳細資訊,請參閱 ASP.NET Core Razor 元件。
預先轉譯狀態大小和 SignalR 訊息大小限制
大型預先轉譯狀態大小可能超過 SignalR 線路訊息大小限制,這會導致下列結果:
- SignalR 線路無法初始化,且用戶端發生錯誤:Circuit host not initialized.
- 當線路發生中斷時,用戶端會出現重新連線的 UI。 不可能復原。
若要解決該問題,請使用下列任一種方法:
- 減少放入預先轉譯狀態的資料量。
- 新增 SignalR 訊息大小限制。 警告:增加限制可能會增加拒絕服務 (DoS) 攻擊的風險。