question

osyris-3187 avatar image
0 Votes"
osyris-3187 asked AgaveJoe commented

where and how to put custom Function on startup

I want to create a Admin Seeder that seeds the user and Roles on startup
I have create that function but where do i put it?

In Net 5 i Remember i put my function requirements in the Configure
and than call the function in the Configure section:

example:

 public void Configure(IApplicationBuilder app, IWebHostEnvironment env,
             UserManager<ApplicationUser> userManager,
             RoleManager<ApplicationRole> roleManager)
    
 UserAndRoleSeeder.SeedRoles(roleManager);
             UserAndRoleSeeder.SeedUsers(userManager);

I know there is a Override Function on the ApplicationDbContext
but i want that function to start everytime the website starts up not when the database is created



dotnet-aspnet-core-generaldotnet-aspnet-generaldotnet-aspnet-core-webapidotnet-aspnet-core-auth
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

AgaveJoe avatar image
0 Votes"
AgaveJoe answered AgaveJoe edited

The pattern JaliyaUdagedara shared above takes advantage of an extension method. This is a very typically pattern going back to the beginning of Core. Your code is not well designed for Core start up. Plus it expects a role and usermanger service instance.

I recommend going through any of the getting tutorials in the official documentation as they all cover seeding data. The official documentation also illustrates how to instantiate a service within the seed extension method. Follow the same pattern to get the role and usermanager services.

Seed the database
Initialize DB with test data

This is the pattern I use.

 var builder = WebApplication.CreateBuilder(args);
    
 // Add services to the container.
 builder.Services.AddRazorPages();
    
    
 builder.Services.AddDbContext<RazorPagesMovieContext>(options =>
        options.UseSqlite(builder.Configuration.GetConnectionString("RazorPagesMovieContext")));
    
 var app = builder.Build();
    
 using (var scope = app.Services.CreateScope())
 {
     var services = scope.ServiceProvider;
    
     SeedData.Initialize(services);
 }

....

 public static class SeedData
 {
     public static void Initialize(IServiceProvider serviceProvider)
     {
         using (var context = new RazorPagesMovieContext(
             serviceProvider.GetRequiredService<
                 DbContextOptions<RazorPagesMovieContext>>()))
         {

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

JaliyaUdagedara avatar image
0 Votes"
JaliyaUdagedara answered JaliyaUdagedara edited

I believe you are trying to achieve this for a .NET 6 appication. (since you mentioned .NET 5).

You can do something like below,

 public static class WebAplicationExtensions
 {
     public static WebApplication SeedData(this WebApplication webApplication)
     {
         IServiceScopeFactory scopedFactory = webApplication.Services.GetRequiredService<IServiceScopeFactory>();
    
         using IServiceScope scope = scopedFactory.CreateScope();
    
         using MyDbContext dbContext = scope.ServiceProvider.GetService<MyDbContext>();
         // TODO: Use dbContext to seed your data
    
         return webApplication;
     }
 }

And in the Program.cs,

 WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
    
 builder.Services.AddDbContext<MyDbContext>(options =>
      options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
    
 await using WebApplication app = builder.Build();

 // Other code
    
 await app
     .SeedData()
     .RunAsync();
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Bruce-SqlWork avatar image
0 Votes"
Bruce-SqlWork answered Bruce-SqlWork edited

In program.cs. In the old version it was before defining services, so that would be a good sport, or you could do after defining services. Anywhere you like before app.Run()

 var builder = WebApplication.CreateBuilder(args);
    
    
 // here is where you did it before
    
 // Add services to the container.
 builder.Services.AddRazorPages();
    
 // here is another logical spot
    
 var app = builder.Build();
    
 // Configure the HTTP request pipeline.
 if (!app.Environment.IsDevelopment())
 {
     app.UseExceptionHandler("/Error");
     // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
     app.UseHsts();
 }
    
 app.UseHttpsRedirection();
 app.UseStaticFiles();
    
 app.UseRouting();
    
 app.UseAuthorization();
    
 app.MapRazorPages();
    
 app.Run();
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

osyris-3187 avatar image
0 Votes"
osyris-3187 answered

Thanks for the replys, but how do I use my Code and put it into that place
My Admin seeder :


     public class AdminSeeder
     {
         public static void SeedRoles(RoleManager<ApplicationRole> roleManager)
         {
             if (!roleManager.RoleExistsAsync("Admin").Result)
             {
                 var AdminRole = new ApplicationRole();
                 AdminRole.Name = "Admin";
                 AdminRole.Description = "Founder of the company";
    
                 roleManager.CreateAsync(AdminRole).Wait();
             }
    
             if (!roleManager.RoleExistsAsync("Manager").Result)
             {
                 var ManageRole = new ApplicationRole();
                 ManageRole.Name = "Manager";
                 ManageRole.Description = "Leads the employees";
    
                 roleManager.CreateAsync(ManageRole).Wait();
             }
         }
    
         public static void SeedUsers(UserManager<ApplicationUser> userManager)
         {
             if(userManager.FindByEmailAsync("Info@Admin.com").Result == null)
             {
                 var Admin = new ApplicationUser();
                 Admin.Email = "Info@Admin.com";
                 Admin.FirstName = "Johnson";
                 Admin.LastName = "Brown";
                 Admin.UserName = "Admin";
                 Admin.EmailConfirmed = true;
    
                 var result = userManager.CreateAsync(Admin, "Admin_@123").Result;
    
                 if (result.Succeeded)
                     userManager.AddToRoleAsync(Admin, "Admin").Wait();
             }
    
             if (userManager.FindByEmailAsync("Info@Manager.com").Result == null)
             {
                 var Manager = new ApplicationUser();
                 Manager.Email = "Info@Manager.com";
                 Manager.FirstName = "Eric";
                 Manager.LastName = "Smith";
                 Manager.UserName = "Manager";
                 Manager.EmailConfirmed = true;
    
                 var result = userManager.CreateAsync(Manager, "Admin_@123").Result;
    
                 if (result.Succeeded)
                     userManager.AddToRoleAsync(Manager, "Admin").Wait();
             }
         }
    
            
     }
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

osyris-3187 avatar image
0 Votes"
osyris-3187 answered AgaveJoe commented

Thank you for the helpfull Articles
I have managed to seed the database:

  public static class SeedAdmin 
     {
         public static async void Initialize(IServiceProvider serviceProvider)
         {
             using (var _dbcontext = new ApplicationDbContext(serviceProvider
                 .GetRequiredService<DbContextOptions<ApplicationDbContext>>()))
             {
    
                 var findAdmin = await _dbcontext.Users.FirstOrDefaultAsync(x => x.Email == "Info@Admin.com");
                 if (findAdmin != null)
                     return;
    
                 var Admin = new ApplicationUser();
                 Admin.Email = "Info@Admin.com";
                 Admin.FirstName = "Johnson";
                 Admin.LastName = "Brown";
                 Admin.UserName = "Admin";
                 Admin.EmailConfirmed = true;
    
                 _dbcontext.Users.Add(Admin);
                 await _dbcontext.SaveChangesAsync();
             }
    
         }
     }


But I would like to implement the UserManager and the RoleManager.
I have tried serveral ways and i have lookup up other related topics but i could not
figure out on how to achive this.

Some help with be well appreciated

· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

The pattern is exactly the same for role and user manager. But the role and user manger must have been added to the DI container.

 var userManager = scope.ServiceProvider.GetService<UserManager<ApplicationUser>>();
0 Votes 0 ·