共用方式為


多個託管的 ASP.NET Core Blazor WebAssembly 應用程式

備註

這不是本文的最新版本。 如需本文的最新版本,請參閱 .NET 7 版本

本文說明如何設定託管 Blazor WebAssembly 應用程式以裝載多個 Blazor WebAssembly 應用程式。

設定

選取符合您裝載需求的本文版本,例如埠:5001/:5002firstapp.com/secondapp.com/網域裝載 (例如 或 ) 或路由子路徑裝載 (例如 和 )。 /FirstApp/SecondApp

使用目前的託管選項,本文涵蓋連接埠/網域託管(例如 或 :5001/:5002firstapp.com/secondapp.com)。

在下列範例中:

  • 託管 Blazor WebAssembly 應用程式的專案名稱位於 MultipleBlazorApps 名為 MultipleBlazorApps的資料夾中。
  • 在新增第二個用戶端應用程式之前,解決方案中的三個專案位於MultipleBlazorApps.ClientClient資料夾、MultipleBlazorApps.Server資料夾ServerMultipleBlazorApps.Shared資料夾中Shared
  • 初始 (第一個) 用戶端應用程式是從專案範本建立 Blazor WebAssembly 之解決方案的預設用戶端專案。
  • 第二個用戶端應用程式會新增至解決方案,位於名為 MultipleBlazorApps.SecondClient的資料夾中。 SecondClient
  • 或者,伺服器專案 (MultipleBlazorApps.Server) 可以將頁面或檢視作為 Pages 或 MVC 應用程式提供 Razor 。
  • 第一個用戶端應用程式可在瀏覽器中存取連接埠 5001 或 firstapp.com主機 . 第二個用戶端應用程式可在瀏覽器中存取連接埠 5002 或 secondapp.com主機 .

在目前的選取專案中,本文涵蓋路由子路徑裝載 (例如 和 /FirstApp/SecondApp)。

在下列範例中:

  • 託管 Blazor WebAssembly 應用程式的專案名稱位於 MultipleBlazorApps 名為 MultipleBlazorApps的資料夾中。
  • 在新增第二個用戶端應用程式之前,解決方案中的三個專案位於MultipleBlazorApps.ClientClient資料夾、MultipleBlazorApps.Server資料夾ServerMultipleBlazorApps.Shared資料夾中Shared
  • 初始 (第一個) 用戶端應用程式是從專案範本建立 Blazor WebAssembly 之解決方案的預設用戶端專案。
  • 第二個用戶端應用程式會新增至解決方案,位於名為 MultipleBlazorApps.SecondClient的資料夾中。 SecondClient
  • 或者,伺服器專案 (MultipleBlazorApps.Server) 可以將頁面或檢視作為正式 Razor 的 Pages 或 MVC 應用程式提供。
  • 這兩個用戶端應用程式都會使用專案檔案MultipleBlazorApps.Server在其Properties/launchSettings.json值中定義的applicationUrl預設連接埠。 第一個用戶端應用程式可在子路徑的 /FirstApp 瀏覽器中存取。 第二個用戶端應用程式可在子路徑的 /SecondApp 瀏覽器中存取。

本文中顯示的範例需要針對以下項目進行額外設定:

  • 直接在範例主機網域存取應用程式, firstapp.com 以及 secondapp.com
  • 用戶端應用程式的憑證,以啟用 TLS/HTTPS 安全性。
  • 將伺服器應用程式設定為 Razor Pages 應用程式,以取得下列功能:
    • 將 Razor 元件整合到頁面或檢視中。
    • 預先轉譯 Razor 元件。

上述設定超出本文的範圍。 如需詳細資訊,請參閱下列資源:

