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

ABP 5.14 NavigationProvider中注入服务实现动态菜单报错如何解决?

ABP 5.14 NavigationProvider生成动态菜单解决方案

报错原因说明

你遇到的两个异常都是ABP启动阶段的服务生命周期特性导致的:

  • 注入应用服务时抛出AutoMapperObjectMapper依赖无法满足的异常:NavigationProvider初始化阶段,AutoMapper配置还未完成构建,依赖AutoMapper的应用服务无法被正常解析。
  • 调用Manager层方法时抛出DbContext已释放的异常:启动阶段解析得到的Manager依赖的DbContext,会在启动流程对应Scope结束后被自动销毁,后续访问数据库时对应的DbContext实例已不存在。

解决方案1:手动创建Scope解析服务(启动时一次性生成菜单)

不需要修改现有业务逻辑,仅调整NavigationProvider的服务注入和调用方式即可解决问题:

  1. 构造函数仅注入IServiceScopeFactory,不直接注入应用服务或Manager服务
  2. 在SetNavigation方法内手动创建独立的生命周期Scope,从Scope中解析所需服务
  3. 异步数据库操作使用ABP封装的AsyncHelper.RunSync执行,避免异步同步混用死锁

参考代码:

public class CustomNavigationProvider : NavigationProvider
{
    private readonly IServiceScopeFactory _serviceScopeFactory;

    // 仅注入Scope工厂
    public CustomNavigationProvider(IServiceScopeFactory serviceScopeFactory)
    {
        _serviceScopeFactory = serviceScopeFactory;
    }

    public override void SetNavigation(INavigationProviderContext context)
    {
        // 创建独立Scope,保证内部服务生命周期受控
        using var scope = _serviceScopeFactory.CreateScope();
        // 解析需要的服务
        var menuManager = scope.ServiceProvider.GetRequiredService<IMenuManager>();
        // 执行数据库查询,异步方法同步调用
        var dynamicMenuList = AsyncHelper.RunSync(() => menuManager.GetAllMenusFromDbAsync());

        // 把动态菜单添加到导航配置中
        foreach (var menu in dynamicMenuList)
        {
            context.Manager.MainMenu.AddItem(
                new MenuItemDefinition(
                    name: menu.Code,
                    displayName: new FixedLocalizableString(menu.Name),
                    url: menu.Route,
                    icon: menu.Icon,
                    requiredPermissionName: menu.Permission
                )
            );
        }
    }
}

该方案的菜单仅在应用启动时生成一次,数据库菜单配置变更后需要重启应用生效。

解决方案2:渲染阶段动态拼接菜单(支持实时更新、按用户权限动态展示)

如果需要菜单支持实时更新、不同用户看到不同菜单,推荐避开NavigationProvider的启动阶段限制,在菜单返回给前端的环节动态拼接:

  1. 仅在NavigationProvider中配置固定不变的静态菜单
  2. 在菜单查询接口/视图组件中,注入INavigationManager获取静态菜单配置,同时注入Manager/应用服务查询动态菜单
  3. 合并静态、动态菜单后再返回给前端渲染

该方案完全避开了启动阶段的服务依赖限制,菜单配置变更后无需重启应用即可生效,还支持按当前登录用户权限动态过滤菜单。

注意事项

  • 不要直接从根依赖容器解析服务,必须通过IServiceScopeFactory创建独立Scope后解析,避免出现内存泄漏、DbContext生命周期异常问题
  • 启动阶段的同步上下文下,异步方法不要直接使用.Result或.Wait()调用,优先使用ABP封装的AsyncHelper.RunSync执行,避免死锁

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 07:36:03