Несколько размещенных приложений Blazor WebAssembly ASP.NET Core
Примечание.
Это не последняя версия этой статьи. Последняя версия этой статьи см. в версии .NET 7.
В этой статье описано, как настроить размещенное приложение Blazor WebAssembly для размещения нескольких приложений Blazor WebAssembly.
Настройка
Выберите версию этой статьи, которая соответствует вашим требованиям размещения, размещение портов или домена (например, :5001
/:5002
илиfirstapp.com
secondapp.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.
Предыдущие конфигурации выходят за рамки этой статьи. Дополнительные сведения см. на следующих ресурсах:
- Статьи о размещении и развертывании
- Принудительное применение HTTPS в ASP.NET Core
- Интеграция компонентов ASP.NET Core Razor с MVC или Razor Pages в размещенных Blazor WebAssembly решениях
Используйте существующее размещенное Blazor WebAssemblyBlazor WebAssembly решение или создайте размещенное решение из Blazor WebAssembly шаблона проекта, передав -ho|--hosted
параметр, если используется интерфейс командной строки .NET или установите флажок ASP.NET Core Hosted в Visual Studio при создании проекта в интегрированной среде разработки.
Укажите для решения папку с именем MultipleBlazorApps
и присвойте проекту имя MultipleBlazorApps
.
Создайте новую папку в решении с именем SecondClient
. В новой папке добавьте второе Blazor WebAssembly клиентское приложение с именем MultipleBlazorApps.SecondClient
. Добавьте проект в формате автономного приложения Blazor WebAssembly. Чтобы создать автономное Blazor WebAssembly приложение, не передайте -ho|--hosted
этот параметр, если используется .NET CLI или не используйте флажок ASP.NET Core Hosted при использовании 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
. Имена "" и "FirstApp
SecondApp
" просто предназначены для демонстрационных целей. Другие имена допустимы для отличия клиентских приложений, таких как App1
App2
/, 1
/Client1
/Client2
2
или любая аналогичная схема именования.
При маршрутизации запросов к клиентским приложениям через порт или домен, "" и "FirstApp
SecondApp
" используются внутренне для маршрутизации запросов и обслуживания ответов для статических ресурсов и не отображаются в адресной строке браузера.
Примечание.
В демонстрации в этой статье используются имена путей статических FirstApp
веб-ресурсов для MultipleBlazorApps.Client
проекта и SecondApp
проекта MultipleBlazorApps.SecondClient
. Имена "" и "FirstApp
SecondApp
" просто предназначены для демонстрационных целей. Другие имена допустимы для отличия клиентских приложений, таких как App1
App2
/, 1
/Client1
/Client2
2
или любая аналогичная схема именования.
"" и "FirstApp
SecondApp
" также отображаются в адресной строке браузера, так как запросы направляются в два клиентских приложения с помощью этих имен. Поддерживаются другие допустимые сегменты маршрутов URL-адресов, а сегменты маршрутов не должны соответствовать именам, используемым для маршрутизации статических веб-ресурсов внутри. Использование "" и "FirstApp
SecondApp
" как для маршрутизации внутренних статических ресурсов, так и для маршрутизации запросов приложений в примерах этой статьи.
В файле проекта первого клиентского приложения добавьте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
сервера настройте applicationUrl
Kestrel профиль (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, подвержены потенциальному спуфинду клиентов.
Чтобы предотвратить спуфинирование узлов и портов, используйте один из следующих подходов:
- Используйте HttpContext.Connection (ConnectionInfo.LocalPort) место проверки портов.
- Использование фильтрации узлов.
Добавьте ПО промежуточного слоя, которое сопоставляет запросы с клиентскими приложениями. Следующий пример настраивает по промежуточному слоя для запуска, если подпатка запроса является
/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
см. в следующих документах:
- Microsoft.AspNetCore.Builder.ComponentsWebAssemblyApplicationBuilderExtensions.UseBlazorFrameworkFiles (справочный ресурс)
- Microsoft.AspNetCore.Builder.StaticFilesEndpointRouteBuilderExtensions.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]")]
Если вы планируете обслуживать страницы в серверном приложении, добавьте страницу Index
Razor в папку 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() => View();
}
Примечание.
Предыдущее Index
представление является минимальным примером исключительно для демонстрационных целей. Если приложению требуются дополнительные ресурсы MVC, например макет, стили, скрипты и инструкции импорта, получите их из приложения, созданного на основе шаблона для проекта MVC. Дополнительные сведения см. в статье Начало работы с ASP.NET Core MVC.
Дополнительные сведения об использовании Razor компонентов из клиентских приложений на страницах или представлениях серверного приложения см. в разделе "Интеграция компонентов ASP.NET Core Razor " с MVC или Razor Pages в размещенных 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
помощью команды (или 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" />
Дополнительные ресурсы
ASP.NET Core