简体   繁体   中英

How to get all users async, with AspNetCore.Identity and MongoDb?

This question asks about how to retrieve all users from AspNetCore Identity, in an async method:

ASP.NET Identity 2 UserManager get all users async

The non-sync method is simple:

[HttpGet]
public ActionResult<IEnumerable<UserDto>> GetAsync()
{
    var users = userManager.Users
        .ToList()
        .Select(user => user.AsDto());
    return Ok(users);
}

The obvious solution is this:

[HttpGet]
public async Task<ActionResult<IEnumerable<UserDto>>> GetAsync()
{
    var users = await userManager.Users
        .ToListAsync()
        .Select(user => user.AsDto());
    return Ok(users);
}

But this doesn't work because userManager.Users is an IQueryable<>, and that doesn't define a.ToListAsync().

The recommended answer in the question above is:

public async Task<List<User>> GetUsersAsync()
{
    using (var context = new YourContext())
    {
        return await UserManager.Users.ToListAsync();
    }
}

But that is tied to Entity Framework, and if you're using AspNetCore.Identity.MongoDbCore, you won't have any dbcontexts, and the above simply doesn't work.

One comment on the answer points out that the.ToListAsync() extension method is defined in System.Data.Entity - but if you're using MongoDb you won't be including that.

How, actually, do you access all users from UserManager<> in an async method?

Basiccally, AspNetCore.Identity.MongoDbCore was just implementation wrapping around core concept of AspNetCore.Identity . And things gone just a bit difference from Sql implementation, cause they doesn't make use of unit of work concept (I know, SaveChange implement would wrap operation in transaction, but for everymethod call, the query execute immediately got this pretty similar to mongo in someway).

Then, If we need any furthur extension of those basic task, why don't just write our own implementation on top of default MongoDbCore implementation like good old days?

// Starting with UserStore
public class ApplicationUserStore : MongoUserStore<How many generic would depend on use cases>, IApplicationUserStore
{
    protected IMongoCollection<TUser> ApplicationUsersCollection;
    public ApplicationUserStore(ApplicationDbContext context, IdentityErrorDescriber describer = null) : base(context, describer)
    {
        ApplicationUsersCollection = Context.GetCollection<TUser>();
    }

    public async Task<ICollection<ApplicationUser>> GetAllUserAsync() => // We have access to UsersCollection, implement as normal mongodb operation;
}

// Then, UserManager
public class ApplicationUserManager : UserManager<How many generic would depend on use cases>
{
    private readonly IApplicationUserStore _applicationUserStore;

    // Constructtor that could resolve our ApplicationUserStore.
    public ApplicationUserManager(IApplicationUserStore applicationUserStore,...)
    {
        _applicationUserStore = applicationUserStore;
    }

    public async Task<ICollection<ApplicationUser>> GetAllUserAsync() => _applicationUserStore.GetAllUserAsync();

// Registering things
services.AddScoped<IApplicationUserStore, ApplicationUserStore>();
services.AddScoped<ApplicationUserManager>();
}

This was just describe the idea, implementation should be vary.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM