共用方式為


將 ASP.NET Core Razor 元件與 MVC 或 Razor Pages 整合至託管Blazor WebAssembly 解決方案中

Note

裝載 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 應用程式設定預渲染:

  1. 在 ASP.NET Core 應用程式中裝載 Blazor WebAssembly 應用程式。 獨立 Blazor WebAssembly 應用程式可以新增至 ASP.NET Core 解決方案,或者,您可以使用透過託管選項從 Blazor WebAssembly 建立的託管 Blazor WebAssembly 應用程式。

    • Visual Studio:建立 應用程式時,在 [其他資訊] 對話方塊中選取 [已託管 ASP.NET Core]Blazor WebAssembly 核取方塊。 在本文中的範例中,解決方案的名稱為 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

  2. 刪除wwwroot/index.htmlBlazor WebAssemblyClient 專案中的檔案。

  3. Client 專案中,刪除Program.cs 中的以下幾行:

    - builder.RootComponents.Add<App>("#app");
    - builder.RootComponents.Add<HeadOutlet>("head::after");
    
  4. _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
      
    • 在檔案頂端為 @using 專案新增 Client 指示詞:

      @using BlazorHosted.Client
      
    • 更新樣式表連結,以指向 WebAssembly 專案的樣式表。 在下列範例中,用戶端專案的命名空間為 BlazorHosted.Client{APP NAMESPACE} 預留位置代表提供 _Host.cshtml 檔案的捐贈者應用程式的命名空間。 更新 <component> 元件的 Tag Helper (HeadOutlet 標籤),以預先呈現元件。

      刪除:

      - <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" />
      

      Note

      將要求 Bootstrap 樣式表 (<link>) 的 css/bootstrap/bootstrap.min.css 元素保留在原處。

    • 更新 Blazor 指令碼來源以使用用戶端 Blazor WebAssembly 指令碼:

      刪除:

      - <script src="_framework/blazor.server.js"></script>
      

      新增:

      <script src="_framework/blazor.webassembly.js"></script>
      
    • render-mode更新為預先轉譯根App元件為WebAssemblyPrerendered

      刪除:

      - <component type="typeof(App)" render-mode="ServerPrerendered" />
      

      新增:

      <component type="typeof(App)" render-mode="WebAssemblyPrerendered" />
      

      重要

      驗證端點 (/authentication/ 路徑線段) 不支援預渲染。 如需詳細資訊,請參閱 ASP.NET Core Blazor WebAssembly 的其他安全性案例

  5. Program.cs 專案的 Server 檔案中,將後援端點從 index.html 檔案變更為 _Host.cshtml 頁面:

    刪除:

    - app.MapFallbackToFile("index.html");
    

    新增:

    app.MapFallbackToPage("/_Host");
    
  6. 如果 ClientServer 專案在預先轉譯期間使用一或多個一般服務,請將服務註冊納入可從這兩個專案呼叫的方法中。 如需詳細資訊,請參閱 ASP.NET Core Blazor 相依性插入

  7. 執行 Server 專案。 託管的 Blazor WebAssembly 應用程式由 Server 專案為客戶預先渲染。

將 Razor 元件內嵌至頁面或檢視的設定

以下各節和範例說明如何將Razor元件內嵌至ClientBlazor WebAssembly應用程式的頁面或伺服器應用程式的檢視表,需要額外的配置。

Server 專案必須具有下列檔案和資料夾。

Razor 頁數:

  • 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)。 具有 -o|--output 預留位置值的選項 {PROJECT NAME} 會提供應用程式的名稱,並且為應用程式建立資料夾。

在匯入的 _ViewImports.cshtml 檔案中更新命名空間,以符合接收檔案的 Server 專案所使用的命名空間。

Pages/_ViewImports.cshtml (Razor 頁數):

@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

更新匯入的配置檔案,適用於 Pages 的是 Pages/Shared/_Layout.cshtml,適用於 MVC 的是 Razor。

