【问题标题】:ASP.NET MVC Identity Framework hangs on FindByEmail call in development, but not live versionASP.NET MVC 身份框架在开发中挂起 FindByEmail 调用,但不是实时版本
【发布时间】:2018-01-29 08:18:15
【问题描述】:

我们的网站使用 MVC 和身份框架 2.0。在实时站点上(幸运的是)用户现在可以完美登录:

这是使这项工作附加到 Account 控制器的 Login 操作的代码:

public async Task<ActionResult> Login(vmAccountLogin model, string ReturnUrl)
{
    // if problems with model, just redisplay form
    if (!ModelState.IsValid)
    {
        return View(model);
    }


    // hangs on this line
    var user = UserManager.FindByEmail(model.Email);

    // if user not found for this email, abort with no clues
    if (user == null)

当我构建项目并将 DLL 复制到实时服务器时,它可以完美运行。但是...

在我的测试版本中,这挂在显示的行上。大约十秒钟后,调试跳转到 Dispose 方法。我已经逐行检查了 web.config 文件以检查它们是否相同。我读过很多 SO 文章,但不认为其中任何一篇适用于这个问题。顺便说一下,这是 UserManager 调用,效果很好:

public ApplicationUserManager UserManager
{
    get
    {
        return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
    }
    private set
    {
        _userManager = value;
    }
}

如果我启用 .NET 符号的调试,它会挂在 FindByEmail 方法调用上。 GetUserManager 调用在即时窗口中显示:

?HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
{wiseowl.ApplicationUserManager}
    ClaimsIdentityFactory: {Microsoft.AspNet.Identity.ClaimsIdentityFactory<wiseowl.Models.ApplicationUser, string>}
    DefaultAccountLockoutTimeSpan: {00:05:00}
    EmailService: {wiseowl.EmailService}
    MaxFailedAccessAttemptsBeforeLockout: 5
    PasswordHasher: {Microsoft.AspNet.Identity.PasswordHasher}
    PasswordValidator: {Microsoft.AspNet.Identity.PasswordValidator}
    SmsService: {wiseowl.SmsService}
    Store: {Microsoft.AspNet.Identity.EntityFramework.UserStore<wiseowl.Models.ApplicationUser>}
    SupportsQueryableUsers: true
    SupportsUserClaim: true
    SupportsUserEmail: true
    SupportsUserLockout: true
    SupportsUserLogin: true
    SupportsUserPassword: true
    SupportsUserPhoneNumber: true
    SupportsUserRole: true
    SupportsUserSecurityStamp: true
    SupportsUserTwoFactor: true
    TwoFactorProviders: Count = 2
    UserLockoutEnabledByDefault: true
    UserTokenProvider: {Microsoft.AspNet.Identity.Owin.DataProtectorTokenProvider<wiseowl.Models.ApplicationUser>}
    UserValidator: {Microsoft.AspNet.Identity.UserValidator<wiseowl.Models.ApplicationUser>}
    Users: {System.Data.Entity.DbSet<wiseowl.Models.ApplicationUser>}
    _claimsFactory: {Microsoft.AspNet.Identity.ClaimsIdentityFactory<wiseowl.Models.ApplicationUser, string>}
    _defaultLockout: {00:05:00}
    _disposed: false
    _factors: Count = 2
    _passwordHasher: {Microsoft.AspNet.Identity.PasswordHasher}
    _passwordValidator: {Microsoft.AspNet.Identity.PasswordValidator}
    _userValidator: {Microsoft.AspNet.Identity.UserValidator<wiseowl.Models.ApplicationUser>}

请问大家有什么建议吗?

【问题讨论】:

  • 他们在 dev 和 prod 中使用相同的连接字符串?
  • 还有你为什么不使用await UserManager.FindByEmailAsync,因为你已经在使用TPL(任务)
  • 您是否能够从您的开发环境成功连接到数据库?挂在那条线上很可能是由于与数据库服务器的连接缓慢/失败。

标签: c# asp.net-mvc asp.net-identity-2


【解决方案1】:

到目前为止,测试环境中的挂起看起来像是异步调用和阻塞调用的混合,这可能导致死锁。 FindByEmail 是一个扩展方法,它封装了 UserManager.FindByEmailAsync 的异步 API 调用。

UserManagerExtensions.cs 中找到的那个版本的源代码显示异步调用正在同步执行。

/// <summary>
///     Find a user by email
/// </summary>
/// <param name="manager"></param>
/// <param name="email"></param>
/// <returns></returns>
public static TUser FindByEmail<TUser, TKey>(this UserManager<TUser, TKey> manager, string email)
    where TKey : IEquatable<TKey>
    where TUser : class, IUser<TKey>
{
    if (manager == null)
    {
        throw new ArgumentNullException("manager");
    }
    return AsyncHelper.RunSync(() => manager.FindByEmailAsync(email));
}

我相信在测试环境中运行时会导致死锁(挂起)。没有解释为什么它仍然在现场环境中工作。

我建议按照预期通过FindByEmailAsync 方法使代码一直异步。尽量避免混合使用异步调用和阻塞调用。

public async Task<ActionResult> Login(vmAccountLogin model, string ReturnUrl) {
    // if problems with model, just redisplay form
    if (!ModelState.IsValid) {
        return View(model);
    }

    // hangs on this line
    var user = await UserManager.FindByEmailAsync(model.Email);

    // if user not found for this email, abort with no clues
    if (user == null)

    //...code removed for brevity

除此之外,我还建议确保测试环境为身份数据存储使用正确的连接字符串。因为挂起也可能是由于它等待连接到数据库时超时。

【讨论】:

  • 天啊。我在开发版本的 web.config 文件中缺少连接字符串。我假设因为它连接到 SQL Server 实例上的其他数据库,所以它也连接到 AspNetUsers 表。我一定有一段时间删除了这条线,因为它以前工作过。让我感到困惑的是挂起 - 今天我等了足够长的时间才看到出现 SQL Server 连接错误消息。我已经接受了 Nkosi 的回答(我在发布问题之前确实尝试了异步调用的想法,并且没有任何区别),因为它引发了我的想法。真是个白痴……
  • @AndyBrown 不用担心。我过去也遇到过同样的问题。它的所有部分。哈哈。很高兴这有助于解决您的问题。
猜你喜欢
  • 2010-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-26
相关资源
最近更新 更多