Hi @ismcagdas, I don't see any error messages when creating the new database, it just creates the database outside of the Elastic Pool I have specified. It also creates it on a very expensive Tier!
When creating databases in azure, I need to be able to specify options for the database being created using CreateOrMigrateForTenant.
The entity framework tells me that I can do this using the DbContext Model builder like so: https://learn.microsoft.com/en-us/ef/core/providers/sql-server/azure-sql-database
But this is not working, I am not 100% sure if this is an AspNetZero problem or not, it might just be broken. Is this the way you would suggest setting db settings such as the Service Tier or in my case, the elastic pool that I want the new tenant database to be created in?
Hi ismcagdas,
public override string GetNameOrConnectionString(ConnectionStringResolveArgs args)
{
if (args["DbContextConcreteType"] as Type == typeof(TenantDbContext))
{
var tenantCacheItem = _tenantCache.Get(_currentUnitOfWorkProvider.Current.GetTenantId().Value);
if (tenantCacheItem.ConnectionString.IsNullOrEmpty())
{
return _appConfiguration[$"ConnectionStrings:{CloudConsts.TenantConnectionStringName}"];
}
return tenantCacheItem.ConnectionString;
}
return base.GetNameOrConnectionString(args);
}
This is my Custom Connection String Resolver, it works perfectly but I can see this method is called so much I just want to make sure I cant improve it in any way as it currently does quite a lot! MultiTenancySide seemed like it would help but it is always either Host or Null, never Tenant, even though I have decorated my second db context with [MultiTenancySide(MultiTenancySides.Tenant)]. Its also Null most of the time for the main db context too so i cant just check for NULL. I am concerned that when we have 100s of people using this system, performance of this code block is going to be terrible
For now we have gone with creating the public site in the same angular app and just putting the routing in the root-routing module e.g.
{
path: 'about',
component: LandingComponent,
loadChildren: () => import('./landing/about/about.module').then((m) => m.AboutModule),
},
This is working for now but it is not ideal. I would like to explore the option of having a second angular app for the public site, so that the main angular app included with AspNetZero would be served on my.company.com and a new "Landing" site would be served on www.company.com, just like the MVC Public Project Included with AspNetZero.
I started off by cloning the current angular folder to angular-Landing and adding the landing components there ( e.g. About, Contact etc ) but it became apparent that this was going to create some major issues as I didn't want to use the authentication from this project. I want the landing site to share a session with the main angular app. I sort of got this working because I was hosting them on the same domain and could wildcard the CORS but when it needed to login etc, it was trying to use the pages from the folder and not the main one. Another worry is that if we ever updated the AspNetZero template to a new version, this might mean the angular-landing site broke.
I think what I need to do it make a completely separate angular site from scratch but I want to be able to access the proxies from the main app and share the login/session. Any advice anyone has for me on this would be much appreciated!
I don't suppose AspNetZero have any plans to migrate the MVC Public site to Angular do they?!
Yes I did think about doing this but I want to share the user session with the main app. If they are logged in on app.mywebsite.com, www.mywebsite.com should show the logged in user menu, not the login button. I want to do this because if they are logged in, the landing site will show different menu items etc
I am using the Asp.Net Core with Angular v12 template but I don't want to use the MVC public site template. I have added a "Landing" folder at the same level as the Account and App folders in the Angular project. I have then created a module and component in this folder and have created folders/components under this folder for the landing site pages, e.g. about, contact etc. This is all working fine and I have adjusted the routing etc so I can now see localhost:4200/landing/home without needing to be logged in, which is great. My issue now is how I can tweak the routing for once the site is published. I have pushed the dist folder to a static web app in azure and setup two custom domains, app.mywebsite.com and www.mywebsite.com. app.mywebsite.com works perfectly, showing the main app or the login page if not logged in. What I cant figure out how to do is point www.mywebsite.com to the landing/home component. I can create redirects but I would need to do this for every component and it feels like it will be quite messy. I also want people to be able to go to www.mywebsite.com/about, not www.mywebsite.com/landing/about. Is there a way to achieve this or am i stuck having to create redirects?
To add to my original question, I have found that the "Deploy Azure Static Web App (Preview)" Task in the build pipeline of Azure doesnt seem to like the Agent Specification being set to Windows so I have tried splitting the pipeline into 2 different jobs, using different agents but it still wont build. In the end I gave up and pushed the dist folder manually using SWA Deploy. Not ideal but it will do for now
https://learn.microsoft.com/en-us/azure/static-web-apps/static-web-apps-cli-deploy
Has anyone managed to deploy the Angular app to an Azure Static Web App? It seems like this is a much better fit than deploying it to an azure storage account that then requires a cdn etc. I found this guide on how to publish an angular app to a static web app but it only seems to work if you host you project in github, which we dont, we use DevOps. Am I missing something here? Is a Static Web App the best way to go for price, performance and convenience?! If so, any advice on how to setup deployment would be much appreciated!
Thanks @ismcagdas, I did try decorating my second db context like this:
[MultiTenancySide(MultiTenancySides.Tenant)]
public class SecondDbContext : AbpDbContext
{
public virtual DbSet<CustomEntity> Stuff { get; set; }
...
}
but it isnt picked up on my Custom Connection String Resolver:
public override string GetNameOrConnectionString(ConnectionStringResolveArgs args)
{
if (args.MultiTenancySide == MultiTenancySides.Tenant)
{
//This is never hit
}
...
}
Any idea why? Is there something else I need to do? I could use the DbContextConcreteType but it seems like just using the MultiTenancySide would be much more efficient? Tenants will always have a connection string and will only access ONE Custom DbContext (In Addition to the AspNetZeroDbContext, for shared data lookups and user logins etc)
public override string GetNameOrConnectionString(ConnectionStringResolveArgs args)
{
if (args["DbContextConcreteType"] as Type == typeof(SecondDbContext))
{
var tenantCacheItem = _tenantCache.Get(_currentUnitOfWorkProvider.Current.GetTenantId().Value);
return tenantCacheItem.ConnectionString;
}
if (args["DbContextConcreteType"] as Type == typeof(ThirdDbContext))
{
var tenantCacheItem = _tenantCache.Get(_currentUnitOfWorkProvider.Current.GetTenantId().Value);
return tenantCacheItem.ConnectionString;
}
return base.GetNameOrConnectionString(args);
}
Sorry to keep coming back to this but I still don't have a working solution for this. We have 2 different types of tenant, which is denoted by a property on the Tenant called "TenantType". I have created 2 extra dbContexts for these, each with their own DbContextConfigurer, DbContextFactory and DbMigrator Class (Which inherits from my iTenantMigrator interface, as suggested above). I have also created a CustomConnectionStringResolver class but I dont really want to use args["DbContextConcreteType"] in order to work out what dbContext is requesting the connection string, is there not a better way? I was hoping to use args.MultiTenancySide but this seems to be coming through as NULL when it is from my second dbContext, which is decorated with [MultiTenancySide(MultiTenancySides.Tenant)]. Am I misunderstanding what the args.MultiTenancySide property does?