I have a question, about how to set up a project for multiple clients. We currently develop an ASP Core application. All clients use the same database structure, so they have identical databases, just filled with different users,... We currently use one publish, set up two test websites on IIS and each of those publishes has a different JSON config file containing the DB context (read out at Startp.cs).
Our problem here is, that if we have multiple clients, we have to copy our publish multiple times to maintain multiple websites for the IIS. We didn't find a way to just use one publish and define the config file to be used dependent on the URL/port of the connected client. We tried a tutorial for tenancy under ASP Core, but it failed at the User Manager.
Can someone point me out, to what's the best solution for this kind of webproject, which requires one shared website/publish under IIS, different DB contexts for each client (URL/port), user authentication (we used Identity for that). We tried this for weeks now, but failed to get it working. Our main problem is, that the DB context is created in the Startup.cs before the host is built, so we don't have any URL's from the request and can't create a specific DB context when the application starts. This means, we can't fill the UserStore and can't get the login to work. We know we could make a master table with all the users and domains, but we really would like to avoid this approach, as we are not sure, if the websites will run on the same server, or if one client may use his own internal company server.
EDIT: I need to be more specific, as I made a small mistake. The databases are identical. So i actually won't need different context classes, but just different connection strings. But they are set in the Startup.cs in the AddDbContext function...
EDIT2: I tried a few solutions now, and I'm always failing on Identity. It doesn't seem to work and crashes, when no DbContext is created directly during Startup.
EDIT3: As I failed so far, here are some Code Snippets from our Projekt
In our Startup.cs/ConfigureServices(IServiceCollection services)
- We are loading our DB settings from a config file
IConfigurationSection DbSection = Configuration.GetSection("Database");
- We are adding the DB Context
services.AddDbContext<MyDbContext>(options => options.UseSqlServer(MyDbContext.createConnectionString(DbSection), b => b.MigrationsAssembly("MyNamespace.DB").EnableRetryOnFailure()));
- And setting up Identity
services.AddScoped<Microsoft.AspNetCore.Identity.SignInManager<MyUser>, MySignInManager>();
services.AddScoped<Microsoft.AspNetCore.Identity.IUserStore<MyUser>, MyUserStore>();
services.AddScoped<Microsoft.AspNetCore.Identity.UserManager<MyUser>, Services.LogIn.MyUserManager>();
services.AddIdentity<MyUser, MyRole>()
.AddUserManager<MyUserManager>()
.AddUserStore<MyUserStore>()
.AddRoleStore<MyRoleStore>()
.AddDefaultTokenProviders();
- We are adding authorization
services.AddAuthorization(options =>
{ options.DefaultPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
});
In our Startup.cs/Configure(...) - We set UseAuthorization
app.UseAuthentication();
app.UseAuthorization();
In our MyDbContext class we are creating the connection string
public static string createConnectionString(IConfigurationSection configurationSection)
{
return @"server=" + configurationSection.GetSection("Server").Value +
";database=" + configurationSection.GetSection("Database").Value +
";persist security info=True;user id=" + configurationSection.GetSection("User").Value +
";password=" + configurationSection.GetSection("Password").Value + ";multipleactiveresultsets=True;";
}
So basically all we are trying to achieve, is to make different connections for different urls. Let's say we have 2 cients:
clientone.mysite.com:123 -> database_clientone
clienttwo.mysite.com:456 -> database_clienttwo
This does not work, as we don't have the domain when creating the DbContext. But we are required to have each database store it's own login credentials, instead of using a master table with all the logins for each existing users/databases...
And Identity doesn't seem to work with this scenario either.