【问题标题】:MVC - InvalidOperationException: UserId not foundMVC - InvalidOperationException:找不到用户 ID
【发布时间】:2016-07-07 13:11:10
【问题描述】:

当我使用以下代码注册用户时:

// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = new ApplicationUser() { UserName = model.UserName };

        IdentityResult result = await UserManager.CreateAsync(user, model.Password);

        if (result.Succeeded)
        {
            await SignInAsync(user, isPersistent: false);
            return RedirectToAction("Index", "Home");
        }
        else
        {
            AddErrors(result);
        }

        return View(model);
    }
}

我可以使用 [Authorize] 属性访问所有视图。 但是,如果我使用同一用户注销并重新登录,则会收到一个错误页面,其中包含

“InvalidOperationException:找不到用户 ID”

错误似乎来自我在声明中的 SignInAsync 函数:

var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);

我没有添加用户 ID,并且用户类(其 ID)或 AspNetUsers 表中没有用户 ID 字段。 该用户存在于该表中,但同样没有 UserId。

我已尝试清除 cookie 等,但仍然无法重新登录。 我是不是注册错了?我不明白为什么当 UserId 字段似乎不存在时,身份验证会寻找它

编辑: 当我第一次登录时...我得到错误页面。但是,当我重新打开页面并读取 cookie 时,我可以访问所有内容。初次登录到底发生了什么?

这里是 SignInAsync 方法:

 private async Task SignInAsync(ApplicationUser user, bool isPersistent)
        {
            AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
            var _identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);

            AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, _identity);
        }

包含

 public class ApplicationUser : IdentityUser
    {
        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
        {
            // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
            // Add custom user claims here
            return userIdentity;
        }
    }

【问题讨论】:

  • 你能分享你的用户模型吗?
  • 用户是一个IPrinicipal实现。我认为它已经融入其中。用户对象是一个 IdentityUser
  • 你能告诉我们方法 SignInAsync(user, isPersistent: false); 的实现吗?
  • 已添加。谢谢大家的帮助
  • @rigamonk - 你展示了两个不同的CreateIdentityAsync。你指的是哪一个?您还应该展示您的ApplicationUser 的外观,因为它可能与stackoverflow.com/a/35017046/5233410 有关。

标签: asp.net-mvc authentication


【解决方案1】:

编辑:我错了你提到 Dapper,所以 Dapper 特定的细节不相关,但修复的总体思路仍然存在 - 你的 Id 和 UserId 列可能没有正确匹配。


我昨天遇到了这个确切的错误。我想您之前提到过您使用 Dapper 作为数据访问机制。我认为这可能是相关的,因为您还提到该表有一个 Userid 字段,但您的用户类有一个 Id 属性。我猜您可能还有一些代码可以将新的Guid 分配给Id 属性,如果那里没有的话。像这样的:

public ApplicationUser()
{
    Id = Guid.NewGuid().ToString();
}

这与 Dapper 映射的工作方式相结合可能会让您感到困惑,因为 Id 字段最终会使用新的 Guid 而不是它应该从表中读取的那个。

在下面的示例中,Dapper 无法分配 ApplicationUser 的 Id 字段,因为 DB 字段的名称与类的属性不同。但它已经从其构造函数中获得了一个 Id 值。这会导致以后对FindByIdAsync() 和朋友的调用失败。

public async Task<ApplicationUser> FindByNameAsync(string userName)
{
    ApplicationUser result = null;

    using (var conn = await GetOpenDBConnection())
    {
        try
        {
            // this query is bugged with Dapper because UserId does not
            // exist on ApplicationUser.
            var queryResults = await conn.QueryAsync<ApplicationUser>(
                "SELECT UserId, UserName, Email FROM dbo.Users WHERE UserName = @UserName;",
                new { UserName = userName });

            result = queryResults.FirstOrDefault();
        }
        catch (Exception ex)
        {
                            //handle error appropriately.
            result = null;
        }
    }

    return result;
}

如果实际上是 Dapper 映射问题,您可以重命名查询结果中的字段,例如 SELECT UserId as [Id], UserName, Email FROM dbo.Users WHERE UserName = @UserName,或者参阅 Randall Stutton's answer 了解如何以非常干净的方式映射 Dapper 字段。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-24
    • 2012-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-13
    相关资源
    最近更新 更多