Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
Замечание
Это не последняя версия этой статьи. Последняя версия этой статьи см. в версии .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 .
Предыдущие конфигурации выходят за рамки этой статьи. Дополнительные сведения см. в следующих ресурсах:
- Размещение и развертывание ASP.NET Core
- Принудительное применение HTTPS в ASP.NET Core
- Интеграция компонентов ASP.NET Core Razor с MVC или Razor Pages в размещенных Blazor WebAssembly решениях
Используйте существующее размещенное Blazor WebAssemblyрешение или создайте Blazor WebAssembly размещенное решение из Blazor WebAssembly шаблона проекта, передав -ho|--hosted параметр при использовании .NET CLI или установите флажок 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 . Имена "" и "FirstAppSecondApp" просто предназначены для демонстрационных целей. Другие имена допустимы для отличия клиентских приложений, таких как App1/App2, Client1/Client21/2или любая аналогичная схема именования.
При маршрутизации запросов к клиентским приложениям через порт или домен, "" и "FirstAppSecondApp" используются внутренне для маршрутизации запросов и обслуживания ответов для статических ресурсов и не отображаются в адресной строке браузера.
Замечание
В демонстрации в этой статье используются имена путей статических FirstApp веб-ресурсов для MultipleBlazorApps.Client проекта и SecondApp проекта MultipleBlazorApps.SecondClient . Имена "" и "FirstAppSecondApp" просто предназначены для демонстрационных целей. Другие имена допустимы для отличия клиентских приложений, таких как App1/App2, Client1/Client21/2или любая аналогичная схема именования.
"" и "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.comsecondapp.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.htmlSecondClient/wwwroot/index.htmlобновите<base>значение тега, чтобы отразить подпатку. Косая черта требуется:<base href="/SecondApp/" />
Дополнительные сведения см. в UseStaticFilesразделе ASP.NET Статические файлы CoreBlazor.
Дополнительные сведения и UseBlazorFrameworkFilesMapFallbackToFileсведения см. в следующих ресурсах:
- Microsoft.AspNetCore.Builder.ComponentsWebAssemblyApplicationBuilderExtensions.UseBlazorFrameworkFiles (справочный источник)
- Microsoft.AspNetCore.Builder.StaticFilesEndpointRouteBuilderExtensions.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]")]
Если вы планируете обслуживать страницы из серверного приложения, добавьте 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() => View();
}
Замечание
Предыдущее Index представление является минимальным примером исключительно для демонстрационных целей. Если приложению требуются дополнительные ресурсы MVC, такие как макет, стили, скрипты и импорт, получите их из приложения, созданного из шаблона проекта MVC. Дополнительные сведения см. в статье "Начало работы с ASP.NET Core MVC".
Дополнительные сведения об использовании Razor компонентов из клиентских приложений на страницах или представлениях серверного приложения см. в статье "Интеграция ASP.NET основных 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) в папке vehiclewwwroot:
<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" />