首先,從捐贈者專案中刪除標題和樣式表 (在下列範例中為 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

- &copy; {DATE} - {DONOR NAME} - <a asp-area="" asp-page="/Privacy">Privacy</a>
+ &copy; {DATE} - BlazorHosted - <a asp-area="" asp-page="/Privacy">Privacy</a>

在上述範例中,{DATE} 預留位置代表從 Razor Pages 或 MVC 專案範本產生的應用程式中的著作權日期。

若要讓 Privacy 鏈接導向隱私權頁面(Razor Pages),請將隱私權頁面新增至 Server 專案。

Pages/Privacy.cshtml 專案中的 Server

@page
@model PrivacyModel
@{
    ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>

<p>Use this page to detail your site's privacy policy.</p>

針對以MVC為基礎的隱私權檢視,請在 Server 專案中建立隱私權檢視。

View/Home/Privacy.cshtml 專案中的 Server

@{
    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)。

從捐贈者專案的 Server 資料夾中,將靜態資產匯入至 wwwroot 專案:

  • wwwroot/css 資料夾及其內容
  • wwwroot/js 資料夾及其內容
  • wwwroot/lib 資料夾及其內容

如果捐贈者專案是從 ASP.NET Core 專案範本建立的,且檔案並未修改,您可以將整個 wwwroot 資料夾從捐贈者專案複製到 Server 專案中,並移除 favicon 圖示檔案。

警告

請避免將靜態資產同時放入 ClientServerwwwroot 資料夾中。 如果這兩個資料夾中有相同的檔案,將會擲回例外狀況,因為靜態資產會共用相同的 Web 根目錄路徑。 因此,應在任一 wwwroot 資料夾 (而不是兩者) 中裝載靜態資產。

採用上述設定之後,將 Razor 元件內嵌至 Server 專案的頁面或檢視中。 使用本文中以下幾節的指引:

  • 使用 Component Tag Helper 在頁面或檢視上呈現元件
  • 使用 CSS 選取器在頁面或檢視中轉譯元件

使用 Component Tag Helper 在頁面或檢視中呈現元件

設定解決方案 (包括其他設定) 之後,元件標籤協助程式支援以兩種轉譯模式在頁面或檢視中轉譯 Blazor WebAssembly 應用程式中的元件:

在下列 Razor Pages 範例中,Counter 元件會在頁面中呈現。 為了使元件具有互動性,Blazor WebAssembly 腳本被包含在頁面的 渲染部分 中。 若要避免在使用 Counter () 時使用 {ASSEMBLY NAME}.Pages.Counter 元件的完整命名空間,請為用戶端專案的 @using 命名空間新增 Pages 指令。 在下列範例中,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 專案。 瀏覽至位於 Razor 的 /razorpagescounter1 頁面。 預先轉譯的 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 選取器在頁面或檢視中渲染元件

設定解決方案 (包括其他設定) 之後,請將根元件新增至 Client 檔案中的託管 Blazor WebAssembly 解決方案的 Program.cs 專案。 在下列範例中,Counter 元件會宣告為根元件,且有 CSS 選取器可選取 id 符合 counter-component 的元素。 在下列範例中,Client 專案的命名空間為 BlazorHosted.Client

Program.cs 專案的 Client 檔案中,將專案的 Razor 元件命名空間新增至檔案頂端:

using BlazorHosted.Client.Pages;

builder 中建立 Program.cs 之後,請將 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 專案。 瀏覽至位於 Razor 的 /razorpagescounter2 頁面。 預先轉譯的 Counter 元件會內嵌在頁面中。

依據元件所使用的靜態資源,以及配置頁面在應用程式中的組織方式,可能需要額外的工作。 一般而言,指令碼會新增至頁面或檢視的 Scripts 轉譯區段,而樣式表會新增至版面配置的 <head> 元素內容。

Note

在上述範例中,如果 JSException 應用程式被預先轉譯並同時使用 CSS 選取器整合至 Blazor WebAssembly Pages 或 MVC 應用程式中,則會擲回 Razor。 瀏覽至其中一個 Client 專案的 Razor 元件,或瀏覽至具有內嵌元件的 Server 頁面或檢視,將會擲回一或多個 JSException

這是正常行為,因為預渲染並整合 Blazor WebAssembly 應用程式與可路由 Razor 元件,與使用 CSS 選取器並不相容。

如果您已完成以上幾節中的範例,而想了解一下 CSS 選取器在您範例應用程式中的運作情形,請在 App 專案的 Client 檔案中將 Program.cs 根元件的規格註解化:

- builder.RootComponents.Add<App>("#app");
+ //builder.RootComponents.Add<App>("#app");

瀏覽至使用 CSS 選取器的頁面或檢視,該頁面或檢視包含內嵌的 Razor 元件(例如,前例中的 /razorpagescounter2)。 頁面或檢視會載入內嵌元件,且內嵌元件會如預期運作。

保存預先轉譯的狀態

若未保存預先轉譯的狀態,在預先轉譯期間所使用的狀態會遺失,而且必須在應用程式完全載入時重建。 如果有任何狀態是以非同步方式設定的,UI 可能會閃爍,因為預先渲染的 UI 會被替換成暫時的預留位置,然後再完整呈現。

若要為預渲染元件保持狀態,請使用 Persist Component State Tag Helper參考來源)。 在預先轉譯元件的應用程式中,將標籤協助程式的標籤 <persist-component-state /> 新增到 </body> 頁面的結尾 _Host 標記內。

Note

.NET 參考原始碼的文件連結通常會載入儲存庫的預設分支,這代表 .NET 下一版本的當前開發進度。 若要選取特定發行版本的標籤,請使用「切換分支或標籤」下拉式清單。 如需詳細資訊,請參閱如何選取 ASP.NET Core 原始程式碼 (dotnet/AspNetCore.Docs #26205) 的版本標籤

Pages/_Host.cshtml應用程式中的Blazor應用程式中,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()
    {
        if (!ApplicationState.TryTakeFromJson<{TYPE}>(
            "{TOKEN}", out var restored))
        {
            data = await ...;
        }
        else
        {
            data = restored!;
        }

        // Call at the end to avoid a potential race condition at app shutdown
        persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);
    }

    private Task PersistData()
    {
        ApplicationState.PersistAsJson("{TOKEN}", data);

        return Task.CompletedTask;
    }

    void IDisposable.Dispose()
    {
        persistingSubscription.Dispose();
    }
}

