使用FindByIdAsync时取消ASP.Net核心标识

时间:2017-06-08 08:46:12

标签: asp.net entity-framework asp.net-core-identity

我有一个小项目,它使用Asp.Net核心身份框架和EF Core。 一个函数调用UserManager.FindByIdAsync(id)并返回正确的对象。但是,它仅在应用程序启动后的几分钟内工作。只要服务器忙,它就能正常工作,但只要应用程序空闲超过1-2分钟,请求就会失败。

失败了:

*OperationCanceledException: The operation was canceled.
System.Threading.CancellationToken.ThrowOperationCanceledException()*

stacktrace看起来像这样:

*System.Threading.CancellationToken.ThrowOperationCanceledException()
Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore.FindByIdAsync(string userId, CancellationToken cancellationToken)
Microsoft.AspNetCore.Identity.UserManager.FindByIdAsync(string userId)
MyProject.Areas.Admin.ControllerServices.UserService+<GetUser>d__11.MoveNext() in UserService.cs*

我还在登录,因为其他网页工作正常。 对EF context.Users.FindAsync(new object[] { id })的简单调用将按预期工作,但包含FindByIdAsync的下一行将失败。

所有这些在开发环境中都很完美,当在WS 2008 R2上运行IIS的服务器上安装应用程序时会发生错误。回收应用程序池将使其再次工作,直到它再次闲置几分钟。

我注意到当'Connection id'0HL5E91K33IIQ“重置”时。正在记录,然后应用程序开始失败。在此之前它有效。

FindByIdAsync不是唯一失败的身份函数,许多其他函数失败并出现相同的错误。

我错过了什么?

2 个答案:

答案 0 :(得分:7)

我将回答我自己的问题,希望这将有助于其他人。

对我来说,这一切都归结为注入服务的生命周期。 UserManager取决于IHttpContextAccessor(这是CancellationToken来自的地方),并且在生命周期不匹配时行为不正确。 IHttpContextAccessor被添加为Singleton服务,而UserManager被添加为范围服务。我使用UserManager的服务已添加为Singleton服务。 将此更改为Scoped会使错误消失。

答案 1 :(得分:0)

在我的情况下,它归结为完全相同的问题,但是由ASP.Net Core的DI实现中的一个非常微妙的设计“缺陷”引起。由于各种原因,我更喜欢使用SimpleInjector,但是将ASP.Net Identity Core填充到其中是很困难的,相比之下,为容器中的构建提供了很好的扩展方法。所以我将框架内容放在框架容器中,并将我的业务放在SimpleInjector中,决定“身份验证和授权”被认为是“框架”。框架容器仅使用交叉布线解析AccountController。但是,在请求范围外使用app.ApplicationServices.GetService<AccountController>()不会失败,但会返回一个能够存活的 Singleton !不幸的是,当您让SimpleInjector验证它的配置时,会发生这种情况。导致故障的第一个请求(错误登录)会使整个运行时出现缺陷单例实例。 SimpleInjectors文档中详细记录了此解决方案,而是使用其扩展名app.GetRequiredRequestService<AccountController>()

更新asp.net core 2.0

现在,你不会得到可疑的单例实例,但是例外: System.InvalidOperationException: 'Cannot resolve scoped service 'WebApplication15.Controllers.AccountController' from root provider.'