Несколько размещенных приложений Blazor WebAssembly ASP.NET Core

Примечание.

Это не последняя версия этой статьи. Последняя версия этой статьи см. в версии .NET 7.

В этой статье описано, как настроить размещенное приложение Blazor WebAssembly для размещения нескольких приложений Blazor WebAssembly.

Настройка

Выберите версию этой статьи, которая соответствует вашим требованиям размещения, размещение портов или домена (например, :5001/:5002 илиfirstapp.comsecondapp.com/) или размещение подпаток маршрута (например, /FirstApp и )./SecondApp

При выборе текущего размещения в этой статье рассматривается размещение портов или доменов (например, :5001/:5002 или).firstapp.com/secondapp.com

В примерах ниже сделайте следующее:

  • Для размещенного приложения Blazor WebAssembly используется имя MultipleBlazorApps, и оно находится в папке с именем MultipleBlazorApps.
  • До добавления второго клиентского приложения здесь были размещены три проекта: MultipleBlazorApps.Client в папке Client, MultipleBlazorApps.Server в папке Server и MultipleBlazorApps.Shared в папке Shared.
  • Исходное (первое) клиентское приложение представляет собой стандартный клиентский проект решения на основе шаблона проекта Blazor WebAssembly.
  • Мы добавляем в это решение второе клиентское приложение MultipleBlazorApps.SecondClient, разместив его в папке SecondClient.
  • При необходимости серверный проект (MultipleBlazorApps.Server) может служить страницами или представлениями в Razor качестве приложения Pages или MVC.
  • Первое клиентское приложение открывается в окне на порте 5001 или на узле firstapp.com. Второе клиентское приложение открывается в окне на порте 5002 или на узле secondapp.com.

В текущей статье рассматривается размещение подпаток маршрута (например, /FirstApp и /SecondApp).

В примерах ниже сделайте следующее:

  • Для размещенного приложения Blazor WebAssembly используется имя MultipleBlazorApps, и оно находится в папке с именем MultipleBlazorApps.
  • До добавления второго клиентского приложения здесь были размещены три проекта: MultipleBlazorApps.Client в папке Client, MultipleBlazorApps.Server в папке Server и MultipleBlazorApps.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 шаблона проекта, передав -ho|--hosted параметр, если используется интерфейс командной строки .NET или выберите папку ASP.NET Core Hosted проверка box в Visual Studio при создании проекта в интегрированной среде разработки.

Укажите для решения папку с именем MultipleBlazorApps и присвойте проекту имя MultipleBlazorApps.

Создайте новую папку в решении с именем SecondClient. В новой папке добавьте второе Blazor WebAssembly клиентское приложение с именем MultipleBlazorApps.SecondClient. Добавьте проект в формате автономного приложения Blazor WebAssembly. Чтобы создать автономное Blazor WebAssembly приложение, не передайте -ho|--hosted этот параметр, если используется .NET CLI или не используйте ASP.NET Core Hosted проверка box при использовании Visual Studio.

Внесите следующие изменения в MultipleBlazorApps.SecondClient проект:

  • FetchData Скопируйте компонент (Pages/FetchData.razor) из Client/Pages папки в папкуSecondClient/Pages. Этот шаг необходим, так как автономное Blazor WebAssembly приложение не вызывает Server контроллер проекта для погодных данных, он использует статический файл данных. Копируя компонент в FetchData добавленный проект, второе клиентское приложение также вызывает веб-API к API сервера для данных о погоде.
  • Удалите папку SecondClient/wwwroot/sample-data , так как weather.json файл в папке не используется.

В следующей таблице описываются папки решения и имена проектов после SecondClient добавления папки и MultipleBlazorApps.SecondClient проекта.

Физическая папка Имя проекта Description
Client MultipleBlazorApps.Client Blazor WebAssembly клиентское приложение
SecondClient MultipleBlazorApps.SecondClient Blazor WebAssembly клиентское приложение
Server MultipleBlazorApps.Server приложение сервера ASP.NET Core
Shared MultipleBlazorApps.Shared Проект общих ресурсов

