From 760ea09f83bbe54aa5565580fb59fabd4e63dafa Mon Sep 17 00:00:00 2001 From: Hesam Asnaashari <46031836+ilhesam@users.noreply.github.com> Date: Fri, 20 Jan 2023 10:15:56 +0330 Subject: [PATCH] refac - remove build service provider --- src/Common/uBeac.Core.Common/IDataSeeder.cs | 6 ++ src/Examples/Identity.MongoDB.API/Program.cs | 2 + .../Extensions/RoleExtensions.cs | 59 ++++------------ .../Extensions/UnitExtensions.cs | 67 +++++-------------- .../Extensions/UnitTypeExtensions.cs | 54 ++++----------- .../Extensions/UserExtensions.cs | 55 ++++----------- .../uBeac.Core.Identity/Seeders/RoleSeeder.cs | 38 +++++++++++ .../uBeac.Core.Identity/Seeders/UnitSeeder.cs | 41 ++++++++++++ .../Seeders/UnitTypeSeeder.cs | 38 +++++++++++ .../uBeac.Core.Identity/Seeders/UserSeeder.cs | 46 +++++++++++++ .../uBeac.Core.Logging/AppContextEnricher.cs | 33 --------- .../ApplicationExtensions.cs | 18 ++++- 12 files changed, 241 insertions(+), 216 deletions(-) create mode 100644 src/Common/uBeac.Core.Common/IDataSeeder.cs create mode 100644 src/Identity/uBeac.Core.Identity/Seeders/RoleSeeder.cs create mode 100644 src/Identity/uBeac.Core.Identity/Seeders/UnitSeeder.cs create mode 100644 src/Identity/uBeac.Core.Identity/Seeders/UnitTypeSeeder.cs create mode 100644 src/Identity/uBeac.Core.Identity/Seeders/UserSeeder.cs delete mode 100644 src/Logging/uBeac.Core.Logging/AppContextEnricher.cs diff --git a/src/Common/uBeac.Core.Common/IDataSeeder.cs b/src/Common/uBeac.Core.Common/IDataSeeder.cs new file mode 100644 index 00000000..869a5e24 --- /dev/null +++ b/src/Common/uBeac.Core.Common/IDataSeeder.cs @@ -0,0 +1,6 @@ +namespace uBeac; + +public interface IDataSeeder +{ + Task SeedAsync(CancellationToken cancellationToken = default); +} diff --git a/src/Examples/Identity.MongoDB.API/Program.cs b/src/Examples/Identity.MongoDB.API/Program.cs index 133eca42..00a186e5 100644 --- a/src/Examples/Identity.MongoDB.API/Program.cs +++ b/src/Examples/Identity.MongoDB.API/Program.cs @@ -107,6 +107,8 @@ var app = builder.Build(); +app.SeedData(); + app.UseHttpsRedirection(); app.UseHstsOnProduction(builder.Environment); app.UseCorsPolicy(corsPolicyOptions); diff --git a/src/Identity/uBeac.Core.Identity/Extensions/RoleExtensions.cs b/src/Identity/uBeac.Core.Identity/Extensions/RoleExtensions.cs index 7f38d55e..a60e5189 100644 --- a/src/Identity/uBeac.Core.Identity/Extensions/RoleExtensions.cs +++ b/src/Identity/uBeac.Core.Identity/Extensions/RoleExtensions.cs @@ -1,5 +1,7 @@ using Microsoft.AspNetCore.Identity; +using uBeac; using uBeac.Identity; +using uBeac.Identity.Seeders; namespace Microsoft.Extensions.DependencyInjection; @@ -35,12 +37,10 @@ public static IdentityBuilder AddIdentityRole(this IdentityBuil if (configureOptions is not null) { // Register options - var options = builder.Services.RegisterRoleOptions(configureOptions); + builder.Services.RegisterRoleOptions(configureOptions); // Insert default values - builder.Services.BuildServiceProvider().CreateScope().ServiceProvider - .GetRequiredService>() - .InsertDefaultRoles(options.DefaultValues); + builder.Services.AddScoped>(); } return builder; @@ -49,7 +49,6 @@ public static IdentityBuilder AddIdentityRole(this IdentityBuil public static IdentityBuilder AddIdentityRole(this IdentityBuilder builder, Action> configureOptions = default) where TRole : Role { - // Configure AspNetIdentity builder .AddRoles() @@ -59,12 +58,10 @@ public static IdentityBuilder AddIdentityRole(this IdentityBuilder builde if (configureOptions is not null) { // Register options - var options = builder.Services.RegisterRoleOptions(configureOptions); - + builder.Services.RegisterRoleOptions(configureOptions); + // Insert default values - builder.Services.BuildServiceProvider().CreateScope().ServiceProvider - .GetRequiredService>() - .InsertDefaultRoles(options.DefaultValues); + builder.Services.AddScoped>(); } return builder; @@ -74,12 +71,12 @@ private static RoleOptions RegisterRoleOptions where TRoleKey : IEquatable where TRole : Role { + var options = new RoleOptions(); + configureOptions(options); + // Register IOptions> services.Configure(configureOptions); - // Get RoleOptions<,> from ServiceProvider - var options = services.BuildServiceProvider().GetRequiredService>>().Value; - // Register RoleOptions<,> without IOptions services.AddSingleton>(options); @@ -89,43 +86,15 @@ private static RoleOptions RegisterRoleOptions private static RoleOptions RegisterRoleOptions(this IServiceCollection services, Action> configureOptions) where TRole : Role { + var options = new RoleOptions(); + configureOptions(options); + // Register IOptions> services.Configure(configureOptions); - // Get RoleOptions<,> from ServiceProvider - var options = services.BuildServiceProvider().GetRequiredService>>().Value; - // Register RoleOptions<,> without IOptions services.AddSingleton>(options); return options; } - - private static void InsertDefaultRoles(this IRoleService service, IEnumerable values) - where TRoleKey : IEquatable - where TRole : Role - { - if (values is null || values.Any() is false) return; - foreach (var role in values) - { - try - { - // If role was not inserted before, insert it - if (service.Exists(role.Name).Result is false) - { - service.Create(role).Wait(); - } - } - catch (Exception) - { - // ignored - } - } - } - - private static void InsertDefaultRoles(this IRoleService service, IEnumerable values) - where TRole : Role - { - service.InsertDefaultRoles(values); - } -} \ No newline at end of file +} diff --git a/src/Identity/uBeac.Core.Identity/Extensions/UnitExtensions.cs b/src/Identity/uBeac.Core.Identity/Extensions/UnitExtensions.cs index 79b0ec52..b4f3da87 100644 --- a/src/Identity/uBeac.Core.Identity/Extensions/UnitExtensions.cs +++ b/src/Identity/uBeac.Core.Identity/Extensions/UnitExtensions.cs @@ -1,5 +1,7 @@ using Microsoft.AspNetCore.Identity; +using uBeac; using uBeac.Identity; +using uBeac.Identity.Seeders; namespace Microsoft.Extensions.DependencyInjection; @@ -29,12 +31,10 @@ public static IdentityBuilder AddIdentityUnit(this IdentityBuil if (configureOptions is not null) { // Register options - var options = builder.Services.RegisterUnitOptions(configureOptions); + builder.Services.RegisterUnitOptions(configureOptions); // Insert default values - builder.Services.BuildServiceProvider().CreateScope().ServiceProvider - .GetRequiredService>() - .InsertDefaultUnits(options.DefaultValues); + builder.Services.AddScoped>(); } return builder; @@ -46,12 +46,10 @@ public static IdentityBuilder AddIdentityUnit(this IdentityBuilder builde if (configureOptions is not null) { // Register options - var options = builder.Services.RegisterUnitOptions(configureOptions); + builder.Services.RegisterUnitOptions(configureOptions); // Insert default values - builder.Services.BuildServiceProvider().CreateScope().ServiceProvider - .GetRequiredService>() - .InsertDefaultUnits(options.DefaultValues); + builder.Services.AddScoped>(); } return builder; @@ -61,12 +59,12 @@ private static UnitOptions RegisterUnitOptions where TUnitKey : IEquatable where TUnit : Unit { + var options = new UnitOptions(); + configureOptions(options); + // Register IOptions> services.Configure(configureOptions); - - // Get UnitOptions<,> from ServiceProvider - var options = services.BuildServiceProvider().GetRequiredService>>().Value; - + // Register UnitOptions<,> without IOptions services.AddSingleton>(options); @@ -76,50 +74,15 @@ private static UnitOptions RegisterUnitOptions private static UnitOptions RegisterUnitOptions(this IServiceCollection services, Action> configureOptions) where TUnit : Unit { + var options = new UnitOptions(); + configureOptions(options); + // Register IOptions> services.Configure(configureOptions); - - // Get UnitOptions<,> from ServiceProvider - var options = services.BuildServiceProvider().GetRequiredService>>().Value; - + // Register UnitOptions<,> without IOptions services.AddSingleton>(options); return options; } - - private static void InsertDefaultUnits(this IUnitService service, IEnumerable values) - where TUnitKey : IEquatable - where TUnit : Unit - { - if (values is null || values.Any() is false) return; - - // Insert default values - foreach (var unit in values) - { - try - { - // If unit was not inserted before, insert it - if (service.Exists(unit.Code, unit.Type).Result is false) - { - // Set parent id - var parent = unit.GetParentUnit(); - if (parent != null) unit.ParentUnitId = parent.Id; - - // Insert - service.Create(unit).Wait(); - } - } - catch (Exception) - { - // ignored - } - } - } - - private static void InsertDefaultUnits(this IUnitService service, IEnumerable values) - where TUnit : Unit - { - service.InsertDefaultUnits(values); - } -} \ No newline at end of file +} diff --git a/src/Identity/uBeac.Core.Identity/Extensions/UnitTypeExtensions.cs b/src/Identity/uBeac.Core.Identity/Extensions/UnitTypeExtensions.cs index 7e74861d..0fad25ee 100644 --- a/src/Identity/uBeac.Core.Identity/Extensions/UnitTypeExtensions.cs +++ b/src/Identity/uBeac.Core.Identity/Extensions/UnitTypeExtensions.cs @@ -1,5 +1,7 @@ using Microsoft.AspNetCore.Identity; +using uBeac; using uBeac.Identity; +using uBeac.Identity.Seeders; namespace Microsoft.Extensions.DependencyInjection; @@ -29,12 +31,10 @@ public static IdentityBuilder AddIdentityUnitType(this if (configureOptions is not null) { // Register options - var options = builder.Services.RegisterUnitTypeOptions(configureOptions); + builder.Services.RegisterUnitTypeOptions(configureOptions); // Insert default values - builder.Services.BuildServiceProvider().CreateScope().ServiceProvider - .GetRequiredService>() - .InsertDefaultUnitTypes(options.DefaultValues); + builder.Services.AddScoped>(); } return builder; @@ -46,12 +46,10 @@ public static IdentityBuilder AddIdentityUnitType(this IdentityBuilde if (configureOptions is not null) { // Register options - var options = builder.Services.RegisterUnitTypeOptions(configureOptions); + builder.Services.RegisterUnitTypeOptions(configureOptions); // Insert default values - builder.Services.BuildServiceProvider().CreateScope().ServiceProvider - .GetRequiredService>() - .InsertDefaultUnitTypes(options.DefaultValues); + builder.Services.AddScoped>(); } return builder; @@ -61,12 +59,12 @@ private static UnitTypeOptions RegisterUnitTypeOptions< where TUnitTypeKey : IEquatable where TUnitType : UnitType { + var options = new UnitTypeOptions(); + configureOptions(options); + // Register IOptions> services.Configure(configureOptions); - // Get UnitTypeOptions<,> from ServiceProvider - var options = services.BuildServiceProvider().GetRequiredService>>().Value; - // Register UnitTypeOptions<,> without IOptions services.AddSingleton>(options); @@ -76,43 +74,15 @@ private static UnitTypeOptions RegisterUnitTypeOptions< private static UnitTypeOptions RegisterUnitTypeOptions(this IServiceCollection services, Action> configureOptions) where TUnitType : UnitType { + var options = new UnitTypeOptions(); + configureOptions(options); + // Register IOptions> services.Configure(configureOptions); - // Get UnitTypeOptions<,> from ServiceProvider - var options = services.BuildServiceProvider().GetRequiredService>>().Value; - // Register UnitTypeOptions<,> without IOptions services.AddSingleton>(options); return options; } - - private static void InsertDefaultUnitTypes(this IUnitTypeService service, IEnumerable values) - where TUnitTypeKey : IEquatable - where TUnitType : UnitType - { - if (values is null || values.Any() is false) return; - foreach (var unitType in values) - { - try - { - // If unit type was not inserted before, insert it - if (service.Exists(unitType.Code).Result is false) - { - service.Create(unitType).Wait(); - } - } - catch (Exception) - { - // ignored - } - } - } - - private static void InsertDefaultUnitTypes(this IUnitTypeService service, IEnumerable values) - where TUnitType : UnitType - { - service.InsertDefaultUnitTypes(values); - } } \ No newline at end of file diff --git a/src/Identity/uBeac.Core.Identity/Extensions/UserExtensions.cs b/src/Identity/uBeac.Core.Identity/Extensions/UserExtensions.cs index 7bec7ede..24f75e33 100644 --- a/src/Identity/uBeac.Core.Identity/Extensions/UserExtensions.cs +++ b/src/Identity/uBeac.Core.Identity/Extensions/UserExtensions.cs @@ -1,6 +1,8 @@ using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Configuration; +using uBeac; using uBeac.Identity; +using uBeac.Identity.Seeders; namespace Microsoft.Extensions.DependencyInjection; @@ -39,13 +41,10 @@ public static IdentityBuilder AddIdentityUser(this IServiceColl if (configureOptions is not null) { // Register options - var options = builder.Services.RegisterUserOptions(configureOptions); + builder.Services.RegisterUserOptions(configureOptions); // Insert default values - var scope = builder.Services.BuildServiceProvider().CreateScope(); - var userService = scope.ServiceProvider.GetRequiredService>(); - var userRoleService = scope.ServiceProvider.GetRequiredService>(); - userService.InsertAdminUserAndAssignRole(userRoleService, options.AdminRole, options.AdminUser, options.AdminPassword); + builder.Services.AddScoped>(); } return builder; @@ -65,13 +64,10 @@ public static IdentityBuilder AddIdentityUser(this IServiceCollection ser if (configureOptions is not null) { // Register options - var options = builder.Services.RegisterUserOptions(configureOptions); + builder.Services.RegisterUserOptions(configureOptions); // Insert default values - var scope = builder.Services.BuildServiceProvider().CreateScope(); - var userService = scope.ServiceProvider.GetRequiredService>(); - var userRoleService = scope.ServiceProvider.GetRequiredService>(); - userService.InsertAdminUserAndAssignRole(userRoleService, options.AdminRole, options.AdminUser, options.AdminPassword); + builder.Services.AddScoped>(); } return builder; @@ -113,12 +109,12 @@ private static UserOptions RegisterUserOptions where TUserKey : IEquatable where TUser : User { + var options = new UserOptions(); + configureOptions(options); + // Register IOptions> services.Configure(configureOptions); - // Get UserOptions<,> from ServiceProvider - var options = services.BuildServiceProvider().GetRequiredService>>().Value; - // Register UserOptions<,> without IOptions services.AddSingleton>(options); @@ -128,42 +124,15 @@ private static UserOptions RegisterUserOptions private static UserOptions RegisterUserOptions(this IServiceCollection services, Action> configureOptions) where TUser : User { + var options = new UserOptions(); + configureOptions(options); + // Register IOptions> services.Configure(configureOptions); - // Get UserOptions<,> from ServiceProvider - var options = services.BuildServiceProvider().GetRequiredService>>().Value; - // Register UserOptions<,> without IOptions services.AddSingleton>(options); return options; } - - private static void InsertAdminUserAndAssignRole(this IUserService userService, IUserRoleService userRoleService, string role, TUser user, string password) - where TUserKey : IEquatable - where TUser : User - { - if (user is null || password is null) return; - - // If user was not inserted before, insert it - try - { - if (userService.ExistsUserName(user.UserName).Result is false) - { - userService.Create(user, password).Wait(); - if (role is not null) userRoleService.AddRoles(user.Id, new List { role }).Wait(); - } - } - catch (Exception) - { - // ignored - } - } - - private static void InsertAdminUserAndAssignRole(this IUserService userService, IUserRoleService userRoleService, string role, TUser user, string password) - where TUser : User - { - userService.InsertAdminUserAndAssignRole(userRoleService, role, user, password); - } } \ No newline at end of file diff --git a/src/Identity/uBeac.Core.Identity/Seeders/RoleSeeder.cs b/src/Identity/uBeac.Core.Identity/Seeders/RoleSeeder.cs new file mode 100644 index 00000000..2d64d8d5 --- /dev/null +++ b/src/Identity/uBeac.Core.Identity/Seeders/RoleSeeder.cs @@ -0,0 +1,38 @@ +namespace uBeac.Identity.Seeders; + +public class RoleSeeder : IDataSeeder + where TKey : IEquatable + where TRole : Role +{ + private readonly IRoleService _roleService; + private readonly RoleOptions _roleOptions; + + public RoleSeeder(IRoleService roleService, RoleOptions roleOptions) + { + _roleService = roleService; + _roleOptions = roleOptions; + } + + public async Task SeedAsync(CancellationToken cancellationToken = default) + { + var data = _roleOptions.DefaultValues?.ToList(); + + if (data is null || data.Any() is false) return; + + foreach (var role in data) + { + if (await _roleService.Exists(role.Name, cancellationToken) is false) + { + await _roleService.Create(role, cancellationToken); + } + } + } +} + +public class RoleSeeder : RoleSeeder + where TRole : Role +{ + public RoleSeeder(IRoleService roleService, RoleOptions roleOptions) : base(roleService, roleOptions) + { + } +} diff --git a/src/Identity/uBeac.Core.Identity/Seeders/UnitSeeder.cs b/src/Identity/uBeac.Core.Identity/Seeders/UnitSeeder.cs new file mode 100644 index 00000000..8d74d214 --- /dev/null +++ b/src/Identity/uBeac.Core.Identity/Seeders/UnitSeeder.cs @@ -0,0 +1,41 @@ +namespace uBeac.Identity.Seeders; + +public class UnitSeeder : IDataSeeder + where TKey : IEquatable + where TUnit : Unit +{ + private readonly IUnitService _unitService; + private readonly UnitOptions _unitOptions; + + public UnitSeeder(IUnitService unitService, UnitOptions unitOptions) + { + _unitService = unitService; + _unitOptions = unitOptions; + } + + public async Task SeedAsync(CancellationToken cancellationToken = default) + { + var data = _unitOptions.DefaultValues?.ToList(); + + if (data is null || data.Any() is false) return; + + foreach (var unit in data) + { + if (await _unitService.Exists(unit.Code, unit.Type, cancellationToken) is false) + { + var parent = unit.GetParentUnit(); + if (parent != null) unit.ParentUnitId = parent.Id; + + await _unitService.Create(unit, cancellationToken); + } + } + } +} + +public class UnitSeeder : UnitSeeder + where TUnit : Unit +{ + public UnitSeeder(IUnitService unitService, UnitOptions unitOptions) : base(unitService, unitOptions) + { + } +} diff --git a/src/Identity/uBeac.Core.Identity/Seeders/UnitTypeSeeder.cs b/src/Identity/uBeac.Core.Identity/Seeders/UnitTypeSeeder.cs new file mode 100644 index 00000000..289aa25e --- /dev/null +++ b/src/Identity/uBeac.Core.Identity/Seeders/UnitTypeSeeder.cs @@ -0,0 +1,38 @@ +namespace uBeac.Identity.Seeders; + +public class UnitTypeSeeder : IDataSeeder + where TKey : IEquatable + where TUnitType : UnitType +{ + private readonly IUnitTypeService _unitTypeService; + private readonly UnitTypeOptions _unitTypeOptions; + + public UnitTypeSeeder(IUnitTypeService unitTypeService, UnitTypeOptions unitTypeOptions) + { + _unitTypeService = unitTypeService; + _unitTypeOptions = unitTypeOptions; + } + + public async Task SeedAsync(CancellationToken cancellationToken = default) + { + var data = _unitTypeOptions.DefaultValues?.ToList(); + + if (data is null || data.Any() is false) return; + + foreach (var unitType in data) + { + if (await _unitTypeService.Exists(unitType.Code, cancellationToken) is false) + { + await _unitTypeService.Create(unitType, cancellationToken); + } + } + } +} + +public class UnitTypeSeeder : UnitTypeSeeder + where TUnitType : UnitType +{ + public UnitTypeSeeder(IUnitTypeService unitTypeService, UnitTypeOptions unitTypeOptions) : base(unitTypeService, unitTypeOptions) + { + } +} diff --git a/src/Identity/uBeac.Core.Identity/Seeders/UserSeeder.cs b/src/Identity/uBeac.Core.Identity/Seeders/UserSeeder.cs new file mode 100644 index 00000000..48bf98c2 --- /dev/null +++ b/src/Identity/uBeac.Core.Identity/Seeders/UserSeeder.cs @@ -0,0 +1,46 @@ +namespace uBeac.Identity.Seeders; + +public class UserSeeder : IDataSeeder + where TKey : IEquatable + where TUser : User +{ + private readonly IUserService _userService; + private readonly IUserRoleService _userRoleService; + private readonly UserOptions _userOptions; + + public UserSeeder(IUserService userService, IUserRoleService userRoleService, UserOptions userOptions) + { + _userService = userService; + _userRoleService = userRoleService; + _userOptions = userOptions; + } + + public async Task SeedAsync(CancellationToken cancellationToken = default) + { + var adminUser = _userOptions.AdminUser; + var adminPassword = _userOptions.AdminPassword; + + await CreateAdminUser(adminUser, adminPassword, cancellationToken); + } + + public async Task CreateAdminUser(TUser user, string password, CancellationToken cancellationToken = default) + { + var role = _userOptions.AdminRole; + + if (user is null || password is null || role is null) return; + + if (await _userService.ExistsUserName(user.UserName, cancellationToken) is false) + { + await _userService.Create(user, password, cancellationToken); + await _userRoleService.AddRoles(user.Id, new List { role }, cancellationToken); + } + } +} + +public class UserSeeder : UserSeeder + where TUser : User +{ + public UserSeeder(IUserService userService, IUserRoleService userRoleService, UserOptions userOptions) : base(userService, userRoleService, userOptions) + { + } +} diff --git a/src/Logging/uBeac.Core.Logging/AppContextEnricher.cs b/src/Logging/uBeac.Core.Logging/AppContextEnricher.cs deleted file mode 100644 index 356f1315..00000000 --- a/src/Logging/uBeac.Core.Logging/AppContextEnricher.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using Serilog.Configuration; -using Serilog.Core; -using Serilog.Events; -using uBeac; - -namespace Serilog; - -public class AppContextEnricher : ILogEventEnricher -{ - protected readonly IServiceCollection Services; - - public AppContextEnricher(IServiceCollection services) - { - Services = services; - } - - public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) - { - var context = Services.BuildServiceProvider().CreateScope().ServiceProvider.GetRequiredService(); - logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("TraceId", context.TraceId)); - logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("SessionId", context.SessionId)); - logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("UserName", context.UserName)); - logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("UserIp", context.UserIp)); - logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("Language", context.Language)); - } -} - -public static class AppContextEnricherExtensions -{ - public static LoggerConfiguration WithAppContext(this LoggerEnrichmentConfiguration enrichmentConfiguration, IServiceCollection services) - => enrichmentConfiguration.With(new AppContextEnricher(services)); -} \ No newline at end of file diff --git a/src/Web/uBeac.Core.Web.Common/ApplicationExtensions.cs b/src/Web/uBeac.Core.Web.Common/ApplicationExtensions.cs index 8f5d52a6..ab476652 100644 --- a/src/Web/uBeac.Core.Web.Common/ApplicationExtensions.cs +++ b/src/Web/uBeac.Core.Web.Common/ApplicationExtensions.cs @@ -1,5 +1,7 @@ using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using uBeac; using uBeac.Web; namespace Microsoft.AspNetCore.Builder; @@ -21,4 +23,18 @@ public static IApplicationBuilder UseHstsOnProduction(this IApplicationBuilder a return app; } -} \ No newline at end of file + + public static IApplicationBuilder SeedData(this IApplicationBuilder app) + { + var seeders = app.ApplicationServices.CreateScope() + .ServiceProvider + .GetServices(); + + foreach (var seeder in seeders) + { + seeder.SeedAsync().Wait(); + } + + return app; + } +}