托管在子文件夹中的 Blazor webassembly
Blazor webassembly hosted in sub folder
我有一个相当复杂的现有 asp.net 核心站点,带有 SPA。此 SPA 使用 # 进行路由,因此所有现有的剃刀页面和 API 端点都可以正常工作。
我最初尝试仅使用 app.UseBlazorFrameworkFiles()
来托管,但各种事情都与此有关。
然后我尝试将它放在一个子文件夹中:app.UseBlazorFrameworkFiles("/UI")
,更新主 Index.cshtml
以重定向到 /UI/
并在 HTML 中提供适当的 HTML =17=] 并添加了 <StaticWebAssetBasePath>UI</StaticWebAssetBasePath>
并破解了 AddHttpClient
以使用整个站点的基本地址。
这行得通...除非行不通,特别是当使用 url 到 blazor 中的子页面或从 blazor 导航到不存在的路由时。这将最终访问托管站点并为我的 404 服务。
然后我尝试了
的各种变体
app.MapWhen(ctx => ctx.Request.Path.StartsWithSegments("/UI/"), blazor => {
blazor.UseEndpoints(endpoints => {
endpoints.MapFallbackToAreaPage("/UI/{*path:nonfile}", "/", "UI");
});
});
结果:InvalidOperationException: Cannot find the fallback endpoint specified by route values: { page: /, area: UI }.
app.MapFallbackToAreaPage("/", "UI");
结果:InvalidOperationException: Cannot find the fallback endpoint specified by route values: { page: /, area: UI }.
app.MapFallbackToAreaPage("/Index", "UI");
结果:AmbiguousMatchException: The request matched multiple endpoints. Matches: /Index /Index
或我能想到的任何其他类型的变体,结果都是
a) 炸毁现有配置或 b) 在启动时炸毁或 c) 在访问不存在的页面时炸毁。
请帮忙。如何在我的网站上托管此 blazor?
我在这里不确定 - 从一些代码片段构建图片并不容易 - 但你可能缺少 index.html
中的 <base href=....>
设置
我最近针对一个非常相似的问题将 Whosebug 答案、存储库和演示放在一起 - 这个问题是关于在同一站点上托管多个 SPA。
这是一个例子index.html
:
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>Blazr.Medusa.Grey</title>
<base href="/grey/" />
<link href="/grey/css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="/grey/css/app.css" rel="stylesheet" />
<link href="Blazr.Medusa.Grey.styles.css" rel="stylesheet" />
</head>
项目文件:
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<StaticWebAssetBasePath>grey</StaticWebAssetBasePath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.2" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Blazr.Medusa.SPA\Blazr.Medusa.SPA.csproj" />
</ItemGroup>
</Project>
和网站程序设置部分:
app.MapWhen(ctx => ctx.Request.Path.StartsWithSegments("/grey"), app1 =>
{
app1.UseBlazorFrameworkFiles("/grey");
app1.UseRouting();
app1.UseEndpoints(endpoints =>
{
endpoints.MapFallbackToFile("/grey/{*path:nonfile}", "/grey/index.html");
});
});
Addition
这是我完整的 Program
来显示中间件顺序:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.MapWhen(ctx => ctx.Request.Path.StartsWithSegments("/grey"), app1 =>
{
app1.UseBlazorFrameworkFiles("/grey");
app1.UseRouting();
app1.UseEndpoints(endpoints =>
{
endpoints.MapFallbackToFile("/grey/{*path:nonfile}", "/grey/index.html");
});
});
app.MapWhen(ctx => ctx.Request.Path.StartsWithSegments("/green"), app1 =>
{
app1.UseBlazorFrameworkFiles("/green");
app1.UseRouting();
app1.UseEndpoints(endpoints =>
{
endpoints.MapFallbackToFile("/green/{*path:nonfile}", "/green/index.html");
});
});
app.MapWhen(ctx => ctx.Request.Path.StartsWithSegments("/purple"), app1 =>
{
app1.UseBlazorFrameworkFiles("/purple");
app1.UseRouting();
app1.UseEndpoints(endpoints =>
{
endpoints.MapFallbackToFile("/purple/{*path:nonfile}", "/purple/index.html");
});
});
app.UseBlazorFrameworkFiles("");
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.MapFallbackToFile("/index.html");
app.Run();
任何问题 - 问。
TLDR;在管道开始时修复它,而不是在结束时(使用 mapfallback)
我能够通过破解管道并重写请求找到解决方案。
app.UseHttpsRedirection(); //after this
//host blazor in this folder
app.UseBlazorFrameworkFiles("/UI");
app.Use((ctx, next) => {
if (ctx.Request.Path.StartsWithSegments("/UI", out var rest) && !rest.StartsWithSegments("/"))
{
//detected paths that needs to be routed by Blazor and not server
ctx.Request.Path = new PathString("/UI/");
return next();
}
return next();
});
如果将其放在 UseHttpsRedirection
之后和其他所有内容之前(如果新路径是 non-file,也可以放在 UseStaticFiles
之后),它将重写一切都像 /UI/*
变成 /UI/
.
我创建了一个标准的 Blazor WASM 托管解决方案 [Client/Server/Shared]。
它在 Visual studio 中构建并且 运行 正常,但是当我将它发布到我网站上的子文件夹时,它无法加载。
我终于确定问题出在客户端 index.html 中的 <base href="/" />
。
子文件夹的名称与解决方案 [BlazorWASMHosted2022] 相同,因此我将标签更改为 <base href="/BlazorWASMHosted2022/" />
并再次发布了解决方案,一切正常。
根据我用谷歌搜索的结果,这似乎是 Blazor WASM 的问题。
所以我想出了一个添加到 index.html 的脚本来测试当前的 URL 并相应地设置 base.href 这工作正常 - 这是我的示例(带有一些信息加载时显示):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>BlazorWASMHosted2022</title>
<script type="text/javascript">
var base = document.createElement('base');
var currentUrl = window.location.href;
var localHostUrl = 'https://localhost';
if (currentUrl.startsWith(localHostUrl))
{
base.href = '/';
} else {
base.href = '/BlazorWASMHosted2022/';
}
document.getElementsByTagName('head')[0].appendChild(base);
</script>
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="css/app.css" rel="stylesheet" />
<link href="BlazorWASMHosted2022.Client.styles.css" rel="stylesheet" />
</head>
<body>
<div id="app">Loading...</div>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss"></a>
</div>
<script type="text/javascript">
document.write("location.pathname:- <br/>");
document.write(window.location.href);
document.write("<br/>");
document.write("base.href:- <br/>");
document.write(base.href);
</script>
<script src="_framework/blazor.webassembly.js"></script>
</body>
</html>
我有一个相当复杂的现有 asp.net 核心站点,带有 SPA。此 SPA 使用 # 进行路由,因此所有现有的剃刀页面和 API 端点都可以正常工作。
我最初尝试仅使用 app.UseBlazorFrameworkFiles()
来托管,但各种事情都与此有关。
然后我尝试将它放在一个子文件夹中:app.UseBlazorFrameworkFiles("/UI")
,更新主 Index.cshtml
以重定向到 /UI/
并在 HTML 中提供适当的 HTML =17=] 并添加了 <StaticWebAssetBasePath>UI</StaticWebAssetBasePath>
并破解了 AddHttpClient
以使用整个站点的基本地址。
这行得通...除非行不通,特别是当使用 url 到 blazor 中的子页面或从 blazor 导航到不存在的路由时。这将最终访问托管站点并为我的 404 服务。
然后我尝试了
的各种变体app.MapWhen(ctx => ctx.Request.Path.StartsWithSegments("/UI/"), blazor => {
blazor.UseEndpoints(endpoints => {
endpoints.MapFallbackToAreaPage("/UI/{*path:nonfile}", "/", "UI");
});
});
结果:InvalidOperationException: Cannot find the fallback endpoint specified by route values: { page: /, area: UI }.
app.MapFallbackToAreaPage("/", "UI");
结果:InvalidOperationException: Cannot find the fallback endpoint specified by route values: { page: /, area: UI }.
app.MapFallbackToAreaPage("/Index", "UI");
结果:AmbiguousMatchException: The request matched multiple endpoints. Matches: /Index /Index
或我能想到的任何其他类型的变体,结果都是 a) 炸毁现有配置或 b) 在启动时炸毁或 c) 在访问不存在的页面时炸毁。
请帮忙。如何在我的网站上托管此 blazor?
我在这里不确定 - 从一些代码片段构建图片并不容易 - 但你可能缺少 index.html
<base href=....>
设置
我最近针对一个非常相似的问题将 Whosebug 答案、存储库和演示放在一起 - 这个问题是关于在同一站点上托管多个 SPA。
这是一个例子index.html
:
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>Blazr.Medusa.Grey</title>
<base href="/grey/" />
<link href="/grey/css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="/grey/css/app.css" rel="stylesheet" />
<link href="Blazr.Medusa.Grey.styles.css" rel="stylesheet" />
</head>
项目文件:
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<StaticWebAssetBasePath>grey</StaticWebAssetBasePath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.2" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Blazr.Medusa.SPA\Blazr.Medusa.SPA.csproj" />
</ItemGroup>
</Project>
和网站程序设置部分:
app.MapWhen(ctx => ctx.Request.Path.StartsWithSegments("/grey"), app1 =>
{
app1.UseBlazorFrameworkFiles("/grey");
app1.UseRouting();
app1.UseEndpoints(endpoints =>
{
endpoints.MapFallbackToFile("/grey/{*path:nonfile}", "/grey/index.html");
});
});
Addition
这是我完整的 Program
来显示中间件顺序:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.MapWhen(ctx => ctx.Request.Path.StartsWithSegments("/grey"), app1 =>
{
app1.UseBlazorFrameworkFiles("/grey");
app1.UseRouting();
app1.UseEndpoints(endpoints =>
{
endpoints.MapFallbackToFile("/grey/{*path:nonfile}", "/grey/index.html");
});
});
app.MapWhen(ctx => ctx.Request.Path.StartsWithSegments("/green"), app1 =>
{
app1.UseBlazorFrameworkFiles("/green");
app1.UseRouting();
app1.UseEndpoints(endpoints =>
{
endpoints.MapFallbackToFile("/green/{*path:nonfile}", "/green/index.html");
});
});
app.MapWhen(ctx => ctx.Request.Path.StartsWithSegments("/purple"), app1 =>
{
app1.UseBlazorFrameworkFiles("/purple");
app1.UseRouting();
app1.UseEndpoints(endpoints =>
{
endpoints.MapFallbackToFile("/purple/{*path:nonfile}", "/purple/index.html");
});
});
app.UseBlazorFrameworkFiles("");
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.MapFallbackToFile("/index.html");
app.Run();
任何问题 - 问。
TLDR;在管道开始时修复它,而不是在结束时(使用 mapfallback)
我能够通过破解管道并重写请求找到解决方案。
app.UseHttpsRedirection(); //after this
//host blazor in this folder
app.UseBlazorFrameworkFiles("/UI");
app.Use((ctx, next) => {
if (ctx.Request.Path.StartsWithSegments("/UI", out var rest) && !rest.StartsWithSegments("/"))
{
//detected paths that needs to be routed by Blazor and not server
ctx.Request.Path = new PathString("/UI/");
return next();
}
return next();
});
如果将其放在 UseHttpsRedirection
之后和其他所有内容之前(如果新路径是 non-file,也可以放在 UseStaticFiles
之后),它将重写一切都像 /UI/*
变成 /UI/
.
我创建了一个标准的 Blazor WASM 托管解决方案 [Client/Server/Shared]。
它在 Visual studio 中构建并且 运行 正常,但是当我将它发布到我网站上的子文件夹时,它无法加载。
我终于确定问题出在客户端 index.html 中的 <base href="/" />
。
子文件夹的名称与解决方案 [BlazorWASMHosted2022] 相同,因此我将标签更改为 <base href="/BlazorWASMHosted2022/" />
并再次发布了解决方案,一切正常。
根据我用谷歌搜索的结果,这似乎是 Blazor WASM 的问题。
所以我想出了一个添加到 index.html 的脚本来测试当前的 URL 并相应地设置 base.href 这工作正常 - 这是我的示例(带有一些信息加载时显示):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>BlazorWASMHosted2022</title>
<script type="text/javascript">
var base = document.createElement('base');
var currentUrl = window.location.href;
var localHostUrl = 'https://localhost';
if (currentUrl.startsWith(localHostUrl))
{
base.href = '/';
} else {
base.href = '/BlazorWASMHosted2022/';
}
document.getElementsByTagName('head')[0].appendChild(base);
</script>
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="css/app.css" rel="stylesheet" />
<link href="BlazorWASMHosted2022.Client.styles.css" rel="stylesheet" />
</head>
<body>
<div id="app">Loading...</div>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss"></a>
</div>
<script type="text/javascript">
document.write("location.pathname:- <br/>");
document.write(window.location.href);
document.write("<br/>");
document.write("base.href:- <br/>");
document.write(base.href);
</script>
<script src="_framework/blazor.webassembly.js"></script>
</body>
</html>