使用現有的裝載Blazor WebAssembly解決方案,或從專案範本建立Blazor WebAssembly,方法是傳遞Blazor WebAssembly選項(如果使用 .NET CLI),或在 IDE 中建立專案時,在 Visual Studio 中選取 [-ho|--hosted 核取方塊。

使用名為 MultipleBlazorApps 的解決方案資料夾,並將專案 MultipleBlazorApps命名為 。

在解決方案 SecondClient中建立名為 的新資料夾。 在新資料夾中,新增名為 Blazor WebAssembly的第二個MultipleBlazorApps.SecondClient用戶端應用程式。 將專案新增為獨立 Blazor WebAssembly 應用程式。 若要建立獨立 Blazor WebAssembly 應用程式,如果使用 .NET CLI,請勿傳遞選項,如果使用 Visual Studio,請勿使用 -ho|--hostedASP.NET Core Hosted 核取方塊。

對專案進行 MultipleBlazorApps.SecondClient 下列變更:

  • 將元件 () 從FetchData資料夾複製Pages/FetchData.razor到資料夾Client/PagesSecondClient/Pages 此步驟是必要的,因為獨立 Blazor WebAssembly 應用程式不會呼叫 Server 專案的控制器來取得天氣資料,而是使用靜態資料檔案。 藉由將 FetchData 元件複製到新增的專案,第二個用戶端應用程式也會對伺服器 API 進行 Web API 呼叫,以取得天氣資料。
  • 刪除 SecondClient/wwwroot/sample-data 資料夾,因為 weather.json 不會使用資料夾中的檔案。

下表說明新增資料夾和SecondClient專案之後MultipleBlazorApps.SecondClient的解決方案資料夾和專案名稱。

實體資料夾 專案名稱 說明
Client MultipleBlazorApps.Client Blazor WebAssembly 用戶端應用程式
SecondClient MultipleBlazorApps.SecondClient Blazor WebAssembly 用戶端應用程式
Server MultipleBlazorApps.Server ASP.NET Core 伺服器應用程式
Shared MultipleBlazorApps.Shared 共用資源專案

專案會 MultipleBlazorApps.Server 為兩個 Blazor WebAssembly 用戶端應用程式提供服務,並透過 MVC 控制器將天氣資料提供給用戶端應用程式的 FetchData 元件。 或者,專案 MultipleBlazorApps.Server 也可以作為傳統的 Razor Pages 或 MVC 應用程式提供頁面或檢視。 啟用放送頁面或檢視的步驟將在本文稍後介紹。

備註

本文中的示範會針對專案和FirstAppMultipleBlazorApps.Client專案使用 的SecondAppMultipleBlazorApps.SecondClient靜態 Web 資產路徑名稱。 “”和FirstApp“”這個名稱SecondApp僅供演示。 其他名稱可以區分用戶端應用程式,例如 App1/App2、 、Client1/Client21/2 或任何類似的命名配置。

透過埠或網域將要求路由傳送至用戶端應用程式時,FirstApp會使用 “SecondApp” 和 “” 來路由傳送要求,並為靜態資產提供回應,而且不會顯示在瀏覽器的網址列中。

備註

本文中的示範會針對專案和FirstAppMultipleBlazorApps.Client專案使用 的SecondAppMultipleBlazorApps.SecondClient靜態 Web 資產路徑名稱。 “”和FirstApp“”這個名稱SecondApp僅供演示。 其他名稱可以區分用戶端應用程式,例如 App1/App2、 、Client1/Client21/2 或任何類似的命名配置。

FirstApp” 和 “SecondApp” 也會出現在瀏覽器的網址列中,因為使用這些名稱將請求路由傳送到兩個用戶端應用程式。 支援其他有效的 URL 路由區段,而且路由區段並不嚴格需要符合用於在內部路由靜態 Web 資產的名稱。 針對內部靜態資產路由和應用程式要求路由使用 “FirstApp” 和 “SecondApp” 只是為了本文範例中的召集。

在第一個用戶端應用程式的專案檔案 ()MultipleBlazorApps.Client.csproj 中,將屬性新增至<StaticWebAssetBasePath><PropertyGroup>為 ,FirstApp以設定專案靜態資產的基底路徑:

<StaticWebAssetBasePath>FirstApp</StaticWebAssetBasePath>

在應用程式的專案檔案中 MultipleBlazorApps.SecondClientMultipleBlazorApps.SecondClient.csproj):

  • 將屬性新增至 <StaticWebAssetBasePath><PropertyGroup> 其值 SecondApp為 :

    <StaticWebAssetBasePath>SecondApp</StaticWebAssetBasePath>
    
  • 將專案的MultipleBlazorApps.Shared專案參照新增至:<ItemGroup>

    <ItemGroup>
      <ProjectReference Include="..\Shared\MultipleBlazorApps.Shared.csproj" />
    </ItemGroup>
    

