You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor模块化UI应用服务容器托管时的路由配置问题

问题:Blazor作为HostedService跨进程运行时的回退路由映射问题

我正在尝试创建Blazor应用,计划将宿主与布局定义在单个Razor Class Library(RCL)或应用中,供其他RCL模块复用。但遇到路由问题,始终无法实现预期效果。具体来说,当Blazor应用自身作为HostedService在另一个进程中运行时,不知道如何将回退路由正确映射到宿主页面。

示例场景

我用标准“Blazor Server Application”模板创建应用,把应用构建逻辑移到了UiHostService中,代码如下:

using Alpha.ReferenceApp.Data;

namespace Alpha.ReferenceApp.Services
{
public class UiHostService : IHostedService
{
    WebApplication? _app;

    public Task StartAsync(CancellationToken cancellationToken)
    {
        var builder = WebApplication.CreateBuilder(Environment.GetCommandLineArgs());

        // Add services to the container.
        builder.Services.AddRazorPages();
        builder.Services.AddServerSideBlazor();
        builder.Services.AddSingleton<WeatherForecastService>();

        _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.
            _app.UseHsts();
        }

        _app.UseHttpsRedirection();
        _app.UseStaticFiles();
        _app.UseRouting();
        _app.MapBlazorHub();
        _app.MapFallbackToPage("/_Host");

        return _app.StartAsync(cancellationToken);
    }

    public Task StopAsync(CancellationToken cancellationToken) =>
        _app?.StopAsync(cancellationToken) ?? Task.CompletedTask;
}

原应用的Program.cs代码如下:

public static async Task Main() => await Host.CreateDefaultBuilder()
        .ConfigureServices(svc => svc
            .AddHostedService<UiHostService>()
        )
        .Build()
        .RunAsync();

该方案在原应用中运行可行,且能加载来自RCL的区域/页面。但将其加载到独立应用Alpha.HostProcess的服务容器中时(代码如下),无法将路由映射回回退页面“_Host”。

using Alpha.ReferenceApp.Services;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

await Host.CreateDefaultBuilder().ConfigureServices(svc => svc
    .AddHostedService<UiHostService>()
)
.Build()
.RunAsync();

问题原因

  • 内容根路径不匹配:独立宿主进程运行时,WebApplication默认内容根路径是宿主进程的执行目录,而非原Blazor应用的目录,导致找不到_Host.cshtml页面文件。
  • 资源访问权限缺失:独立进程无法访问原Blazor应用中的Razor页面、静态资源等文件,因为这些文件未被正确嵌入或复制到宿主进程环境中。

正确配置方式

方式一:将Blazor应用转为RCL并嵌入资源

  1. 转换项目类型并配置嵌入资源:
    将原Blazor项目改为Razor Class Library(RCL),把_Host.cshtml、布局文件、静态资源等文件的生成操作设置为嵌入的资源(在文件属性中修改)。
  2. 指定内容根路径:
    创建WebApplicationBuilder时,指定内容根路径为RCL程序集所在目录:
    using System.Reflection;
    
    var builder = WebApplication.CreateBuilder(new WebApplicationOptions
    {
        Args = Environment.GetCommandLineArgs(),
        ContentRootPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
    });
    
  3. 注册嵌入式Razor Pages:
    添加Razor Pages服务时,指定加载当前程序集的页面资源:
    builder.Services.AddRazorPages()
        .AddApplicationPart(typeof(UiHostService).Assembly);
    

方式二:调整宿主进程的内容根路径

若不想转为RCL,可直接修改独立宿主进程的内容根路径,使其指向原Blazor应用的发布目录:

await Host.CreateDefaultBuilder(new[] { "--contentRoot", @"C:\Path\To\Alpha.ReferenceApp\Publish" })
    .ConfigureServices(svc => svc.AddHostedService<UiHostService>())
    .Build()
    .RunAsync();

确保原Blazor应用已发布到指定路径,且宿主进程有权限访问该目录下的所有文件。

路由配置补充注意事项

  • 确认MapFallbackToPage("/_Host")中的路径正确,_Host.cshtml需位于Razor Pages的根目录(或配置的RootDirectory下)。
  • 若使用区域,需在路由中指定区域,例如:MapFallbackToPage("/_Host", "/Areas/MyArea")。

内容的提问来源于stack exchange,提问作者Mik3c

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 10:45:27