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

Blazor (.NET8)托管应用直接访问链接时懒加载失效问题求助

Blazor .NET 8托管式Web应用懒加载直接URL访问失效问题解决

问题描述

为Blazor .NET 8托管式Web应用实现懒加载后,通过导航菜单跳转至/dashboard页面时懒加载正常工作,但直接在浏览器地址栏输入URL访问时懒加载失效,页面显示NotFound。若在Program.cs中添加Dashboard项目程序集的AddAdditionalAssemblies引用,虽能解决直接访问问题,但会导致页面加载两次。

原因分析

直接输入URL访问时,Router组件在初始渲染阶段就会执行路由匹配,此时懒加载的程序集尚未加载(OnNavigateAsync是在路由匹配流程之后触发的),因此无法找到对应路由,直接进入NotFound分支。而添加AddAdditionalAssemblies会让应用在初始启动时就加载Dashboard程序集,破坏了懒加载的设计,同时导致后续导航时重复加载该程序集。

解决方案

方案1:初始加载时预检查路径并加载程序集

修改Routes.razor,在组件初始化阶段先根据当前URL路径加载对应程序集,再触发Router重新匹配路由:

@using BlazorApp.Client.Layout
@using Microsoft.AspNetCore.Components.WebAssembly.Services
@using System.Reflection
@inject LazyAssemblyLoader assemblyLoader
@inject NavigationManager NavigationManager

<Router AppAssembly="@typeof(Program).Assembly"
        OnNavigateAsync="OnNavigateAsync"
        AdditionalAssemblies="_lazyLoadedAssemblies">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
        <FocusOnNavigate RouteData="@routeData" Selector="h1" />
    </Found>
    <NotFound>
        <PageTitle>Not found</PageTitle>
        <LayoutView Layout="@typeof(MainLayout)">
            <p role="alert">Sorry, there's nothing at this address.</p>
        </LayoutView>
    </NotFound>
    <Navigating>
        <p>Page loading...</p>
    </Navigating>
</Router>

@code
{
    private readonly List<Assembly> _lazyLoadedAssemblies = [];
    private bool _isInitialLoadComplete = false;

    protected override async Task OnInitializedAsync()
    {
        // 获取当前URL的相对路径,处理BasePath影响
        var initialPath = NavigationManager.ToBaseRelativePath(NavigationManager.Uri);
        
        // 根据初始路径加载对应程序集
        var assemblies = initialPath switch
        {
            "dashboard" => await assemblyLoader.LoadAssembliesAsync(new[] { "Dashboard.wasm" }),
            _ => []
        };
        
        _lazyLoadedAssemblies.AddRange(assemblies);
        _isInitialLoadComplete = true;
        
        // 触发组件重新渲染,让Router重新匹配路由
        StateHasChanged();
    }

    private async Task OnNavigateAsync(NavigationContext context)
    {
        // 仅处理初始加载后的导航跳转
        if (_isInitialLoadComplete)
        {
            var assemblies = context.Path switch
            {
                "dashboard" => await assemblyLoader.LoadAssembliesAsync(new[] { "Dashboard.wasm" }),
                _ => []
            };

            _lazyLoadedAssemblies.AddRange(assemblies);
        }
    }
}

方案2:使用Route Group结合懒加载组件(更优雅)

通过自定义懒加载组件,在路由匹配后先加载目标程序集再渲染页面,避免初始路由匹配失败:

步骤1:创建LazyLoadAssembly.razor组件

@inject LazyAssemblyLoader assemblyLoader
@using System.Reflection

@if (_isLoaded)
{
    @ChildContent
}
else
{
    <p>Loading page...</p>
}

@code {
    [Parameter, Required] public string AssemblyName { get; set; } = string.Empty;
    [Parameter] public RenderFragment? ChildContent { get; set; }
    
    private bool _isLoaded = false;
    private List<Assembly> _loadedAssemblies = [];

    protected override async Task OnInitializedAsync()
    {
        // 加载指定程序集
        var assemblies = await assemblyLoader.LoadAssembliesAsync(new[] { AssemblyName });
        _loadedAssemblies.AddRange(assemblies);
        _isLoaded = true;
        StateHasChanged();
    }
}

步骤2:修改Routes.razor使用懒加载组件

@using BlazorApp.Client.Layout
@using Microsoft.AspNetCore.Components.WebAssembly.Services
@using System.Reflection

<Router AppAssembly="@typeof(Program).Assembly">
    <Found Context="routeData">
        <!-- 对/dashboard路由使用懒加载 -->
        @if (routeData.Route.RouteTemplate.StartsWith("/dashboard"))
        {
            <LazyLoadAssembly AssemblyName="Dashboard.wasm">
                <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
                <FocusOnNavigate RouteData="@routeData" Selector="h1" />
            </LazyLoadAssembly>
        }
        else
        {
            <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
            <FocusOnNavigate RouteData="@routeData" Selector="h1" />
        }
    </Found>
    <NotFound>
        <PageTitle>Not found</PageTitle>
        <LayoutView Layout="@typeof(MainLayout)">
            <p role="alert">Sorry, there's nothing at this address.</p>
        </LayoutView>
    </NotFound>
    <Navigating>
        <p>Page loading...</p>
    </Navigating>
</Router>

注意事项

  • 确保懒加载的程序集(如Dashboard.wasm)已正确发布到应用的wwwroot目录,可通过项目属性设置“复制到输出目录”为“始终复制”。
  • 不要在Program.cs中添加懒加载程序集的AddAdditionalAssemblies引用,否则会导致程序集在初始启动时被加载,失去懒加载效果。
  • 处理路径时需使用NavigationManager.ToBaseRelativePath,避免应用配置了BasePath导致路径匹配错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 21:05:10