Проект MultipleBlazorApps.Server служит двум Blazor WebAssembly клиентским приложениям и предоставляет данные о погоде компонентам клиентских приложений FetchData через контроллер MVC. MultipleBlazorApps.Server При необходимости проект также может обслуживать страницы или представления в качестве традиционного Razor приложения Pages или MVC. Действия по включению страниц обслуживания или представлений рассматриваются далее в этой статье.

Примечание.

В демонстрации в этой статье используются имена путей статических FirstApp веб-ресурсов для MultipleBlazorApps.Client проекта и SecondApp проекта MultipleBlazorApps.SecondClient . Имена "" и "FirstAppSecondApp" просто предназначены для демонстрационных целей. Другие имена допустимы для отличия клиентских приложений, таких как App1App2/, 1/Client1/Client22или любая аналогичная схема именования.

При маршрутизации запросов к клиентским приложениям через порт или домен, "" и "FirstAppSecondApp" используются внутренне для маршрутизации запросов и обслуживания ответов для статических ресурсов и не отображаются в адресной строке браузера.

Примечание.

В демонстрации в этой статье используются имена путей статических FirstApp веб-ресурсов для MultipleBlazorApps.Client проекта и SecondApp проекта MultipleBlazorApps.SecondClient . Имена "" и "FirstAppSecondApp" просто предназначены для демонстрационных целей. Другие имена допустимы для отличия клиентских приложений, таких как App1App2/, 1/Client1/Client22или любая аналогичная схема именования.

"" и "FirstAppSecondApp" также отображаются в адресной строке браузера, так как запросы направляются в два клиентских приложения с помощью этих имен. Поддерживаются другие допустимые сегменты маршрутов URL-адресов, а сегменты маршрутов не должны соответствовать именам, используемым для маршрутизации статических веб-ресурсов внутри. Использование "" и "FirstAppSecondApp" как для маршрутизации внутренних статических ресурсов, так и для маршрутизации запросов приложений в примерах этой статьи.

В файле проекта первого клиентского приложения добавьтеMultipleBlazorApps.Client.csproj<StaticWebAssetBasePath> свойство<PropertyGroup> в значениеFirstApp, указывающее базовый путь для статических ресурсов проекта:

<StaticWebAssetBasePath>FirstApp</StaticWebAssetBasePath>

В файле проекта (MultipleBlazorApps.SecondClient) приложения MultipleBlazorApps.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 сервера настройте applicationUrlKestrel профиль (MultipleBlazorApps.Server) для доступа к клиентским приложениям через порты 5001 и 5002. Если вы настроите локальную среду для использования примеров доменов, URL-адреса для applicationUrl использования firstapp.com и secondapp.com не используют порты.

Примечание.

Использование портов в этом демонстрационном примере позволяет обращаться к клиентским проектам в локальном браузере, не настраивая для них специальную среду размещения в локальной среде. Веб-браузеры получают доступ к клиентским приложениям через конфигурации узлов 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.Host и RequireHost, подвержены потенциальному спуфинду клиентов.

    Чтобы предотвратить спуфинирование узлов и портов, используйте один из следующих подходов:

  • Добавьте ПО промежуточного слоя, которое сопоставляет запросы с клиентскими приложениями. Следующий пример настраивает по промежуточному слоя для запуска, если подпатка запроса является /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.htmlSecondClient/wwwroot/index.htmlобновите <base> значение тега, чтобы отразить подпатку. Косая черта требуется:

    <base href="/SecondApp/" />
    

Дополнительные сведения о UseStaticFiles см. в статье Статические файлы ASP.NET Core Blazor.

Дополнительные сведения о UseBlazorFrameworkFiles и MapFallbackToFile см. в следующих документах:

Примечание.

По ссылкам в документации на справочные материалы по .NET обычно загружается ветвь репозитория по умолчанию, которая представляет текущую разработку для следующего выпуска .NET. Чтобы выбрать тег для определенного выпуска, используйте раскрывающийся список Switch branches or tags (Переключение ветвей или тегов). Дополнительные сведения см. в статье Выбор тега версии исходного кода 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]")]