下列範例是基於 FetchData 專案範本的託管 Blazor WebAssembly 應用程式中 Blazor 元件的更新版本。 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()
    {
        if (!ApplicationState.TryTakeFromJson<WeatherForecast[]>(
            nameof(forecasts), out var restored))
        {
            forecasts = await WeatherForecastService.GetForecastAsync(
                DateOnly.FromDateTime(DateTime.Now));
        }
        else
        {
            forecasts = restored!;
        }

        // Call at the end to avoid a potential race condition at app shutdown
        persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);
    }

    private Task PersistData()
    {
        ApplicationState.PersistAsJson(nameof(forecasts), forecasts);

        return Task.CompletedTask;
    }

    void IDisposable.Dispose()
    {
        persistingSubscription.Dispose();
    }
}

通過使用與預渲染時相同的狀態來初始化組件,可以確保任何高成本的初始化步驟只執行一次。 轉譯的 UI 也會符合預先轉譯的 UI,因此瀏覽器中不會發生閃爍。

保存的預先呈現狀態會傳送至用戶端,用來還原元件狀態。 若要在託管 Blazor WebAssembly 應用程式中預先呈現數據,數據會公開給瀏覽器,且不得包含機密的私人資訊。

其他 Blazor WebAssembly 資源

預先轉譯可藉由轉譯初始 HTTP 回應的內容來改善搜尋引擎最佳化 (SEO),讓搜尋引擎可使用該回應來計算頁面排名。

解決方案設定

預渲染設定

