將 ASP.NET 核心Razor元件與裝載Blazor WebAssembly解決方案中的MVC或 Razor Pages整合
注意
裝載 Blazor WebAssembly 的解決方案仍受支援,但已移除專案範本,且在 .NET 8 或更新版本中不再受到支援。 本文會出現在最多 .NET 7 的目錄中以供參考,但請注意,.NET 7 是 不再支援的標準支援字詞 版本。
警告
不再支援此版本的 ASP.NET Core。 如需詳細資訊,請參閱 .NET 和 .NET Core 支持原則。
本文說明 Razor 裝載 Blazor WebAssembly 應用程式的元件整合案例,包括預先呈現 Razor 伺服器上的元件。
重要
不同 ASP.NET Core 版本的架構變更,導致本文提供了不同的指示集。 使用本文的指引之前,請確認本文頂端的檔版本選取器符合您想要用於應用程式的 ASP.NET Core 版本。
預先轉譯可藉由轉譯初始 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 元件內嵌至頁面或檢視的設定
下列各節和範例,可將應用程式中的ClientBlazor WebAssembly元件內嵌Razor至伺服器應用程式的頁面或檢視表,需要額外的設定。
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
)。 頁面或檢視會載入內嵌元件,且內嵌元件會如預期運作。
保存預先轉譯的狀態
若未保存預先轉譯的狀態,在預先轉譯期間所使用的狀態會遺失,而且必須在應用程式完全載入時重建。 如果以非同步方式設定了任何狀態,UI 可能會閃動,因為預先轉譯的 UI 會取代為暫時的預留位置,然後再次完整轉譯。
若要保存預先轉譯元件的狀態,請使用保存元件狀態標記協助程式 (參考來源)。 在預先轉譯元件的應用程式中 _Host
頁面的結尾 </body>
標記內,新增標記協助程式的標記 <persist-component-state />
。
注意
.NET 參考來源的文件連結通常會載入存放庫的預設分支,這表示下一版 .NET 的目前開發。 若要選取特定版本的標籤,請使用 [切換分支或標籤] 下拉式清單。 如需詳細資訊,請參閱如何選取 ASP.NET Core 原始程式碼 (dotnet/AspNetCore.Docs #26205) 的版本標籤。
Blazor在Pages/_Host.cshtml
載入應用程式中的 WebAssembly 預先呈現 (WebAssemblyPrerendered
) Blazor WebAssembly 應用程式中:
<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 應用程式中預先呈現數據,數據會公開給瀏覽器,且不得包含機密的私人資訊。
其他 Blazor WebAssembly 資源
- 狀態管理:處理預先轉譯
- 組件延遲載入的預先轉譯支援
- 與預先轉譯相關的 Razor 元件生命週期主題
- 元件初始化 (
OnInitialized{Async}
) - 元件轉譯之後 (
OnAfterRender{Async}
) - 預先轉譯之後的具狀態重新連線:雖然本節內容著重於 Blazor Server 和具狀態的 SignalR重新連線,但託管 Blazor WebAssembly 應用程式 (WebAssemblyPrerendered) 中的預先轉譯案例涉及類似條件和方法,以防止開發人員程式碼執行兩次。 若要在預先轉譯時執行初始化程式碼期間保留狀態,請參閱本文的保存預先轉譯的狀態一節。
- 使用 JavaScript Interop 預先轉譯
- 元件初始化 (
- 關於預先轉譯的驗證和授權主題
- 裝載和部署:Blazor WebAssembly
- 處理錯誤:預先轉譯
- OnNavigateAsync 會在預先轉譯時執行兩次:使用
OnNavigateAsync
處理非同步導覽事件
預先轉譯可藉由轉譯初始 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 元件內嵌至頁面或檢視的設定
下列各節和範例,可將應用程式中的ClientBlazor WebAssembly元件內嵌Razor至伺服器應用程式的頁面或檢視表,需要額外的設定。
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
)。 頁面或檢視會載入內嵌元件,且內嵌元件會如預期運作。
保存預先轉譯的狀態
若未保存預先轉譯的狀態,在預先轉譯期間所使用的狀態會遺失,而且必須在應用程式完全載入時重建。 如果以非同步方式設定了任何狀態,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 應用程式中預先呈現數據,數據會公開給瀏覽器,且不得包含機密的私人資訊。
其他 Blazor WebAssembly 資源
- 狀態管理:處理預先轉譯
- 組件延遲載入的預先轉譯支援
- 與預先轉譯相關的 Razor 元件生命週期主題
- 元件初始化 (
OnInitialized{Async}
) - 元件轉譯之後 (
OnAfterRender{Async}
) - 預先轉譯之後的具狀態重新連線:雖然本節內容著重於 Blazor Server 和具狀態的 SignalR重新連線,但託管 Blazor WebAssembly 應用程式 (WebAssemblyPrerendered) 中的預先轉譯案例涉及類似條件和方法,以防止開發人員程式碼執行兩次。 若要在預先轉譯時執行初始化程式碼期間保留狀態,請參閱本文的保存預先轉譯的狀態一節。
- 使用 JavaScript Interop 預先轉譯
- 元件初始化 (
- 關於預先轉譯的驗證和授權主題
- 裝載和部署:Blazor WebAssembly
預先轉譯可藉由轉譯初始 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 選取器並不相容。
其他 Blazor WebAssembly 資源
- 狀態管理:處理預先轉譯
- 組件延遲載入的預先轉譯支援
- 與預先轉譯相關的 Razor 元件生命週期主題
- 元件初始化 (
OnInitialized{Async}
) - 元件轉譯之後 (
OnAfterRender{Async}
) - 預先轉譯之後的具狀態重新連線:雖然本節內容著重於 Blazor Server 和具狀態的 SignalR重新連線,但託管 Blazor WebAssembly 應用程式 (WebAssemblyPrerendered) 中的預先轉譯案例涉及類似條件和方法,以防止開發人員程式碼執行兩次。 若要在預先轉譯時執行初始化程式碼期間保留狀態,請參閱本文的保存預先轉譯的狀態一節。
- 使用 JavaScript Interop 預先轉譯
- 元件初始化 (
- 關於預先轉譯的驗證和授權主題
- 裝載和部署:Blazor WebAssembly
.NET 5 或更新版本中的 ASP.NET Core 支援將 Razor 元件整合到 Razor 裝載 Blazor WebAssembly解決方案 中的 Pages 或 MVC 應用程式。 選取本文的 .NET 5 或更新版本。