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
相关产品推荐
相关产品推荐