若要為託管 Blazor WebAssembly 應用程式設定預渲染:

  1. 在 ASP.NET Core 應用程式中裝載 Blazor WebAssembly 應用程式。 獨立 Blazor WebAssembly 應用程式可以新增至 ASP.NET Core 解決方案,或者,您可以使用透過託管選項從 Blazor WebAssembly 建立的託管 Blazor WebAssembly 應用程式。

    • Visual Studio:建立 應用程式時,在 [其他資訊] 對話方塊中選取 [已託管 ASP.NET Core]Blazor WebAssembly 核取方塊。 在本文中的範例中,解決方案的名稱為 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

  2. 刪除wwwroot/index.htmlBlazor WebAssemblyClient 專案中的檔案。

  3. Client 專案中,刪除Program.cs 中的以下幾行:

    - builder.RootComponents.Add<App>("#app");
    - builder.RootComponents.Add<HeadOutlet>("head::after");
    
  4. _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
      
    • 在檔案頂端為 @using 專案新增 Client 指示詞:

      @using BlazorHosted.Client
      
    • 更新樣式表連結,以指向 WebAssembly 專案的樣式表。 在下列範例中,用戶端專案的命名空間為 BlazorHosted.Client{APP NAMESPACE} 預留位置代表提供 _Layout.cshtml 檔案的捐贈者應用程式的命名空間。 更新 <component> 元件的 Tag Helper (HeadOutlet 標籤),以預先呈現元件。

      刪除:

      - <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" />
      

      Note

      將要求 Bootstrap 樣式表 (<link>) 的 css/bootstrap/bootstrap.min.css 元素保留在原處。

    • 更新 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更新為預先轉譯根App元件為WebAssemblyPrerendered

      刪除:

      - <component type="typeof(App)" render-mode="ServerPrerendered" />
      

      新增:

      <component type="typeof(App)" render-mode="WebAssemblyPrerendered" />
      

      重要

      驗證端點 (/authentication/ 路徑線段) 不支援預渲染。 如需詳細資訊,請參閱 ASP.NET Core Blazor WebAssembly 的其他安全性案例

  5. Server 中的 Program.cs 專案端點對應中,將備援從 index.html 檔案變更為 _Host.cshtml 頁面:

    刪除:

    - app.MapFallbackToFile("index.html");
    

    新增:

    app.MapFallbackToPage("/_Host");
    
  6. 如果 ClientServer 專案在預先轉譯期間使用一或多個一般服務,請將服務註冊納入可從這兩個專案呼叫的方法中。 如需詳細資訊,請參閱 ASP.NET Core Blazor 相依性插入

  7. 執行 Server 專案。 託管的 Blazor WebAssembly 應用程式由 Server 專案為客戶預先渲染。

將 Razor 元件內嵌至頁面或檢視的設定

以下各節和範例說明如何將Razor元件內嵌至ClientBlazor WebAssembly應用程式的頁面或伺服器應用程式的檢視表,需要額外的配置。

Server 專案必須具有下列檔案和資料夾。

Razor 頁數:

  • 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)。 具有 -o|--output 預留位置值的選項 {PROJECT NAME} 會提供應用程式的名稱,並且為應用程式建立資料夾。

在匯入的 _ViewImports.cshtml 檔案中更新命名空間,以符合接收檔案的 Server 專案所使用的命名空間。

Pages/_ViewImports.cshtml (Razor 頁數):

@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

更新匯入的配置檔案,適用於 Pages 的是 Pages/Shared/_Layout.cshtml,適用於 MVC 的是 Razor。

