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

ASP.NET Core迁移后AbpSession.Use调用触发UserManager已释放异常

问题:ASP.NET Core 8中使用AbpSession.Use()时出现UserManager已释放异常

将基于.NET Framework 4.6的ASP.NET Boilerplate 7.4 MVC应用迁移至ASP.NET Core 8后,在MVC控制器中使用AbpSession.Use(...)时触发异常,该问题在原MVC5应用中不存在。

相关代码

控制器代码

public class BookMgmController : AbpController {
    ...

    [HttpPost]
    public async Task<JsonResult> Pay(PayRequestVM input) {
        ...
        using (AbpSession.Use(AbpSession.TenantId, myAuthorizedUserIdToAccessOrders)) {
            // 创建订单并设置为"等待支付"状态
            var order = await _orderAppService.CreateAsync(input);   // <--- 问题出现处!
            ...
        }   // using...
    }
}

OrderAppService代码

[AbpAuthorize(PermissionNames.Pages_Orders)]
public class OrderAppService : ..., IOrderAppService {
    ...
    public override async Task<BasicOrderDto> CreateAsync(CreateOrderDto input) {
        ...
    }
    ...
}

异常信息

调用CreateAsync(...)时,ABP抛出异常:

Cannot access a disposed object.
Object name: 'GPSoftware.Booking.Authorization.Users.UserManager'

移除OrderAppService上的AbpAuthorize属性后,异常消失。

堆栈跟踪

System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'GPSoftware.Booking.Authorization.Users.UserManager'.
   at Microsoft.AspNetCore.Identity.UserManager`1.FindByIdAsync(String userId)
   at Abp.Authorization.Users.AbpUserManager`2.<>c__DisplayClass91_0.<<GetUserPermissionCacheItemAsync>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at Abp.Runtime.Caching.TypedCacheWrapper`2.<>c__DisplayClass21_0.<<GetAsync>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at Abp.Runtime.Caching.AbpCacheBase`2.GetAsync(TKey key, Func`2 factory)
   at Abp.Runtime.Caching.TypedCacheWrapper`2.GetAsync(TKey key, Func`2 factory)
   at Abp.Authorization.Users.AbpUserManager`2.GetUserPermissionCacheItemAsync(Int64 userId)
   at Abp.Authorization.Users.AbpUserManager`2.IsGrantedAsync(Int64 userId, Permission permission)
   at Abp.Authorization.Users.AbpUserManager`2.IsGrantedAsync(Int64 userId, String permissionName)
   at Abp.Authorization.PermissionChecker`2.IsGrantedAsync(Int64 userId, String permissionName)
   at Abp.Authorization.PermissionChecker`2.IsGrantedAsync(String permissionName)
   at Abp.Authorization.PermissionCheckerExtensions.IsGrantedAsync(IPermissionChecker permissionChecker, Boolean requiresAll, String[] permissionNames)
   at Abp.Authorization.PermissionCheckerExtensions.AuthorizeAsync(IPermissionChecker permissionChecker, Boolean requireAll, String[] permissionNames)
   at Abp.Authorization.AuthorizationHelper.AuthorizeAsync(IEnumerable`1 authorizeAttributes)
   at Abp.Authorization.AuthorizationHelper.CheckPermissionsAsync(MethodInfo methodInfo, Type type)
   at Abp.Authorization.AuthorizationHelper.AuthorizeAsync(MethodInfo methodInfo, Type type)
   at Abp.Authorization.AuthorizationInterceptor.InternalInterceptAsynchronous[TResult](IInvocation invocation)
   at Abp.Auditing.AuditingInterceptor.InternalInterceptAsynchronous[TResult](IInvocation invocation)
   at Abp.Auditing.AuditingInterceptor.InternalInterceptAsynchronous[TResult](IInvocation invocation)
   at GPSoftware.Booking.Web.Controllers.BookMgmController.DoPay(PayShoppingCartRequestVM input) in C:\WA\GPsoftware\PortamiInPista.NET\aspnet-core\src\web\Booking.Web.Mvc\Controllers\BookMgmController.cs:line 165
   at GPSoftware.Booking.Web.Controllers.BookMgmController.Pay(PayShoppingCartRequestVM input) in C:\WA\GPsoftware\PortamiInPista.NET\aspnet-core\src\web\Booking.Web.Mvc\Controllers\BookMgmController.cs:line 131

补充信息

  • 更新1:大部分对象由ABP框架注入DI,运行时均不为空(包括UserManager和AbpSession)。
  • 更新2:基于ABP模板的简单测试代码未出现该错误。

调试细节

Abp.Authorization.Users.AbpUserManager<TRole, TUser>的私有方法GetUserPermissionCacheItemAsync调用FindByIdAsync和GetRolesAsync时失败:

private async Task<UserPermissionCacheItem> GetUserPermissionCacheItemAsync(long userId) {
    var cacheKey = userId + "@" + (GetCurrentTenantId() ?? 0);
    return await _cacheManager.GetUserPermissionCache().GetAsync(cacheKey, async () => {
        var user = await FindByIdAsync(userId.ToString());  // <= 此处失败
        if (user == null) {
            return null;
        }

        var newCacheItem = new UserPermissionCacheItem(userId);

        foreach (var roleName in await GetRolesAsync(user)) { // <= 此处失败
            newCacheItem.RoleIds.Add((await RoleManager.GetRoleByNameAsync(roleName)).Id);
        }

        foreach (var permissionInfo in await UserPermissionStore.GetPermissionsAsync(userId)) {
            if (permissionInfo.IsGranted) {
                newCacheItem.GrantedPermissions.Add(permissionInfo.Name);
            } else {
                newCacheItem.ProhibitedPermissions.Add(permissionInfo.Name);
            }
        }

        return newCacheItem;
    });
}

重写自定义UserManager的FindByIdAsync方法并注释ThrowIfDisposed()后可正常运行:

public override Task<User> FindByIdAsync(string userId) {
    //ThrowIfDisposed();
    return Store.FindByIdAsync(userId, CancellationToken);
}

但重写GetRolesAsync较为复杂,无法继续。

疑问与求助

  1. 为何会出现该问题?
  2. 为何模板代码无此异常?
  3. 求可行的解决方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 12:06:10