Search code examples
c#asp.net-coreasp.net-identity

The Task is cancelled When adding a user to a role that exists


At the present I am trying to assign a role to a user the role table looks like following

Role Id Name NormalizedName
59f5238-818e-40f9-b95a-fc65db67f253 Parent Parent

My User table is

Id First Name Surname
b3e9d5ec-1ddf-4e57-bf00-1afc2e7f0582 Parent One

The role is also being created fine.

enter image description here But for some reason when I try to add this user to the roles table I am getting the following.

The Task is cancelled at Microsoft.AspNetCore.Identity.UserManager`1.d__116.MoveNext() at Web.SampleData.d__2.MoveNext() in SampleData.cs:line 118

I am using the code to add to the role manager the user

public static async Task<IdentityResult> 
           AssignRoles(IServiceProvider services, 
           string email, string[] roles)
{
  IdentityResult result = new IdentityResult();
  UserManager<ApplicationUser> _userManager = 
    services.GetService<UserManager<ApplicationUser>>();
   ApplicationUser user = await 
         _userManager.FindByEmailAsync(email);
   result = await _userManager.AddToRolesAsync(user, roles);            
   return result;
}

The role is being passed as "Parent" and the correct email address of [email protected] so why am I getting a task is canceled?

As you see the above user has not been added to the aspnetuseroles table

enter image description here

This is the complete seeding method

public static void CreateParent(IServiceProvider 
                                serviceProvider)
{
    var context = new DBContext();// 
     serviceProvider.GetService<DBContext>();
      string[] roles = new string[] { "Parent" };
      foreach (string role in roles)
      {
        var roleStore = new RoleStore<IdentityRole>(context);
        if (!context.Roles.Any(r => r.Name == role))
           {
             roleStore.CreateAsync(new IdentityRole(role));
            }
        }
        
        var user = new ApplicationUser
        {
            FirstName = "Parent",
            LastName = "One",
            Email = "[email protected]",
            NormalizedEmail = "[email protected]",
            UserName = "[email protected]",
            NormalizedUserName = "[email protected]",
            PhoneNumber = "+111111111111",
            EmailConfirmed = true,
            PhoneNumberConfirmed = true,
            SecurityStamp = Guid.NewGuid().ToString("D")
        };

        var db = new DBContext();
        if (!db.Users.Any(u => u.UserName == user.UserName))
        {
            var password = new PasswordHasher<ApplicationUser>);
            var hashed = password.HashPassword(user,2 
                          Test12345!");
            user.PasswordHash = hashed;
            var userStore = new UserStore<ApplicationUser> 
            (context);
            var result = userStore.CreateAsync(user);

        }

        AssignRoles(serviceProvider, user.Email, roles);
        db.SaveChangesAsync();
    }

I call it from my web app startup.cs as such

public void Configure(IApplicationBuilder app, 
   IWebHostEnvironment env,IServiceProvider service)
{
        SampleData.CreateParent(service);

}

Solution

  • The reason why it is getting Cancelled is that you have an asynchronous call that you haven't actually added await to them.

    You have async methods in your CreateParent function so you need to set it as

    public async Task CreateParent()
    

    and you need to add await on

    await roleStore.CreateAsync(new IdentityRole(role));
    await db.SaveChangesAsync();
    
    public async Task Configure(IApplicationBuilder app, 
       IWebHostEnvironment env,IServiceProvider service)
    {
            await SampleData.CreateParent(service);
    }
    

    I suggest you add it in the Program.cs

    public class Program
        {
            public static async Task Main(string[] args)
            {
                new ConfigurationBuilder()
                        .SetBasePath(Directory.GetCurrentDirectory())
                        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                        .AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
                        .AddEnvironmentVariables()
                        .Build();
    
                var host = await CreateHostBuilder(args).Build().MigrateAndSeedDataAsync();
    
                await host.RunAsync();
            }
    
            public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                        webBuilder.UseStartup<Startup>();
                    }).UseDefaultServiceProvider(options => options.ValidateScopes = false);
        }