Reputation: 5724
I have the following function:
public async Task<List<UserViewModel>> Get(string role, string nameText, int offset, int number) {
List<User> users = new List<User>();
if (role != "") {
new List<User>(await userManager.GetUsersForClaimAsync(new System.Security.Claims.Claim("role", role)));
}
List<Task<UserViewModel>> data = users
.Skip(offset)
.Take(number)
.Select(async (user) => {
return await identityUserToUserViewModel(user); ;
}).ToList();
return data;
}
which calls
async Task<UserViewModel> identityUserToUserViewModel(User user) {
var principal = await userManager.GetClaimsAsync(user);
return new UserViewModel()
{
Email = user.Email,
PhoneNumber = user.PhoneNumber,
Location = locationRepository.GetForUser(user.Id),
Name = user.Name,
Role = principal.Where(Claim => Claim.Type == "role").ToList().FirstOrDefault().Value,
sub = user.Id
};
}
However, this function gives an error of
Cannot implicitly convert type 'System.Collections.Generic.List<System.Threading.Tasks.Task<Models.ViewModel.UserViewModel>>' to 'System.Collections.Generic.List<Models.ViewModel.UserViewModel>'
I understand that the async lambda is converting it back into a task, but I can't figure out how to -not- have that happen.
Upvotes: 2
Views: 6777
Reputation: 3607
Due to the following code returns a Task<UserViewModel>
for each call
.Select(async (user) => {
return await identityUserToUserViewModel(user);
You could wrap the LINQ expression with await Task.WhenAll(...)
this returns an array of UserViewModel
that can be converted to a List<UserViewModel>
Upvotes: 0
Reputation: 388333
.Select(async (user) => {
return await identityUserToUserViewModel(user);
})
Because making something async
actually means that the result gets wrapped in a Task
, this actually has the same result as the following:
.Select((user) => {
return identityUserToUserViewModel(user);
})
So the result of that call is an IEnumerable<Task<UserViewModel>>
. So converting it to a list will give you a list of tasks, not a list of UserViewModels.
If you now want to await all those tasks and just return a list of view models, then you can use Task.WhenAll
. It will await all the tasks it gets passed, and fortunately return an array of all the tasks’ results:
IEnumerable<Task<UserViewModel>> dataTasks = users
.Skip(offset)
.Take(number)
.Select(identityUserToUserViewModel);
UserViewModel[] data = Task.WhenAll(dataTasks);
return data;
Upvotes: 3