aspnetcore/blazor/host-and-deploy/app-base-path.md
This article explains the app base path in ASP.NET Core Blazor apps, including configuration guidance.
The app base path is the app's root URL path. Successful routing in Blazor apps requires framework configuration for any root URL path that isn't at the default app base path /.
Consider the following ASP.NET Core app and Blazor sub-app:
MyApp:
d:/MyApp.https://www.contoso.com/{MYAPP RESOURCE}.CoolApp is a sub-app of MyApp:
d:/MyApp/CoolApp.https://www.contoso.com/CoolApp/{COOLAPP RESOURCE}.Without specifying additional configuration for CoolApp, the sub-app in this scenario has no knowledge of where it resides on the server. For example, the app can't construct correct relative URLs to its resources without knowing that it resides at the relative URL path /CoolApp/. This scenario also applies in various hosting and reverse proxy scenarios when an app isn't hosted at a root URL path.
An anchor tag's destination (href) can be composed with either of two endpoints:
Absolute locations that include a scheme (defaults to the page's scheme if omitted), host, port, and path or just a forward slash (/) followed by the path.
Examples: https://example.com/a/b/c or /a/b/c
Relative locations that contain just a path and do not start with a forward slash (/). These are resolved relative to the current document URL or the <base> tag's value, if specified.
Example: a/b/c
The presence of a trailing slash (/) in a configured app base path is significant to compute the base path for URLs of the app. For example, https://example.com/a has a base path of https://example.com/, while https://example.com/a/ with a trailing slash has a base path of https://example.com/a.
For the sources of links that pertain to Blazor in ASP.NET Core apps:
:::moniker range=">= aspnetcore-8.0"
.razor) are typically relative.blazor.*.js), are relative to the document.:::moniker-end
:::moniker range="< aspnetcore-8.0"
_Host.cshtml file (Blazor Server), which if you are rendering inside different documents should always be absolute..razor) are typically relative.blazor.*.js), are relative to the document.:::moniker-end
If you're rendering a Blazor app from different documents (for example, /Admin/B/C/ and /Admin/D/E/), you must take the app base path into account, or the base path is different when the app renders in each document and the resources are fetched from the wrong URLs.
Choose one of the following strategies to keep relative links resolving correctly:
:::moniker range=">= aspnetcore-11.0"
BasePath component to render <base href> automatically, while standalone WebAssembly apps (or scenarios that always use a fixed value) configure the literal <base> tag in the host page.:::moniker-end
:::moniker range="< aspnetcore-11.0"
<base> tag in the host page for both server-side Blazor apps and Blazor WebAssembly apps (or scenarios that always use a fixed value).:::moniker-end
The remainder of this article focuses on implementing a consistent base path.
Map the SignalR hub of a server-side Blazor app by passing the path to xref:Microsoft.AspNetCore.Builder.ComponentEndpointRouteBuilderExtensions.MapBlazorHub%2A in the Program file. The default Blazor hub path is /_blazor, and the following example sets the base path of the default hub to base/path:
app.MapBlazorHub("base/path/_blazor");
The benefit of using xref:Microsoft.AspNetCore.Builder.ComponentEndpointRouteBuilderExtensions.MapBlazorHub%2A is that you can map patterns, such as "{tenant}" and not just concrete paths.
You can also map the SignalR hub when the app is in a virtual folder with a branched middleware pipeline. In the following example, requests to /base/path/ are handled by Blazor's SignalR hub:
app.Map("/base/path", subapp => {
subapp.UsePathBase("/base/path");
subapp.UseRouting();
subapp.UseAntiforgery();
subapp.UseEndpoints(endpoints => {
endpoints.MapBlazorHub("/base/path/_blazor");
endpoints.MapStaticAssets();
endpoints.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
});
});
[!NOTE] The default Blazor hub path is
/_blazor.
Configure the <base> tag, per the guidance in the Configure the app base path section.
:::moniker range="< aspnetcore-8.0"
If the app is a hosted Blazor WebAssembly app:
Program.cs):
app.UseBlazorFrameworkFiles("/base/path");).app.UseStaticFiles("/base/path");).<StaticWebAssetBasePath> in the project file to match the path for serving static web assets (for example, <StaticWebAssetBasePath>base/path</StaticWebAssetBasePath> ).<base> tag, per the guidance in the Configure the app base path section.For an example of hosting multiple Blazor WebAssembly apps in a hosted Blazor WebAssembly solution, see xref:blazor/host-and-deploy/webassembly/multiple-hosted-webassembly, where approaches are explained for domain/port hosting and subpath hosting of multiple Blazor WebAssembly client apps.
:::moniker-end
In a standalone Blazor WebAssembly app, only the <base> tag is configured, per the guidance in the Configure the app base path section.
To provide configuration for the Blazor app's base path of https://www.contoso.com/CoolApp/, set the app base path (<base>), which is also called the relative root path.
By configuring the app base path, a component that isn't in the root directory can construct URLs relative to the app's root path. Components at different levels of the directory structure can build links to other resources at locations throughout the app. The app base path is also used to intercept selected hyperlinks where the href target of the link is within the app base path URI space. The xref:Microsoft.AspNetCore.Components.Routing.Router component handles the internal navigation.
Place the <base> tag in <head> markup (location of <head> content) before any elements with attribute values that are URLs, such as the href attributes of <link> elements.
:::moniker range=">= aspnetcore-11.0"
In many hosting scenarios, the relative URL path to the app is the root of the app. When the app runs at /, the BasePath component (<BasePath />) renders <base href="/" /> automatically in <head> content. For any other deployment path, the component emits a <base> element that matches the current request's path base.
:::moniker-end
:::moniker range=">= aspnetcore-8.0 < aspnetcore-11.0"
In many hosting scenarios, the relative URL path to the app is the root of the app. In these default cases, the app's relative URL base path is / configured as <base href="/" /> in <head> content.
:::moniker-end
:::moniker range="< aspnetcore-8.0"
In many hosting scenarios, the relative URL path to the app is the root of the app. In these default cases, the app's relative URL base path is the following in <head> content:
~/ configured as <base href="~/" />./ configured as <base href="/" />.:::moniker-end
[!NOTE] In some hosting scenarios, such as GitHub Pages and IIS sub-apps, the app base path must be set to the server's relative URL path of the app.
:::moniker range=">= aspnetcore-11.0"
Option 1: Use the BasePath component to set the app's base path (location of <head> content):
<BasePath />
The component renders <base href> automatically based on the current request path base.
::: moniker-end
:::moniker range="< aspnetcore-11.0"
Option 1: Use the <base> tag to set the app's base path (location of <head> content):
<base href="/CoolApp/">
The trailing slash is required.
:::moniker-end
Option 2: Call xref:Microsoft.AspNetCore.Builder.UsePathBaseExtensions.UsePathBase%2A first in the app's request processing pipeline (Program.cs) immediately after the xref:Microsoft.AspNetCore.Builder.WebApplicationBuilder is built (builder.Build()) to configure the base path for any following middleware that interacts with the request path:
app.UsePathBase("/CoolApp");
Calling xref:Microsoft.AspNetCore.Builder.UsePathBaseExtensions.UsePathBase%2A is recommended when you also wish to run the Blazor Server app locally. For example, supply the launch URL in Properties/launchSettings.json:
"launchUrl": "https://localhost:{PORT}/CoolApp",
The {PORT} placeholder in the preceding example is the port that matches the secure port in the applicationUrl configuration path. The following example shows the full launch profile for an app at port 7279:
"BlazorSample": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7279;http://localhost:5279",
"launchUrl": "https://localhost:7279/CoolApp",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
For more information on the launchSettings.json file, see xref:fundamentals/environments#development-and-launchsettingsjson. For additional information on Blazor app base paths and hosting, see <base href="/" /> or base-tag alternative for Blazor MVC integration (dotnet/aspnetcore #43191).
Standalone Blazor WebAssembly (wwwroot/index.html):
<base href="/CoolApp/">
The trailing slash is required.
:::moniker range="< aspnetcore-8.0"
Hosted Blazor WebAssembly (:::no-loc text="Client"::: project, wwwroot/index.html):
<base href="/CoolApp/">
The trailing slash is required.
In the :::no-loc text="Server"::: project, call xref:Microsoft.AspNetCore.Builder.UsePathBaseExtensions.UsePathBase%2A first in the app's request processing pipeline (Program.cs) immediately after the xref:Microsoft.AspNetCore.Builder.WebApplicationBuilder is built (builder.Build()) to configure the base path for any following middleware that interacts with the request path:
app.UsePathBase("/CoolApp");
:::moniker-end
[!NOTE] When using xref:Microsoft.AspNetCore.Builder.WebApplication (see xref:migration/50-to-60#new-hosting-model),
app.UseRoutingmust be called after xref:Microsoft.AspNetCore.Builder.UsePathBaseExtensions.UsePathBase%2A so that the Routing Middleware can observe the modified path before matching routes. Otherwise, routes are matched before the path is rewritten by xref:Microsoft.AspNetCore.Builder.UsePathBaseExtensions.UsePathBase%2A as described in the xref:fundamentals/middleware/index#middleware-order and xref:fundamentals/routing.
Don't prefix links throughout the app with a forward slash. Either avoid the use of a path segment separator or use dot-slash (./) relative path notation:
<a href="/account"><a href="account"><a href="./account">In Blazor WebAssembly web API requests with the HttpClient service, confirm that JSON helpers (xref:System.Net.Http.Json.HttpClientJsonExtensions) don't prefix URLs with a forward slash (/):
var rsp = await client.GetFromJsonAsync("/api/Account");var rsp = await client.GetFromJsonAsync("api/Account");Don't prefix Navigation Manager relative links with a forward slash. Either avoid the use of a path segment separator or use dot-slash (./) relative path notation (Navigation is an injected xref:Microsoft.AspNetCore.Components.NavigationManager):
Navigation.NavigateTo("/other");Navigation.NavigateTo("other");Navigation.NavigateTo("./other");In typical configurations for Azure/IIS hosting, additional configuration usually isn't required. In some non-IIS hosting and reverse proxy hosting scenarios, additional Static File Middleware configuration might be required:
app.UseStaticFiles("/CoolApp");)._framework/blazor.*.js). For more information, see xref:blazor/fundamentals/static-files.For a Blazor WebAssembly app with a non-root relative URL path (for example, <base href="/CoolApp/">), the app fails to find its resources when run locally. To overcome this problem during local development and testing, you can supply a path base argument that matches the href value of the <base> tag at runtime. Don't include a trailing slash. To pass the path base argument when running the app locally, execute the dotnet watch (or dotnet run) command from the app's directory with the --pathbase option:
dotnet watch --pathbase=/{RELATIVE URL PATH (no trailing slash)}
For a Blazor WebAssembly app with a relative URL path of /CoolApp/ (<base href="/CoolApp/">), the command is:
dotnet watch --pathbase=/CoolApp
If you prefer to configure the app's launch profile to specify the pathbase automatically instead of manually with dotnet watch (or dotnet run), set the commandLineArgs property in Properties/launchSettings.json. The following also configures the launch URL (launchUrl):
"commandLineArgs": "--pathbase=/{RELATIVE URL PATH (no trailing slash)}",
"launchUrl": "{RELATIVE URL PATH (no trailing slash)}",
Using CoolApp as the example:
"commandLineArgs": "--pathbase=/CoolApp",
"launchUrl": "CoolApp",
Using either dotnet watch (or dotnet run) with the --pathbase option or a launch profile configuration that sets the base path, the Blazor WebAssembly app responds locally at http://localhost:port/CoolApp.
For more information on the launchSettings.json file, see xref:fundamentals/environments#development-and-launchsettingsjson. For additional information on Blazor app base paths and hosting, see <base href="/" /> or base-tag alternative for Blazor MVC integration (dotnet/aspnetcore #43191).
The following guidance explains how to obtain the path for the <base> tag from an app settings file for different environments.
Add the app settings file to the app. The following example is for the Staging environment (appsettings.Staging.json):
{
"AppBasePath": "staging/"
}
In a server-side Blazor app, load the base path from configuration in <head> content:
@inject IConfiguration Config
...
<head>
...
<base href="/@(Config.GetValue<string>("AppBasePath"))" />
...
</head>
:::moniker range=">= aspnetcore-6.0"
Alternatively, a server-side app can obtain the value from configuration for xref:Microsoft.AspNetCore.Builder.UsePathBaseExtensions.UsePathBase%2A. Place the following code first in the app's request processing pipeline (Program.cs) immediately after the xref:Microsoft.AspNetCore.Builder.WebApplicationBuilder is built (builder.Build()). The following example uses the configuration key AppBasePath:
app.UsePathBase($"/{app.Configuration.GetValue<string>("AppBasePath")}");
In a client-side Blazor WebAssembly app:
Remove the <base> tag from wwwroot/index.html:
- <base href="..." />
Supply the app base path via a HeadContent component in the App component (App.razor):
@inject IConfiguration Config
...
<HeadContent>
<base href="/@(Config.GetValue<string>("AppBasePath"))" />
</HeadContent>
:::moniker-end
If there's no configuration value to load, for example in non-staging environments, the preceding href resolves to the root path /.
The examples in this section focus on supplying the app base path from app settings, but the approach of reading the path from xref:Microsoft.Extensions.Configuration.IConfiguration is valid for any configuration provider. For more information, see the following resources: