托管和部署 ASP.NET Core Blazor
注意
此版本不是本文的最新版本。 有关当前版本,请参阅本文的 .NET 9 版本。
警告
此版本的 ASP.NET Core 不再受支持。 有关详细信息,请参阅 .NET 和 .NET Core 支持策略。 有关当前版本,请参阅本文的 .NET 9 版本。
本文介绍如何托管和部署 Blazor 应用。
发布应用
发布应用,用于发布配置中的部署。
注意
从 Server 项目发布托管的 Blazor WebAssembly 解决方案。
- 从“生成”菜单中选 发布 {APPLICATION} 命令,其中
{APPLICATION}
占位符为应用的名称。 - 选择“发布目标”。 若要在本地发布,请选择“文件夹”。
- 接受“选择文件夹”字段中的默认位置,或指定其他位置。 选择
Publish
按钮。
创建部署资产前,发布应用将触发项目依赖项的还原并生成生成该项目。 在生成过程期间,将删除未使用的方法和程序集,以减少应用下载大小并缩短加载时间。
发布位置:
- Blazor Web App:将应用发布到
/bin/Release/{TARGET FRAMEWORK}/publish
文件夹。 将publish
文件夹的内容部署到主机。 - Blazor WebAssembly:将应用发布到
bin\Release\net8.0\browser-wasm\publish\
文件夹。 若要将应用部署为静态站点,请将wwwroot
文件夹的内容复制到静态站点主机。
- Blazor Server:将应用发布到
/bin/Release/{TARGET FRAMEWORK}/publish
文件夹。 将publish
文件夹的内容部署到主机。 - Blazor WebAssembly
- 独立:应用将发布到
/bin/Release/{TARGET FRAMEWORK}/publish/wwwroot
或bin\Release\{TARGET FRAMEWORK}\browser-wasm\publish
文件夹中,具体取决于用于发布应用的 SDK 版本。 若要将应用部署为静态站点,请将wwwroot
文件夹的内容复制到静态站点主机。 - 托管:客户端 Blazor WebAssembly 应用与服务器应用的其他任何静态 Web 资产一起发布到服务器应用的
/bin/Release/{TARGET FRAMEWORK}/publish/wwwroot
文件夹。 将publish
文件夹的内容部署到主机。
- 独立:应用将发布到
上述路径中的 {TARGET FRAMEWORK}
是目标框架(例如 net8.0
)。
IIS
若要在 IIS 中托管 Blazor 应用,请参阅以下资源:
- IIS 托管
- 托管和部署 ASP.NET Core 服务器端 Blazor 应用:IIS 上运行的服务器应用,包括具有运行 Windows OS 和 Azure 应用服务的 Azure 虚拟机 (VM) 的 IIS。
- 主机和部署 ASP.NET Core Blazor WebAssembly:包括有关在 IIS 上托管 Blazor WebAssembly 应用的其他指南,包括静态站点托管、自定义
web.config
文件、URL 重写、子应用、压缩和 Azure 存储静态文件托管。 - IIS 子应用程序托管
- 在发布应用之前,请遵循 Blazor 应用的 应用基路径 部分中的指导。 这些示例使用应用基路径
/CoolApp
,展示了如何从应用设置或其他配置提供程序获取基路径。 - 按照高级配置中的子应用程序配置指南进行操作。 根站点下的子应用文件夹路径将成为子应用的虚拟路径。 对于
/CoolApp
的应用基路径,Blazor 应用放置在根站点下名为CoolApp
的文件夹中,子应用采用虚拟路径/CoolApp
。
- 在发布应用之前,请遵循 Blazor 应用的 应用基路径 部分中的指导。 这些示例使用应用基路径
不支持在 ASP.NET Core 应用之间共享应用池,包括 Blazor 应用。 当使用 IIS 进行托管时,为每个应用使用一个应用池,并避免使用 IIS 的虚拟目录来承载多个应用。
一个应用池支持一个或多个由 ASP.NET Core 应用托管的 Blazor WebAssembly 应用(称为托管的 Blazor WebAssembly 解决方案)。 但是,不建议也不支持将单个应用池分配到多个托管 Blazor WebAssembly 解决方案或子应用托管方案。
有关解决方案的详细信息,请参阅用于 ASP.NET Core Blazor 的工具。
应用基路径
应用基路径是应用的根 URL 路径。 Blazor 应用中的成功路由需要任何根 URL 路径的框架配置,这些路径不在默认应用基路径 /
。
请考虑使用下列 ASP.NET Core 应用和 Blazor 子应用:
- ASP.NET Core 应用名为
MyApp
:- 该应用实际驻留在
d:/MyApp
中。 - 在
https://www.contoso.com/{MYAPP RESOURCE}
收到请求。
- 该应用实际驻留在
- 名为
CoolApp
的 Blazor 应用是MyApp
的子应用:- 该子应用实际驻留在
d:/MyApp/CoolApp
中。 - 在
https://www.contoso.com/CoolApp/{COOLAPP RESOURCE}
收到请求。
- 该子应用实际驻留在
如果不为 CoolApp
指定其他配置,此方案中的子应用将不知道其在服务器上的位置。 例如,不知道它驻留在相对 URL 路径 /CoolApp/
上,应用就无法构造其资源的正确相对 URL。 这种情况也适用于当应用未托管在根 URL 路径上时的各种托管和反向代理场景。
背景
定位标记的目标(href
)可以由两个终结点之一组成:
包含方案的绝对位置(如果省略,默认为页面的方案)、主机、端口和路径,或只包含正斜杠(
/
),后跟路径。示例:
https://example.com/a/b/c
或/a/b/c
仅包含路径且不以正斜杠开头的相对位置(
/
)。 这些解析相对于当前文档 URL 或<base>
标记的值(如果指定)。示例:
a/b/c
配置的应用基路径中存在尾随斜杠(/
)对于计算应用的 URL 基路径非常重要。 例如,https://example.com/a
有一个基路径 https://example.com/
,而带有尾部斜杠的 https://example.com/a/
有一个基路径 https://example.com/a
。
有三个与 ASP.NET Core 应用中 Blazor 相关的链接来源:
- Razor 组件中的 URL (
.razor
) 通常是相对 URL。 - 脚本中的 URL(例如,对于 Blazor 脚本,为
blazor.*.js
)相对于文档。
- 在
_Host.cshtml
文件中手动编写的 URL(Blazor Server),如果在不同的文档中进行呈现,则这些 URL 应始终是绝对的。 - Razor 组件中的 URL (
.razor
) 通常是相对 URL。 - 脚本中的 URL(例如,对于 Blazor 脚本,为
blazor.*.js
)相对于文档。
如果要从不同的文档(例如,/Admin/B/C/
和 /Admin/D/E/
)呈现 Blazor 应用,则必须将应用基路径考虑在内,或者当应用在每个文档中呈现并且从错误 URL 中提取资源时,基本路径不同。
有两种方法可以解决正确解决相对链接的挑战:
- 使用它们呈现在根上的文档动态映射资源。
- 为文档设置一致的基路径,并映射该基路径下的资源。
第一个选项更为复杂,并不是最典型的方法,因为它使每个文档的导航变得不同。 请考虑以下示例来呈现页面 /Something/Else
:
- 呈现在
/Admin/B/C/
下,页面以/Admin/B/C/Something/Else
的路径呈现。 - 在
/Admin/D/E/
下呈现页面,页面以/Admin/B/C/Something/Else
的同一路径 呈现。
在第一种方法下,路由提供 IDynamicEndpointMetadata 和 MatcherPolicy,这可以组合在一起来实现完全动态的解决方案,该解决方案在运行时确定请求的路由方式。
对于第二个选项(即通常采用的方法),应用在文档中设置基本路径,并将服务器终结点映射到基础下的路径。 以下指南采用此方法。
服务器端 Blazor
通过将路径传递至 Program
文件中的 MapBlazorHub 来映射服务器端 Blazor 应用的 SignalR 中心:
app.MapBlazorHub("base/path");
使用 MapBlazorHub 的好处是可以映射模式,例如 "{tenant}"
,而不仅仅是具体路径。
当应用位于具有分支中间件管道的虚拟文件夹中时,你还可以映射 SignalR 中心。 在以下示例中,对 /base/path/
的请求由 Blazor 的 SignalR 中心处理:
app.Map("/base/path/", subapp => {
subapp.UsePathBase("/base/path/");
subapp.UseRouting();
subapp.UseEndpoints(endpoints => endpoints.MapBlazorHub());
});
根据 配置应用基路径 部分中的指导配置 <base>
标记。
托管 Blazor WebAssembly
如果应用是托管 Blazor WebAssembly 应用:
- 在 Server 项目中(
Program.cs
):- 调整 UseBlazorFrameworkFiles 的路径(例如,
app.UseBlazorFrameworkFiles("/base/path");
)。 - 配置对 UseStaticFiles 的调用(例如,
app.UseStaticFiles("/base/path");
)。
- 调整 UseBlazorFrameworkFiles 的路径(例如,
- 在 Client 项目中:
- 在项目文件中配置
<StaticWebAssetBasePath>
,以匹配提供静态 Web 资产的路径(例如,<StaticWebAssetBasePath>base/path</StaticWebAssetBasePath>
)。 - 根据 配置应用基路径 部分中的指导配置
<base>
标记。
- 在项目文件中配置
有关在托管 Blazor WebAssembly 解决方案中托管多个 Blazor WebAssembly 应用的示例,请参阅多个托管 ASP.NET Core Blazor WebAssembly应用,其中介绍了多个 Blazor WebAssembly 客户端应用的域/端口托管和子路径托管的方法。
独立 Blazor WebAssembly
在独立 Blazor WebAssembly 应用中,根据配置应用基路径部分中的指导,只配置 <base>
标记。
配置应用基路径
若要为 Blazor 应用的基路径 https://www.contoso.com/CoolApp/
提供配置,请设置 应用基路径 (<base>
),该路径也称为相对根路径。
通过配置应用基路径,根目录中的组件可以构造相对于应用的根路径的 URL。 位于目录结构不同级别的组件可生成指向整个应用其他位置的资源链接。 应用基路径也用于拦截所选超链接,其中链接的 href
目标位于应用基路径 URI 空间中。 Router 组件将处理内部导航。
将<base>
标记放置在标记<head>
(内容的位置<head>
)之前,任何具有 URL 属性值的元素(例如href
元素的属性<link>
)。
在许多托管方案中,应用的相对 URL 路径为应用的根目录。 在这些默认情况下,应用的相对 URL 基路径为 /
,它在 <head>
内容中配置为 <base href="/" />
。
在许多托管方案中,应用的相对 URL 路径为应用的根目录。 在这些默认情况下,应用的相对 URL 基路径在 <head>
内容中如下所示:
- Blazor Server:
~/
配置为<base href="~/" />
。 - Blazor WebAssembly:
/
配置为<base href="/" />
。
注意
在一些托管方案中(例如 GitHub 页和 IIS 子应用),应用基路径必须设置为应用的服务器相对 URL 路径。
在服务器端 Blazor 应用中,使用以下任一方法:
选项 1:使用
<base>
标记设置应用的基本路径(<head>
内容 位置):<base href="/CoolApp/">
尾部反斜杠是必需项。
选项 2:在生成 WebApplicationBuilder (
builder.Build()
) 后立即在应用的请求处理管道 (Program.cs
) 中首先调用 UsePathBase,为与请求路径交互的任何以下中间件配置基路径:app.UsePathBase("/CoolApp");
如果还想在本地运行 Blazor Server 应用,建议调用 UsePathBase。 例如,在
Properties/launchSettings.json
中提供启动 URL:"launchUrl": "https://localhost:{PORT}/CoolApp",
上面示例中的占位符
{PORT}
是与applicationUrl
配置路径中的安全端口相匹配的端口。 以下示例显示了端口 7279 上应用的完整启动配置文件:"BlazorSample": { "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, "applicationUrl": "https://localhost:7279;http://localhost:5279", "launchUrl": "https://localhost:7279/CoolApp", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" }
有关
launchSettings.json
文件的详细信息,请参阅在 ASP.NET Core 中使用多个环境。 有关 Blazor 应用基路径和托管的其他信息,请参阅<base href="/" />
或 BlazorMVC 集成 (dotnet/aspnetcore #43191) 基标记替代项。
独立 Blazor WebAssembly (
wwwroot/index.html
):<base href="/CoolApp/">
尾部反斜杠是必需项。
托管 Blazor WebAssembly (Client 项目,
wwwroot/index.html
):<base href="/CoolApp/">
尾部反斜杠是必需项。
在 Server 项目中,在生成 WebApplicationBuilder (
builder.Build()
) 后,立即在应用的请求处理管道 (Program.cs
) 中首先调用 UsePathBase,以便为与请求路径交互的任何以下中间件配置基路径:app.UsePathBase("/CoolApp");
注意
使用 WebApplication(请参阅从 ASP.NET Core 5.0 迁移到 6.0)时,必须在 UsePathBase 之后调用 app.UseRouting
,以便路由中间件可以在匹配路由之前观察已修改的路径。 否则,在 UsePathBase 重写路径之前匹配路由,如中间件排序和路由文章中所述。
不要在整个应用中使用正斜杠作为链接的前缀。 请避免使用路径段分隔符或使用点-斜杠 (./
) 相对路径表示法:
<a href="/account">
不正确:<a href="account">
正确:<a href="./account">
正确:
在使用 HttpClient
服务的 Blazor WebAssembly Web API 请求中,确认 JSON 帮助程序 (HttpClientJsonExtensions) 不会在 URL 前面使用正斜杠 (/
):
var rsp = await client.GetFromJsonAsync("/api/Account");
不正确:var rsp = await client.GetFromJsonAsync("api/Account");
正确:
不要在导航管理器相对链接前加上正斜杠。 避免使用路径段分隔符或使用点斜杠(./
)相对路径表示法(Navigation
是注入 NavigationManager):
Navigation.NavigateTo("/other");
不正确:Navigation.NavigateTo("other");
正确:Navigation.NavigateTo("./other");
正确:
在 Azure/IIS 托管的典型配置中,通常不需要额外的配置。 在某些非 IIS 托管和反向代理托管方案中,可能需要其他静态文件中间件配置:
- 正确提供静态文件(例如,
app.UseStaticFiles("/CoolApp");
)。 - 提供 Blazor 脚本 (
_framework/blazor.*.js
)。 有关详细信息,请参阅 ASP.NET Core Blazor 静态文件。
对于具有非根相对 URL 路径(例如 <base href="/CoolApp/">
)的 Blazor WebAssembly 应用,应用在本地运行时找不到其资源。 要在本地开发和测试过程中解决此问题,可提供 path base 参数,用于匹配运行时 <base>
标记的 href
值。 不要包含尾部反斜杠。 在本地运行应用时,若要传递路径基础参数,请使用 --pathbase
选项从应用的目录执行 dotnet watch
(或 dotnet run
)命令:
dotnet watch --pathbase=/{RELATIVE URL PATH (no trailing slash)}
对于具有相对 URL 路径 /CoolApp/
(<base href="/CoolApp/">
) 的 Blazor WebAssembly 应用,命令如下:
dotnet watch --pathbase=/CoolApp
如果要将应用的启动配置文件配置为自动指定 pathbase
而不是使用 dotnet watch
(或 dotnet run
)手动指定,请在 Properties/launchSettings.json
中设置 commandLineArgs
属性。 以下还配置启动 URL (launchUrl
):
"commandLineArgs": "--pathbase=/{RELATIVE URL PATH (no trailing slash)}",
"launchUrl": "{RELATIVE URL PATH (no trailing slash)}",
以 CoolApp
为例:
"commandLineArgs": "--pathbase=/CoolApp",
"launchUrl": "CoolApp",
Blazor WebAssembly 应用将 dotnet watch
(或 dotnet run
)与 --pathbase
选项或设置了基本路径的启动配置文件配置一起使用,在 http://localhost:port/CoolApp
本地进行响应。
有关 launchSettings.json
文件的详细信息,请参阅在 ASP.NET Core 中使用多个环境。 有关 Blazor 应用基路径和托管的其他信息,请参阅 <base href="/" />
或 BlazorMVC 集成 (dotnet/aspnetcore #43191) 基标记替代项。
从配置中获取应用基路径
以下指南介绍如何从不同环境的应用设置文件中获取 <base>
标记的路径。
将应用设置文件添加到应用。 以下示例适用于 Staging
环境 (appsettings.Staging.json
):
{
"AppBasePath": "staging/"
}
在服务器端 Blazor 应用中,从 <head>
内容中的配置加载基路径:
@inject IConfiguration Config
...
<head>
...
<base href="/@(Config.GetValue<string>("AppBasePath"))" />
...
</head>
也可通过服务器端应用从 UsePathBase 的配置中获取值。 在生成 WebApplicationBuilder (builder.Build()
) 后,立即将以下代码首先放入应用的请求处理管道 (Program.cs
) 中。 以下示例使用配置键 AppBasePath
:
app.UsePathBase($"/{app.Configuration.GetValue<string>("AppBasePath")}");
在客户端 Blazor WebAssembly 应用中:
从
wwwroot/index.html
中删除<base>
标记:- <base href="..." />
通过
App
组件 (App.razor
) 中的HeadContent
组件提供应用基路径:@inject IConfiguration Config ... <HeadContent> <base href="/@(Config.GetValue<string>("AppBasePath"))" /> </HeadContent>
如果没有要加载的配置值(例如在非暂存环境中就是如此),则前面的 href
将解析为根路径 /
。
本部分的示例重点介绍如何从应用设置提供应用基路径,但从 IConfiguration 读取路径的方法对于任何配置提供程序都有效。 有关更多信息,请参见以下资源:
Blazor ServerMapFallbackToPage
配置
本部分仅适用于 Blazor Server应用。 Blazor Web App 和 Blazor WebAssembly 应用不支持 MapFallbackToPage。
在应用需要具有包含自定义资源和 Razor 组件的单独区域的场景中:
在应用的
Pages
文件夹中创建一个文件夹来保存资源。 例如,在名为Admin
的新文件夹中创建应用的管理员部分 (Pages/Admin
)。为该区域创建一个根页面 (
_Host.cshtml
)。 例如,从应用的主要根页面 (Pages/_Host.cshtml
) 创建Pages/Admin/_Host.cshtml
文件。 不要在 Admin@page
页面中提供_Host
指令。向该区域的文件夹添加布局(例如
Pages/Admin/_Layout.razor
)。 在该单独区域的布局中,请设置<base>
标记href
来匹配该区域的文件夹(例如<base href="/Admin/" />
)。 出于演示目的,请将~/
添加到页面中的静态资源。 例如:~/css/bootstrap/bootstrap.min.css
~/css/site.css
~/BlazorSample.styles.css
(示例应用的命名空间为BlazorSample
)~/_framework/blazor.server.js
(Blazor 脚本)
如果想让该区域具有自己的静态资产文件夹,请在
Program.cs
中添加文件夹并将它的位置指定为静态文件中间件(例如app.UseStaticFiles("/Admin/wwwroot")
)。将 Razor 组件添加到该区域的文件夹。 至少,针对该区域使用正确的
@page
指令将Index
组件添加到区域文件夹。 例如,根据应用的默认Pages/Index.razor
文件添加Pages/Admin/Index.razor
文件。 在文件顶部将 Admin 区域指示为路由模板 (@page "/admin"
)。 根据需要添加其他组件。 例如,使用@page
指令添加Pages/Admin/Component1.razor
并指示为路由模板@page "/admin/component1
。在
Program.cs
中,在紧挨到_Host
页面的回退根页面路径之前为该区域的请求路径调用 MapFallbackToPage:... app.UseRouting(); app.MapBlazorHub(); app.MapFallbackToPage("~/Admin/{*clientroutes:nonfile}", "/Admin/_Host"); app.MapFallbackToPage("/_Host"); app.Run();
托管多个 Blazor WebAssembly 应用
有关在托管的 Blazor 解决方案中托管多个 Blazor WebAssembly 应用的详细信息,请参阅多个托管的 ASP.NET Core Blazor WebAssembly 应用。
部署
有关部署指南,请参阅以下主题: