0

我正在开发一个 Asp.net 零项目,前端在 Angular 中,后端在 Asp.net 核心中,数据库在 MS SQL Server 中。我正在研究一种功能,通过该功能我可以在关闭浏览器或选项卡时调用注销功能以结束会话。

这是在浏览器/选项卡关闭时调用注销的Javascript 代码

window.addEventListener("unload", function (e) 
{
    if (context.validNavigation == 0) 
    {
      context._authService.logout();
    }
});

下面是C#函数,如果我们通过菜单单击手动注销,它可以正常工作,但在我们关闭浏览器时会失败:

public async Task LogOut()
        {
            if (AbpSession.UserId != null)
            {
                if (AbpSession.TenantId != null)
                {
                    var user = _userManager.GetUserById((long)AbpSession.UserId);
                    if (user != null)
                    {
                        user.AdminLoginTime = null;
                        _userManager.UpdateAsync(user); **//This is where I get Task exception**
                    }
                    LoginInput loginInput = new LoginInput
                    {
                        EventId = (int)AbpSession.TenantId,
                        Count = _commonLookupAppService.CurrentloginCount().Result
                    };    
                    this._loginHub.Clients.Group("login_" + AbpSession.TenantId).SendAsync("ReceiveLoginStatus", loginInput);
                }
                var tokenValidityKeyInClaims = User.Claims.First(c => c.Type == AppConsts.TokenValidityKey);
                RemoveTokenAsync(tokenValidityKeyInClaims.Value);    
                var refreshTokenValidityKeyInClaims = User.Claims.FirstOrDefault(c => c.Type == AppConsts.RefreshTokenValidityKey);
                if (refreshTokenValidityKeyInClaims != null)
                {                        RemoveTokenAsync(refreshTokenValidityKeyInClaims.Value);
                }    
                if (AllowOneConcurrentLoginPerUser())
                {
                    _securityStampHandler.RemoveSecurityStampCacheItem(
                       AbpSession.TenantId,
                       AbpSession.GetUserId()
                   );
                }
            }
        }

仅当我们关闭浏览器时,_userManager.UpdateAsync(user) 才会生成任务异常。如果我通过单击菜单按钮正确注销,它工作正常。任务异常不允许记录在 AbpUsers 和 SignalR Hub 中更新,异常退出 c# 函数。我无法在关闭浏览器时解决此问题。

堆栈跟踪 :

at Abp.Domain.Uow.UnitOfWorkInterceptor.<InternalInterceptAsynchronous>d__5`1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at ryt.Web.Controllers.TokenAuthController.<LogOut>d__37.MoveNext() in D:\Ravi_2021\sinyunpl\aspnet-core\src\ryt.Web.Core\Controllers\TokenAuthController.cs:line 343

在此处输入图像描述

如果你们中的任何人遇到这个问题并找到了解决方案,请告诉我。

4

2 回答 2

0

根据此处找到的 Microsoft 文档:

当用户关闭浏览器窗口或选项卡,或导航到新页面或刷新页面时,SignalR 连接会立即结束,因为 SignalR 客户端代码会为您处理该浏览器事件并调用 Stop 方法。

也许在您完成 Logout 方法之前,signalR 客户端会自动停止连接?然后,为什么只有在关闭选项卡时才会发生错误是有道理的。

于 2022-03-02T13:27:57.350 回答
0

当浏览器关闭时,TCP 连接关闭,HTTP 请求中止。

ABP 使用via 。HttpContext.RequestAborted CancellationTokenHttpContextCancellationTokenProvider

要在这种情况下覆盖该行为,请CancellationTokenProvider.Use(CancellationToken.None)using语句中调用并且await您的异步方法调用:

public async Task LogOut()
{
    using (CancellationTokenProvider.Use(CancellationToken.None))
    {
        var user = _userManager.GetUserById((long)AbpSession.UserId);
        await _userManager.UpdateAsync(user);
    }
}

参考:https ://github.com/aspnetboilerplate/aspnetboilerplate/.../CancellationToken_Tests.cs#L56

于 2022-03-04T18:04:06.210 回答