在伺服器應用程式的專案檔案 ()Server/MultipleBlazorApps.Server.csproj 中,為新增 MultipleBlazorApps.SecondClient 的用戶端應用程式 <ItemGroup>建立專案參考:

<ProjectReference Include="..\SecondClient\MultipleBlazorApps.SecondClient.csproj" />

在伺服器應用程式的Properties/launchSettings.json檔案中,設定設定檔 (applicationUrl) 的 Kestrel ,MultipleBlazorApps.Server以存取連接埠 5001 和 5002 的用戶端應用程式。 如果您將本機環境配置為使用範例網域,則 的 applicationUrl URL 可以使用 firstapp.comsecondapp.com 而不使用埠。

備註

在此示範中使用連接埠可讓您在本機瀏覽器中存取用戶端專案,而不需要設定本機裝載環境,以便 Web 瀏覽器可以透過主機設定存取用戶端應用程式, firstapp.com 以及 secondapp.com。 在生產案例中,一般設定是使用子網域來區分用戶端應用程式。

例如:

  • 埠將從本演示的配置中刪除。
  • 主機會變更為使用子網域,例如 www.contoso.com 網站訪客和 admin.contoso.com 管理員。
  • 其他用戶端應用程式可以包含其他主機,如果伺服器應用程式也是 Razor 提供頁面或檢視的 Pages 或 MVC 應用程式,則至少需要一個主機。

如果您打算從伺服器應用程式提供頁面或檢視,請在檔案中使用applicationUrl下列Properties/launchSettings.json設定,以允許下列存取:

  • 或者, Razor Pages 或 MVC 應用程式 (MultipleBlazorApps.Server 專案) 會回應埠 5000 的要求。
  • 對第一個客戶端(MultipleBlazorApps.Client 專案)請求的響應位於埠 5001。
  • 對第二個客戶端(MultipleBlazorApps.SecondClient 專案)請求的回應位於連接埠 5002。
"applicationUrl": "https://localhost:5000;https://localhost:5001;https://localhost:5002",

如果您不打算讓伺服器應用程式提供頁面或檢視,而只提供 Blazor WebAssembly 用戶端應用程式,請使用下列設定,以允許下列存取:

  • 第一個用戶端應用程式會在埠 5001 上回應。
  • 第二個用戶端應用程式會在埠 5002 上回應。
"applicationUrl": "https://localhost:5001;https://localhost:5002",

