繁体   English   中英

Blazor webassembly 托管在子文件夹中

[英]Blazor webassembly hosted in sub folder

我有一个非常复杂的现有 asp.net 核心站点,带有一个 SPA。 此 SPA 使用 # 进行路由,因此所有现有的 razor 页面和 API 端点都可以正常工作。

我第一次尝试只使用app.UseBlazorFrameworkFiles()来托管,但是各种各样的事情都与此无关。

然后我尝试将它放在一个子文件夹中: app.UseBlazorFrameworkFiles("/UI") ,更新主Index.cshtml以重定向到/UI/并在/Areas/UI/Pages/Index.cshtml中提供适当的 HTML并添加了<StaticWebAssetBasePath>UI</StaticWebAssetBasePath>并破解了AddHttpClient以使用整个站点的基本地址。

这有效......除非它没有,特别是在使用 blazor 中子页面的 url 或从 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 AmbiguousMatchException: The request matched multiple endpoints. Matches: /Index /Index

或我能想出的任何其他类型的变体,所有结果都是 a)炸毁现有配置或 b)在启动时炸毁或 c)在访问不存在的页面时炸毁。

请帮忙。 如何让这个 blazor 托管在我的网站上?

我创建了一个标准的 Blazor WASM 托管解决方案 [客户端/服务器/共享]。

它在 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>

我不能确定 - 从一些代码片段构建图片并不容易 - 但您可能缺少index.html中的<base href=....>设置

我最近为一个非常相似的问题整理了一个 StackOverflow 答案、repo 和演示 - 这个问题是关于在同一个站点上托管多个 SPA。

在单个解决方案中创建多个 WebAssembly 项目

这是一个示例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");
    });
});

添加

这是我显示中间件顺序的完整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之后和其他所有内容之前(如果新路径是非文件,也可以在UseStaticFiles之后,例如剃须刀页面),它会将/UI/*之类的所有内容重写为/UI/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM