C# CreateUserIdentityAsync返回“;“找不到用户ID”;自定义标识用户的例外情况

C# CreateUserIdentityAsync返回“;“找不到用户ID”;自定义标识用户的例外情况,c#,asp.net,asp.net-web-api,asp.net-identity,C#,Asp.net,Asp.net Web Api,Asp.net Identity,我将跟随JWT创建基于身份和角色的声明。我的应用程序用户是具有int PK的自定义用户表 当前,GenerateUserIdentityAsync方法只返回一个奇怪的找不到用户ID错误。这是我的密码: ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, "JWT"); 以及用户实体中的实现: public async Task<ClaimsIdentity> Generat

我将跟随JWT创建基于身份和角色的声明。我的应用程序用户是具有int PK的自定义用户表

当前,GenerateUserIdentityAsync方法只返回一个奇怪的
找不到用户ID
错误。这是我的密码:

ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, "JWT");
以及
用户
实体中的实现:

public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<User, int> manager, string authenticationType)
{
    //error on this line: CreateIdentityAsync throws error
    var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
    return userIdentity;
}
(对我)不是很有帮助吗

如何找出用户ID不可用的原因/位置?


模式详情:

My
GrantResourceOwnerCredentials()


正如您在调试
IdentityUser
时发现的,在您的情况下,它有一个
Id
,表示用户的Id

您需要从
User
类中删除
UserId
,使用
IdentityUser
中的基
Id
,并将自定义用户表中的
UserId
列重命名为
Id

User
类中的任何属性都需要在数据库的用户表中有一个匹配的列。如果不是,那么对于不匹配的属性,您将得到相同的错误


这意味着
AspNetUsers
表中的
Fullname
Address
ContactNumber
必须具有匹配的列名,否则这些属性也会出现相同的错误。

您的ApplicationUser类看起来像什么? 这个方法在您的应用程序中是什么样子的

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context){}
Taiseer对GrantResourceOwnerCredentials的评论如下:

“我们正在为登录用户生成一个标识,即此标识 将包含已验证用户的所有角色和声明“

我必须将ClaimTypes.NameIdentifier添加到ClaimSideEntity以解决类似的问题。以下是我的GrantResourceOwnerCredentials方法的重要部分:

ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);

if (user == null)
{
    context.SetError("invalid_grant", "The user name or password is incorrect.");
    return;
}

var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()));

您在
User
类中既有
UserId
又有
Id
属性-
Id
继承自
IdentityUser
。问题是您可能将
UserId
配置为
User
的主键

UserManager.GetSecurityStampAsync
上的
ClaimsIdentityFactory.CreateAsync
方法中会引发异常。如您所见,
user.Id
用于检索安全戳

如果查看
UserManager.GetSecurityStampAsync
中的内容,您将看到您得到的异常正是在这里抛出的:

public virtual async Task<string> GetSecurityStampAsync(TKey userId)
{
    ThrowIfDisposed();
    var securityStore = GetSecurityStore();
    var user = await FindByIdAsync(userId).WithCurrentCulture();
    if (user == null)
    {
        throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound,
            userId));
    }
    return await securityStore.GetSecurityStampAsync(user).WithCurrentCulture();
}
公共虚拟异步任务GetSecurityStampAsync(TKey用户ID)
{
ThrowIfDisposed();
var securityStore=GetSecurityStore();
var user=wait FindByIdAsync(userId).WithCurrentCulture();
if(user==null)
{
抛出新的InvalidOperationException(String.Format(CultureInfo.CurrentCulture,Resources.UserIdNotFound,
用户ID);
}
返回wait-wait-securityStore.GetSecurityStampAsync(用户).WithCurrentCulture();
}

因此,从
User
类中删除
UserId
属性,并开始使用
Id
(继承自
IdentityUser

我面临着完全相同的问题。经过一阵头痛之后,我可以解决真正的问题了。 将User类的Id属性的数据类型更改为string时,会在构造函数中将Guid().ToString()分配给Id属性,并将相同的值保存到数据库中,Identity使用该值检索用户详细信息

但是,如果您将Id属性的数据类型更改为int,并且没有在构造函数中为该属性提供值,则标识仍会尝试使用默认int值(0)检索用户详细信息,这将导致抛出消息“System.InvalidOperationException:UserId not found”

我通过command.ExecuteScalar()从数据库中检索值并将值分配给user.Id解决了这个问题。
希望这能帮助一些面临类似问题的人。

Server=xxxx;初始目录=xxxx用户ID=xxxx\u用户;密码=xxxx;其中用户id中有一个空格,而不是 服务器=xxxx;初始目录=xxxxUserID=xxxx\u用户;密码=xxxx;错了!!!!!!!
请参阅以获得确认。

在我的例子中,发生此错误是因为我在帐户控制器的方法登录中添加了另一个SignInManager(下面是添加角色的示例)。它在同一个方法中执行SignInManager.PasswordSignInAsync和SignInManager.SignInAsync,并在ApplicationUser中两次调用GenerateUserIdentityAsync(…),第一次调用成功,第二次调用给我找不到异常“UserId”。

在您的aspnet db中验证您是否有正确的列名(UserId而不是Id,反之亦然)。还有一种可能是列类型不匹配(uniqueidentifiers与nvarchar(256))不匹配.Hi,在上面添加了两个代码块;您没有使用JWT?我用
DefaultAuthenticationTypes.applicationOkie
尝试了它,但仍然是相同的错误,我想我至少现在可以排除JWT干扰它。正确的,我没有使用JWT.Hi,我做了这些更改,但仍然遇到相同的错误;我现在怀疑
UserId
就是我所认为的,没有内部异常,只有堆栈跟踪,但不幸的是,这没有多大帮助。上面的代码拉了用户两次,这不是一个问题,如果它能工作,我可以稍后重构,但它仍然抛出完全相同的代码exception@LocustHorde,我回到绘图板,重新检查了您的问题。使用添加您提供的传统信息使我能够重新创建相同的异常,包括内部异常。
UserId
必须是
AspNetUsers
表中的有效列。我想以前的评论员也指出了这一点。太好了!在您的评论之后,我注意到有两个
UserId
Id
“按表”和“我的种子”中的列
public partial class User : IdentityUser<int, CustomUserLogin, CustomUserRole, CustomUserClaim>
{  
    public int UserId { get; set; }
    public string Fullname { get; set; }
    public string Address { get; set; }
    public string ContactNumber { get; set; }
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context){}
ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);

if (user == null)
{
    context.SetError("invalid_grant", "The user name or password is incorrect.");
    return;
}

var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()));
public virtual async Task<string> GetSecurityStampAsync(TKey userId)
{
    ThrowIfDisposed();
    var securityStore = GetSecurityStore();
    var user = await FindByIdAsync(userId).WithCurrentCulture();
    if (user == null)
    {
        throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound,
            userId));
    }
    return await securityStore.GetSecurityStampAsync(user).WithCurrentCulture();
}