首先,從捐贈者專案中刪除標題和樣式表 (在下列範例中為 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

- &copy; {DATE} - {DONOR NAME} - <a asp-area="" asp-page="/Privacy">Privacy</a>
+ &copy; {DATE} - BlazorHosted - <a asp-area="" asp-page="/Privacy">Privacy</a>

在上述範例中,{DATE} 預留位置代表從 Razor Pages 或 MVC 專案範本產生的應用程式中的著作權日期。

若要讓 Privacy 鏈接導向隱私權頁面(Razor Pages),請將隱私權頁面新增至 Server 專案。

Pages/Privacy.cshtml 專案中的 Server

@page
@model PrivacyModel
@{
    ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>

<p>Use this page to detail your site's privacy policy.</p>

針對以MVC為基礎的隱私權檢視,請在 Server 專案中建立隱私權檢視。

View/Home/Privacy.cshtml 專案中的 Server

@{
    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)。

從捐贈者專案的 Server 資料夾中,將靜態資產匯入至 wwwroot 專案:

  • wwwroot/css 資料夾及其內容
  • wwwroot/js 資料夾及其內容
  • wwwroot/lib 資料夾及其內容

如果捐贈者專案是從 ASP.NET Core 專案範本建立的,且檔案並未修改,您可以將整個 wwwroot 資料夾從捐贈者專案複製到 Server 專案中,並移除 favicon 圖示檔案。

警告

請避免將靜態資產同時放入 ClientServerwwwroot 資料夾中。 如果這兩個資料夾中有相同的檔案,將會擲回例外狀況,因為各個資料夾中的靜態資產會共用相同的 Web 根目錄路徑。 因此,應在任一 wwwroot 資料夾 (而不是兩者) 中裝載靜態資產。

採用上述設定之後,將 Razor 元件內嵌至 Server 專案的頁面或檢視中。 使用本文中以下幾節的指引:

  • 使用 Component Tag Helper 在頁面或檢視上呈現元件
  • 使用 CSS 選取器在頁面或檢視中轉譯元件

使用 Component Tag Helper 在頁面或檢視中呈現元件

設定解決方案 (包括其他設定) 之後,元件標籤協助程式支援以兩種轉譯模式在頁面或檢視中轉譯 Blazor WebAssembly 應用程式中的元件:

在下列 Razor Pages 範例中,Counter 元件會在頁面中呈現。 為了使元件具有互動性,Blazor WebAssembly 腳本被包含在頁面的 渲染部分 中。 若要避免在使用 Counter () 時使用 {ASSEMBLY NAME}.Pages.Counter 元件的完整命名空間,請為用戶端專案的 @using 命名空間新增 Pages 指令。 在下列範例中,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 專案。 瀏覽至位於 Razor 的 /razorpagescounter1 頁面。 預先轉譯的 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 選取器在頁面或檢視中渲染元件

設定解決方案 (包括其他設定) 之後,請將根元件新增至 Client 檔案中的託管 Blazor WebAssembly 解決方案的 Program.cs 專案。 在下列範例中,Counter 元件會宣告為根元件,且有 CSS 選取器可選取 id 符合 counter-component 的元素。 在下列範例中,Client 專案的命名空間為 BlazorHosted.Client

Program.cs 專案的 Client 檔案中,將專案的 Razor 元件命名空間新增至檔案頂端:

using BlazorHosted.Client.Pages;

builder 中建立 Program.cs 之後,請將 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 專案。 瀏覽至位於 Razor 的 /razorpagescounter2 頁面。 預先轉譯的 Counter 元件會內嵌在頁面中。

依據元件所使用的靜態資源,以及配置頁面在應用程式中的組織方式,可能需要額外的工作。 一般而言,指令碼會新增至頁面或檢視的 Scripts 轉譯區段,而樣式表會新增至版面配置的 <head> 元素內容。

Note

在上述範例中,如果 JSException 應用程式被預先轉譯並同時使用 CSS 選取器整合至 Blazor WebAssembly Pages 或 MVC 應用程式中,則會擲回 Razor。 瀏覽至其中一個 Client 專案的 Razor 元件,或瀏覽至具有內嵌元件的 Server 頁面或檢視,將會擲回一或多個 JSException

這是正常行為,因為預渲染並整合 Blazor WebAssembly 應用程式與可路由 Razor 元件,與使用 CSS 選取器並不相容。

如果您已完成以上幾節中的範例,而想了解一下 CSS 選取器在您範例應用程式中的運作情形,請在 App 專案的 Client 檔案中將 Program.cs 根元件的規格註解化:

- builder.RootComponents.Add<App>("#app");
+ //builder.RootComponents.Add<App>("#app");

瀏覽至使用 CSS 選取器的頁面或檢視,該頁面或檢視包含內嵌的 Razor 元件(例如,前例中的 /razorpagescounter2)。 頁面或檢視會載入內嵌元件,且內嵌元件會如預期運作。

保存預先轉譯的狀態

若未保存預先轉譯的狀態,在預先轉譯期間所使用的狀態會遺失,而且必須在應用程式完全載入時重建。 如果有任何狀態是以非同步方式設定的,UI 可能會閃爍,因為預先渲染的 UI 會被替換成暫時的預留位置,然後再完整呈現。

為了解決這些問題,Blazor 支援使用維持元件狀態標籤協助程式在預渲染的頁面中維持狀態。 將標籤協助程式的標籤 <persist-component-state /> 新增到結尾的 </body> 標籤內。

Pages/_Layout.cshtml

<body>
    ...

    <persist-component-state />
</body>

使用 PersistentComponentState 服務決定要保存哪個狀態。 在應用程式暫停前,PersistentComponentState.RegisterOnPersisting 會註冊回呼,以保存元件狀態。 應用程式繼續時會擷取此狀態。 在初始化程式代碼結束時進行呼叫,以避免在應用程式關機期間發生潛在的競爭狀況。

下列範例是基於 FetchData 專案範本的託管 Blazor WebAssembly 應用程式中 Blazor 元件的更新版本。 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()
    {
        if (!ApplicationState.TryTakeFromJson<WeatherForecast[]>(
            nameof(forecasts), out var restored))
        {
            forecasts = 
                await WeatherForecastService.GetForecastAsync(DateTime.Now);
        }
        else
        {
            forecasts = restored!;
        }

        // Call at the end to avoid a potential race condition at app shutdown
        persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);
    }

    private Task PersistData()
    {
        ApplicationState.PersistAsJson(nameof(forecasts), forecasts);

        return Task.CompletedTask;
    }

    void IDisposable.Dispose()
    {
        persistingSubscription.Dispose();
    }
}