在伺服器應用程式的 Program.cs 檔案中,移除下列程式碼,該程式碼會出現在呼叫之後 UseHttpsRedirection

  • 如果您打算從伺服器應用程式提供頁面或檢視,請刪除下列程式碼行:

    - app.UseBlazorFrameworkFiles();
    
    - app.MapFallbackToFile("index.html");
    
  • 如果您計劃讓伺服器應用程式只提供 Blazor WebAssembly 用戶端應用程式,請刪除下列程式碼:

    - app.UseBlazorFrameworkFiles();
    
    ...
    
    - app.UseRouting();
    
    - app.MapRazorPages();
    - app.MapControllers();
    - app.MapFallbackToFile("index.html");
    

    將靜態檔案中介軟體保留在原地:

    app.UseStaticFiles();
    
  • 新增中介軟體,將要求對應至用戶端應用程式。 下列範例會將中介軟體設定為在第一個用戶端應用程式的要求埠為 5001 或第二個用戶端應用程式的 5002,或要求主機 firstapp.com 為第一個用戶端應用程式或 secondapp.com 第二個用戶端應用程式時執行。

    備註

    在本機系統上使用具有本機瀏覽器的主機 (firstapp.com/secondapp.com) 需要其他設定,這超出了本文的範圍。 對於此案例的本機測試,建議您使用連接埠。 一般生產應用程式會設定為使用子網域,例如 www.contoso.com 網站訪客和 admin.contoso.com 管理員。 使用正確的 DNS 和伺服器設定 (超出本文的範圍,且取決於所使用的技術),應用程式會回應下列程式碼中命名的任何主機的要求。

    從 中app.UseBlazorFrameworkFiles();移除該行Program.cs的位置,將下列程式碼放在:

    app.MapWhen(ctx => ctx.Request.Host.Port == 5001 || 
        ctx.Request.Host.Equals("firstapp.com"), first =>
    {
        first.Use((ctx, nxt) =>
        {
            ctx.Request.Path = "/FirstApp" + ctx.Request.Path;
            return nxt();
        });
    
        first.UseBlazorFrameworkFiles("/FirstApp");
        first.UseStaticFiles();
        first.UseStaticFiles("/FirstApp");
        first.UseRouting();
    
        first.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapFallbackToFile("/FirstApp/{*path:nonfile}", 
                "FirstApp/index.html");
        });
    });
    
    app.MapWhen(ctx => ctx.Request.Host.Port == 5002 || 
        ctx.Request.Host.Equals("secondapp.com"), second =>
    {
        second.Use((ctx, nxt) =>
        {
            ctx.Request.Path = "/SecondApp" + ctx.Request.Path;
            return nxt();
        });
    
        second.UseBlazorFrameworkFiles("/SecondApp");
        second.UseStaticFiles();
        second.UseStaticFiles("/SecondApp");
        second.UseRouting();
    
        second.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapFallbackToFile("/SecondApp/{*path:nonfile}", 
                "SecondApp/index.html");
        });
    });
    

    警告

    依賴於主機標頭的 API (例如 HttpRequest.HostRequireHost) 可能會受到用戶端的詐騙。

    若要防止主機和連接埠詐騙,請使用下列其中一種方式:

  • 新增中介軟體,將要求對應至用戶端應用程式。 下列範例會將中介軟體設定為在要求子路徑 /FirstApp 適用於第一個用戶端應用程式或 /SecondApp 第二個用戶端應用程式時執行。

    從 中app.UseBlazorFrameworkFiles();移除該行Program.cs的位置,將下列程式碼放在:

    app.MapWhen(ctx => ctx.Request.Path.StartsWithSegments("/FirstApp", 
        StringComparison.OrdinalIgnoreCase), first =>
    {
        first.UseBlazorFrameworkFiles("/FirstApp");
        first.UseStaticFiles();
        first.UseStaticFiles("/FirstApp");
        first.UseRouting();
    
        first.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapFallbackToFile("/FirstApp/{*path:nonfile}",
                "FirstApp/index.html");
        });
    });
    
    app.MapWhen(ctx => ctx.Request.Path.StartsWithSegments("/SecondApp", 
        StringComparison.OrdinalIgnoreCase), second =>
    {
        second.UseBlazorFrameworkFiles("/SecondApp");
        second.UseStaticFiles();
        second.UseStaticFiles("/SecondApp");
        second.UseRouting();
    
        second.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapFallbackToFile("/SecondApp/{*path:nonfile}",
                "SecondApp/index.html");
        });
    });
    
  • 在每個用戶端應用程式中設定基本路徑:

    在第一個用戶端應用程式的 index.html 檔案 ()Client/wwwroot/index.html 中,更新 <base> 標籤值以反映子路徑。 尾端斜線是必需的:

    <base href="/FirstApp/" />
    

    在第二個用戶端應用程式的 index.html 檔案 ()SecondClient/wwwroot/index.html 中,更新 <base> 標籤值以反映子路徑。 尾端斜線是必需的:

    <base href="/SecondApp/" />
    

