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

IUserStore<TUser>.CreateAsync : how to indicate failure in custom implementation?

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

public async virtual Task CreateAsync(TUser user)

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

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

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

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

有什么想法吗?

答案是 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;
    }

所以基本上他们总是 return 正确。这意味着在当前版本中,将我的创建检查放在 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中就可以了。在我看来,这将是一种更好的设计方式,因为客户不必处理完整性问题。

查看 source code for UserManager.CreateAsync(这是针对 Identity 2.0),您可以看到在调用 IUserStore.CreateAsync 之前,它会调用 IIdentityValidator<TUser>.ValidateAsync,它实际上负责 return 相关 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 实例上。