通過使用與預渲染時相同的狀態來初始化組件,可以確保任何高成本的初始化步驟只執行一次。 轉譯的 UI 也會符合預先轉譯的 UI,因此瀏覽器中不會發生閃爍。

保存的預先呈現狀態會傳送至用戶端,用來還原元件狀態。 若要在託管 Blazor WebAssembly 應用程式中預先呈現數據,數據會公開給瀏覽器,且不得包含機密的私人資訊。

其他 Blazor WebAssembly 資源

預先轉譯可藉由轉譯初始 HTTP 回應的內容來改善搜尋引擎最佳化 (SEO),讓搜尋引擎可使用該回應來計算頁面排名。

解決方案設定

預渲染設定

若要為託管 Blazor WebAssembly 應用程式設定預渲染:

  1. 在 ASP.NET Core 應用程式中裝載 Blazor WebAssembly 應用程式。 獨立 Blazor WebAssembly 應用程式可以新增至 ASP.NET Core 解決方案,或者,您可以使用透過託管選項從 Blazor WebAssembly 建立的託管 Blazor WebAssembly 應用程式。

    • Visual Studio:建立 應用程式時,在 [其他資訊] 對話方塊中選取 [已託管 ASP.NET Core]Blazor WebAssembly 核取方塊。 在本文中的範例中,解決方案的名稱為 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

  2. 刪除wwwroot/index.htmlBlazor WebAssemblyClient 專案中的檔案。

  3. Client 專案中,刪除Program.cs 中的以下這一行:

    - builder.RootComponents.Add<App>("#app");
    
  4. Pages/_Host.cshtml 檔案新增至 Server 專案的 Pages 資料夾。 您可以在命令殼層中使用 _Host.cshtml 命令,從使用 Blazor Server 範本建立的專案中取得 dotnet new blazorserver -o BlazorServer 檔案 (-o BlazorServer 選項會為專案建立資料夾)。 將 Pages/_Host.cshtml 檔案放入託管 Server 解決方案的 Blazor WebAssembly 專案之後,請對檔案進行下列變更:

    • @using 專案提供 Client 指令 (例如 @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" />
      

      Note

      將要求 Bootstrap 樣式表 (<link>) 的 css/bootstrap/bootstrap.min.css 元素保留在原處。

    • render-mode更新為預先轉譯根App元件為WebAssemblyPrerendered

      - <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>
      
  5. Startup.Configure 專案的 Server 中,將備援從 index.html 檔案改為 _Host.cshtml 頁面。

    Startup.cs

    - endpoints.MapFallbackToFile("index.html");
    + endpoints.MapFallbackToPage("/_Host");
    
  6. 如果 ClientServer 專案在預先轉譯期間使用一或多個一般服務,請將服務註冊納入可從這兩個專案呼叫的方法中。 如需詳細資訊,請參閱 ASP.NET Core Blazor 相依性插入

  7. 執行 Server 專案。 託管的 Blazor WebAssembly 應用程式由 Server 專案為客戶預先渲染。

將 Razor 元件內嵌至頁面或檢視的設定

本文中的下列各節和範例,旨在將用戶端應用程式Razor的元件嵌入Blazor WebAssembly到伺服器應用程式的頁面或檢視中,這需要額外的設定。

在 Razor 專案中使用預設的 Server Pages 或 MVC 配置檔案。 Server 專案必須具有下列檔案和資料夾。

Razor 頁數:

  • 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 頁面) 或 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>

匯入的配置包含 HomePrivacy 導覽連結。 若要使 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 鏈接導向隱私權頁面,請將隱私權頁面新增至 Server 專案。

Pages/Privacy.cshtml 專案中的 Server

@page
@model BlazorHosted.Server.Pages.PrivacyModel
@{
}

<h1>Privacy Policy</h1>

如果偏好使用MVC型隱私權檢視,請在 Server 專案中建立隱私權檢視。

View/Home/Privacy.cshtml

