IUserStore <tuser> .CreateAsync:如何在自定义实现中指示失败?

时间:2015-10-03 21:16:05

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

我正在为IUserStore编写一个自定义实现。 create方法的签名是:

public async virtual Task CreateAsync(TUser user)

考虑到Microsoft.AspNet.Identity中的核心接口IUserStore(这是相同的),这是有道理的。

但是,Microsoft.AspNet.Identity中定义的UserManager类的接口是:

public virtual Task<IdentityResult> CreateAsync(TUser user);

我的问题是我不知道如何将此IdentityResult传递给UserManager,因为商店中的返回类型只是&#34;任务&#34;。我有一个自定义逻辑来确定是否可以创建用户,所以我真的需要将CreateAsync的结果告诉UserManager。

有什么想法吗?

2 个答案:

答案 0 :(得分:4)

查看source code for UserManager.CreateAsync(这是针对Identity 2.0),您可以看到在调用IUserStore.CreateAsync之前,它会调用IIdentityValidator<TUser>.ValidateAsync,它负责实际返回相关内容IdentityResult对象:

public virtual async Task<IdentityResult> CreateAsync(TUser user)
{
        ThrowIfDisposed();
        await UpdateSecurityStampInternal(user).ConfigureAwait(false);
        var result = await UserValidator.ValidateAsync(user).ConfigureAwait(false);
        if (!result.Succeeded)
        {
            return result;
        }
        if (UserLockoutEnabledByDefault && SupportsUserLockout)
        {
            await GetUserLockoutStore().SetLockoutEnabledAsync(user, true).ConfigureAwait(false);
        }
        await Store.CreateAsync(user).ConfigureAwait(false);
        return IdentityResult.Success;
}

IUserStore.CreateAsync的主要目的是调用保存数据的基础数据源。您似乎实际上想要实施IIdentityValidator<TUser>并将其设置在UserManager实例上。

答案 1 :(得分:2)

答案是in the source code,这是撰写本文时UserManager中实现的一部分:

public virtual async Task<IdentityResult> CreateAsync(TUser user,
        CancellationToken cancellationToken = default(CancellationToken))
    {
        ThrowIfDisposed();
        await UpdateSecurityStampInternal(user, cancellationToken);
        var result = await ValidateUserInternal(user, cancellationToken);
        if (!result.Succeeded)
        {
            return result;
        }
        if (Options.Lockout.EnabledByDefault && SupportsUserLockout)
        {
            await GetUserLockoutStore().SetLockoutEnabledAsync(user, true, cancellationToken);
        }
        await UpdateNormalizedUserNameAsync(user, cancellationToken);
        await Store.CreateAsync(user, cancellationToken);
        return IdentityResult.Success;
    }

所以基本上他们总是回归真实。这意味着在当前版本中,将我的创建检查放在UserStore中违背了框架的预期用法。

但是我注意到这将在下一个版本中更改。 IUserStore接口将变为:

Task<IdentityResult> CreateAsync(TUser user, CancellationToken cancellationToken);

UserManager实现:

public virtual async Task<IdentityResult> CreateAsync(TUser user)
    {
        ThrowIfDisposed();
        await UpdateSecurityStampInternal(user);
        var result = await ValidateUserInternal(user);
        if (!result.Succeeded)
        {
            return result;
        }
        if (Options.Lockout.AllowedForNewUsers && SupportsUserLockout)
        {
            await GetUserLockoutStore().SetLockoutEnabledAsync(user, true, CancellationToken);
        }
        await UpdateNormalizedUserNameAsync(user);
        await UpdateNormalizedEmailAsync(user);

        return await Store.CreateAsync(user, CancellationToken);
    }

因此,当时可以将创建逻辑放在UserStore中。在我看来,这将是一种更好的设计,因为客户不应该处理完整性问题。