如需 的詳細資訊 UseStaticFiles,請參閱 ASP.NET Core Blazor 靜態檔案

如需 和 UseBlazorFrameworkFiles的詳細資訊MapFallbackToFile,請參閱下列資源:

備註

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

從用戶端應用程式/WeatherForecast到伺服器 API 中的請求是對/FirstApp/WeatherForecast/SecondApp/WeatherForecast或取決於哪個用戶端應用程式提出請求。 因此,從伺服器 API 傳回天氣資料的控制器路由需要修改以包含路徑區段。

在伺服器應用程式的天氣預報控制器 (Controllers/WeatherForecastController.cs) 中,將現有路由 ([Route("[controller]")]WeatherForecastController 取代為下列路由,其中會考慮用戶端要求路徑:

[Route("FirstApp/[controller]")]
[Route("SecondApp/[controller]")]

如果您打算從伺服器應用程式提供頁面,請將頁面Index新增至RazorPages伺服器應用程式的資料夾:

Pages/Index.cshtml

@page
@model MultipleBlazorApps.Server.Pages.IndexModel
@{
    ViewData["Title"] = "Home";
}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>Home</title>
</head>
<body>
    <div class="main">
        <div class="content px-4">

            <div>
                <h1>Welcome</h1>
                <p>Hello from Razor Pages!</p>
            </div>
        </div>
    </div>
</body>
</html>

Pages/Index.cshtml.cs

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace MultipleBlazorApps.Server.Pages;

public class IndexModel : PageModel
{
    public void OnGet()
    {
    }
}
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace MultipleBlazorApps.Server.Pages
{
    public class IndexModel : PageModel
    {
        public void OnGet()
        {
        }
    }
}

備註

Index 一頁是一個純粹用於演示目的的最小示例。 如果應用程式需要其他 Razor Pages 資產,例如版面配置、樣式、指令碼和匯入,請從 Pages 專案範本建立 Razor 的應用程式取得這些資產。 如需詳細資訊,請參閱 Razor ASP.NET Core 中的 Pages 架構和概念

如果您打算從伺服器應用程式提供 MVC 檢視,請新增 Index 檢視和 Home 控制器:

Views/Home/Index.cshtml

@{
    ViewData["Title"] = "Home";
}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>Home</title>
</head>
<body>
    <div class="main">
        <div class="content px-4">

            <div>
                <h1>Welcome</h1>
                <p>Hello from MVC!</p>
            </div>
        </div>
    </div>
</body>
</html>

Controllers/HomeController.cs

using Microsoft.AspNetCore.Mvc;

namespace MultipleBlazorApps.Server.Controllers;

public class HomeController : Controller
{
    public IActionResult Index() => View();
}

備註

上述 Index 檢視是純粹用於示範目的的最小範例。 如果應用程式需要其他 MVC 資產,例如版面配置、樣式、腳本和匯入,請從從 MVC 專案範本建立的應用程式取得這些資產。 如需詳細資訊,請參閱開始使用 ASP.NET Core MVC

如需在伺服器應用程式的頁面或檢視中使用任一用戶端應用程式元件的詳細資訊Razor,請參閱在託管Razor解決方案中將 ASP.NET 核心Razor元件與 MVC 或Blazor WebAssembly頁面整合

執行應用程式

執行 MultipleBlazorApps.Server 專案:

  • 在 存取初始 https://localhost:5001用戶端應用程式。
  • 在 存取新增 https://localhost:5002的用戶端應用程式。
  • 如果伺服器應用程式設定為提供頁面或檢視,請存取 Index 頁面 https://localhost:5000或檢視 。
  • 在 存取初始 https://localhost:{DEFAULT PORT}/FirstApp用戶端應用程式。
  • 在 存取新增 https://localhost:{DEFAULT PORT}/SecondApp的用戶端應用程式。
  • 如果伺服器應用程式設定為提供頁面或檢視,請存取 Index 頁面 https://localhost:{DEFAULT PORT}或檢視 。

在上述範例 URL 中,{DEFAULT PORT}預留位置是專案檔案MultipleBlazorApps.Server在其Properties/launchSettings.json值中定義applicationUrl的預設連接埠。

這很重要

使用 (或 dotnet watch) 命令 (.NET CLI) 執行dotnet run應用程式時,請確認命令殼層已在解決方案的資料夾中Server開啟。

使用 Visual Studio 的 [開始] 按鈕來執行應用程式時,請確認 MultipleBlazorApps.Server 專案已設定為啟動專案 (在 [方案總管] 中醒目提示)。

靜態資產

當資產位於用戶端應用程式的 wwwroot 資料夾中時,請在元件中提供靜態資產要求路徑:

<img alt="..." src="{PATH AND FILE NAME}" />

{PATH AND FILE NAME} 預留位置是 wwwroot 下的路徑和檔案名稱。

例如,Jeep 影像 (jeep-yj.pngvehicle 的來源位於 :wwwroot

<img alt="Jeep Wrangler YJ" src="vehicle/jeep-yj.png" />

Razor 類別程式庫 (RCL) 支援

類別程式庫 (RCL) 新增至Razor解決方案做為新專案:

  • 以滑鼠右鍵按一下 [方案總管 ] 中的解決方案,然後選取 [ 新增>專案]。
  • 使用 [類別庫]Razor 專案範本來建立專案。 本節中的範例使用專案名稱 ComponentLibrary,這也是 RCL 的組件名稱。 請勿選取 [ 支援頁面和檢視 ] 核取方塊。

針對每個裝載 Blazor WebAssembly 的用戶端應用程式,以滑鼠右鍵按一下 [方案總管 ] 中的每個用戶端專案,然後選取 [ 新增>專案參考],以建立 RCL 專案的專案參考。

在用戶端應用程式中使用 RCL 中的元件,並採用下列任一方法:

  • 將指引放在 @using RCL 命名空間的元件頂端,並新增 Razor 元件的語法。 下列範例適用於元件名稱 ComponentLibrary為 :

    @using ComponentLibrary
    
    ...
    
    <Component1 />
    
  • 提供 RCL 的命名空間以及 Razor 元件的語法。 此方法不需要 @using 元件檔案頂端的指示詞。 下列範例適用於元件名稱 ComponentLibrary為 :

    <ComponentLibrary.Component1 />
    

備註

@using指示詞也可以放入每個用戶端應用程式的_Import.razor檔案中,這可讓 RCL 的命名空間全域可供該專案中的元件使用。

當任何其他靜態資產位於 RCL 的資料夾中 wwwroot 時,請根據具有 ASP.NET Core 的類別程式庫中可 Razor 重複使用的 UI 中的指引,參考用戶端應用程式中的靜態資產:

<img alt="..." src="_content/{PACKAGE ID}/{PATH AND FILE NAME}" />

預留位置是 {PACKAGE ID} RCL 的 套件 ID。 如果未在專案檔中指定 <PackageId>,則封裝識別碼預設為專案的組件名稱。 {PATH AND FILE NAME} 預留位置是 wwwroot 下的路徑和檔案名稱。

下列範例顯示 RCL 資料夾jeep-yj.pngvehicle Jeep 影像 (wwwroot) 的標記。 下列範例適用於元件名稱 ComponentLibrary為 :

<img alt="Jeep Wrangler YJ" src="_content/ComponentLibrary/vehicle/jeep-yj.png" />

其他資源