@{
    ViewData["Title"] = "Privacy Policy";
}

<h1>@ViewData["Title"]</h1>

Home 控制器中,傳回檢視。

Controllers/HomeController.cs

public IActionResult Privacy()
{
    return View();
}

從捐贈者專案的 Server 資料夾中,將靜態資產匯入至 wwwroot 專案:

  • wwwroot/css 資料夾及其內容
  • wwwroot/js 資料夾及其內容
  • wwwroot/lib 資料夾及其內容

如果捐贈者專案是從 ASP.NET Core 專案範本建立的,且檔案並未修改,您可以將整個 wwwroot 資料夾從捐贈者專案複製到 Server 專案中,並移除 favicon 圖示檔案。

警告

請避免將靜態資產同時放入 ClientServerwwwroot 資料夾中。 如果這兩個資料夾中有相同的檔案,將會擲回例外狀況,因為各個資料夾中的靜態資產會共用相同的 Web 根目錄路徑。 因此,應在任一 wwwroot 資料夾 (而不是兩者) 中裝載靜態資產。

使用 Component Tag Helper 在頁面或檢視中呈現元件

設定解決方案 (包括其他設定) 之後,元件標籤協助程式支援以兩種轉譯模式在頁面或檢視中轉譯 Blazor WebAssembly 應用程式中的元件:

在下列 Razor Pages 範例中,Counter 元件會在頁面中呈現。 為了使元件具有互動性,Blazor WebAssembly 腳本被包含在頁面的 渲染部分 中。 若要避免在使用 Counter () 時使用 {ASSEMBLY NAME}.Pages.Counter 元件的完整命名空間,請為用戶端專案的 @using 命名空間新增 Pages 指令。 在下列範例中,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 專案。 瀏覽至位於 Razor 的 /razorpagescounter1 頁面。 預先轉譯的 Counter 元件會內嵌在頁面中。

RenderMode 配置元件是否:

  • 被預渲染到頁面中。
  • 是否在頁面上呈現為靜態 HTML,或包含從使用者代理啟動 Blazor 應用程式所需的資訊。

如需元件標籤協助程式的詳細資訊 (包括傳遞參數和 RenderMode 設定),請參閱 ASP.NET Core 中的元件標籤協助程式

依據元件所使用的靜態資源,以及配置頁面在應用程式中的組織方式,可能需要額外的工作。 一般而言,指令碼會新增至頁面或檢視的 Scripts 轉譯區段,而樣式表會新增至版面配置的 <head> 元素內容。

使用 CSS 選取器在頁面或檢視中渲染元件

設定解決方案 (包括其他設定) 之後,請將根元件新增至 Client 中的託管 Blazor WebAssembly 解決方案的 Program.cs 專案。 在下列範例中,Counter 元件會宣告為根元件,且有 CSS 選取器可選取 id 符合 counter-component 的元素。 在下列範例中,Client 專案的命名空間為 BlazorHosted.Client

Program.cs 專案的 Client 中,將專案的 Razor 元件命名空間新增至檔案頂端:

using BlazorHosted.Client.Pages;

builder 中建立 Program.cs 之後,請將 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 專案。 瀏覽至位於 Razor 的 /razorpagescounter2 頁面。 預先轉譯的 Counter 元件會內嵌在頁面中。

依據元件所使用的靜態資源,以及配置頁面在應用程式中的組織方式,可能需要額外的工作。 一般而言,指令碼會新增至頁面或檢視的 Scripts 轉譯區段,而樣式表會新增至版面配置的 <head> 元素內容。

Note

在上述例子中,如果 JSException 應用程式已預先轉譯並且同時使用 CSS 選取器整合至 Blazor WebAssembly Pages 或 MVC 應用程式中,則會擲回 Razor。 瀏覽至 Client 專案的其中一個 Razor 元件時,會拋出下列例外狀況:

Microsoft.JSInterop.JSException:找不到任何符合選取器「#counter-component」的元素。

這是正常行為,因為預渲染並整合 Blazor WebAssembly 應用程式與可路由 Razor 元件,與使用 CSS 選取器並不相容。

其他 Blazor WebAssembly 資源

.NET 5 或更新版本中的 ASP.NET Core 支援將 Razor 元件整合到 Razor 裝載 Blazor WebAssembly解決方案 中的 Pages 或 MVC 應用程式。 選取本文的 .NET 5 或更新版本。