Если вы планируете обслуживать страницы в серверном приложении, добавьте страницу IndexRazor в папку Pages для серверного приложения:

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, например макет, стили, скрипты и инструкции импорта, получите их из приложения, созданного на основе шаблона для проекта Razor Pages. Дополнительные сведения см. в статье Введение в Razor Pages в ASP.NET Core.

Если вы планируете обслуживать представления 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()
    {
        return View();
    }
}
using Microsoft.AspNetCore.Mvc;

namespace MultipleBlazorApps.Server.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    }
}

Примечание.

Предыдущее Index представление является минимальным примером исключительно для демонстрационных целей. Если приложению требуются дополнительные ресурсы MVC, например макет, стили, скрипты и инструкции импорта, получите их из приложения, созданного на основе шаблона для проекта MVC. Дополнительные сведения см. в статье Начало работы с ASP.NET Core MVC.

Дополнительные сведения об использовании компонентов Razor любого из клиентских приложений на страницах или в представлениях серверного приложения см. в статье Компоненты Razor для предварительной визуализации и интеграции ASP.NET Core.

Выполнить приложение

Запустите проект 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 run помощью команды (.NET CLI) убедитесь, что командная оболочка открыта в Server папке решения.

При использовании кнопки запуска Visual Studio для запуска приложения убедитесь, что MultipleBlazorApps.Server проект задан в качестве запускаемого проекта (выделен в Обозреватель решений).

Статические ресурсы.

Если ресурс находится в папке wwwroot клиентского приложения, укажите путь запроса статического ресурса в компонентах:

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

Заполнитель {PATH AND FILE NAME} — это путь и имя файла в папке wwwroot.

Например, так выглядит источник для изображения автомобиля Jeep (jeep-yj.png) в папке vehicle для wwwroot:

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

Поддержка библиотеки классов Razor (RCL)

Добавьте библиотеку классов Razor (RCL) в решение, оформив ее как новый проект:

  • Щелкните решение в обозревателе решений правой кнопкой мыши и выберите Добавить>Новый проект.
  • Используйте шаблон проекта библиотеки классов Razor, чтобы создать этот проект. В примерах для этого раздела используется имя проекта ComponentLibrary, которое совпадает с именем сборки RCL. Не устанавливайте флажок представления.

Для каждого размещенного клиентского приложения Blazor WebAssembly создайте ссылку на проект RCL, щелкнув правой кнопкой мыши каждый клиентский проект в обозревателе решений и выбрав элементы Добавить, Ссылка на проект.

Чтобы использовать компоненты из RCL в клиентских приложениях, выберите любой из следующих подходов.

  • Разместите директиву @using в верхней части компонента для пространства имен RCL и добавьте синтаксис Razor для компонента. Следующий пример предназначен для RCL с именем сборки ComponentLibrary:

    @using ComponentLibrary
    
    ...
    
    <Component1 />
    
  • Укажите пространство имен RCL вместе с синтаксисом Razor для компонента. Этот подход не требует включать директиву @using в верхней части файла компонента. Следующий пример предназначен для RCL с именем сборки ComponentLibrary:

    <ComponentLibrary.Component1 />
    

Примечание.

Директиву @using также можно поместить в файл _Import.razor для каждого клиентского приложения, и тогда пространство имен RCL будет глобально доступным для всех компонентов в этом проекте.

Если в папке wwwroot для RCL есть любой другой статический ресурс, укажите ссылку на этот статический ресурс в клиентском приложении, следуя инструкциям в разделе Создание многоразового пользовательского интерфейса с помощью проекта библиотеки классов Razor в ASP.NET Core:

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

Заполнитель {PACKAGE ID} обозначает идентификатор пакета RCL. Идентификатор пакета по умолчанию имеет имя сборки проекта, если значение <PackageId> не указано в файле проекта. Заполнитель {PATH AND FILE NAME} — это путь и имя файла в разделе wwwroot.

В следующем примере показана разметка для образа Jeep (jeep-yj.png) в vehicle папке папки RCL wwwroot . Следующий пример предназначен для RCL с именем сборки ComponentLibrary:

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

Дополнительные ресурсы