Base solution for your next web application
Open Closed

Tenancy Name as subdomain of subdomain #2573


User avatar
0
cangunaydin created

Hello, I wonder if {tenancy_name} parameter can be used as subdomain of subdomain? i am trying it in the websiterootaddress of appsettings.json but i couldn't succeed. Is there any solution for it? and is it possible to have multiple websiterootaddress values? Cause in the future my application will use multiple domain names for the same ip address probably.


18 Answer(s)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Tenancy Name placeholder can be used as a subdomain of a subdomain. We already use it in that way in our demos. All demos are created under {TENANCY_NAME}.demo.aspnetzero.com.

    You cannot have multiple websiterootaddress values but you can implement a custom ITenantResolveContributer and use it as the default tenant finder. In that way you can find the tenant as you like, you can use multiple websiterootaddress if you like.

  • User Avatar
    0
    cangunaydin created

    Then i am doing sth wrong. Can you give me an example of appsettings.json from the .net core project and from the angular2 project.

    i have tried with these values. in .net core project appsettings.json

    http://{TENANCY_NAME}.mydomain {TENANCY_NAME}.mydomain

    i am always getting 'Access-Control-Allow-Origin' header error.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Probably this is a bug, I have created an issue here <a class="postlink" href="https://github.com/aspnetzero/aspnet-zero-core/issues/76">https://github.com/aspnetzero/aspnet-ze ... /issues/76</a>. For now, you can set "{TENANCY_NAME}.mydomain.com" and when setting CORS policy here <a class="postlink" href="https://github.com/aspnetzero/aspnet-zero-core/blob/dev/aspnet-core/src/MyCompanyName.AbpZeroTemplate.Web.Host/Startup/Startup.cs#L53">https://github.com/aspnetzero/aspnet-ze ... tup.cs#L53</a>, replace "{TENANCY_NAME}" with a "*" and see if it works for you.

    Thanks.

  • User Avatar
    0
    cangunaydin created

    Hello, Thanks for the answer. But i don't think withorigins will resolve all subdomains when you add * for subdomains. I have tried in my local but it doesn't work. Did you try this? does it work for you?

    p.WithOrigins(_appConfiguration["App:WebSiteRootAddress"].RemovePostFix("/").Replace("{TENANCY_NAME}","*")).AllowAnyHeader().AllowAnyMethod();

    This doesn't work for me.

  • User Avatar
    0
    cangunaydin created

    By the way probably you have changed the code for DomainTenantResolveContributer. I have tried your code, but there is a very minor mistake probably it won't work when there is no {TENANCY_NAME} i have got an error from my local at least. i did a change in your new code to make it work.

    after this code

    if (!result.IsMatch)
                {
                    return null;
                }
    

    it is going to match even if you don't have any tenant but matches[0] is gonna give you null value. i did a small patch like this

    if (!result.IsMatch)
                {
                    return null;
                }
                var tenancyName = string.Empty;
                if (result.Matches.Count > 0)
                {
                    tenancyName = result.Matches[0].Value;
                }
    
  • User Avatar
    0
    cangunaydin created

    Ok after i couldn't figure it out how to solve it. I decided to add another settings to appsettings.json for allowed domain names. I am reading the settings and adding it to cors. now cors problem is solved. But when i try to open the application by http://{TENANCY_NAME}.mydomain.com it does not change the tenancy name. On the upper part changing tenancy options are still the same.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    We have found a bug related to this problem recently <a class="postlink" href="https://github.com/aspnetzero/aspnet-zero/issues/344">https://github.com/aspnetzero/aspnet-zero/issues/344</a>. Can you try to use "{TENANCY_NAME}.mydomain.com" instead of "http://{TENANCY_NAME}.mydomain.com" for websiterootaddress ?

    We will try and apply your fix to our code as well.

  • User Avatar
    0
    cangunaydin created

    i have tried every possible combination i guess but no matter what it doesn't work. here is the app configuration in my appsettings.json

    "App": {
        "WebSiteRootAddress": "{TENANCY_NAME}.miconfig.com",
        "AllowedDomainsForCors": [ "http://default.miconfig.com", "http://miconfig.com","http://www.miconfig.com" ]
      }
    

    i have changed my c:\Windows\System32\Drivers\etc\hosts file to try it in my local.

  • User Avatar
    0
    cangunaydin created

    Also can you explain how does the system works when you call a subdomain url? For instance in my example i have miconfig.com as my domain and default.miconfig.com as my subdomain. default is the tenant in my db. so expected behaviour for me should when i call default.miconfig.com (which is binded to my iis web site), it should come with the tenant name on the top of angular ui. I believe it is resolving the tenant from DomainTenantResolveContributer class cause i wrote a custom class for it and i have seen it was working fine. But what i don't understand is i couldn't find a code that is deciding if the tenantid has the value or not in the angular project. Can you give me more details about it? Thank you for the assistance by the way.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    In angular project it works like this. We find tenancyname here <a class="postlink" href="https://github.com/aspnetzero/aspnet-zero-core/blob/master/angular/src/AppPreBootstrap.ts#L40">https://github.com/aspnetzero/aspnet-ze ... rap.ts#L40</a> and we modify remote service url including tenancy name.

    For example, when we enter <a class="postlink" href="http://default.miconfig.com">http://default.miconfig.com</a> (I assume this is the client app url), then all server requests will be made to <a class="postlink" href="http://default.miconfigserver.com">http://default.miconfigserver.com</a> and server will be able to determine tenant from it's url.

    So, you need to use {TENANCY_NAME} both on host and angular client app's configuration. If you cannot manage it, I will prepare a short document about this at the weekend share with you and other people as well.

    Thanks for your effort.

  • User Avatar
    0
    cangunaydin created

    Hello, Thanks for the reply. I am looking forward for that document. Still i have some points that is missing. I will try to give an example. Let's say i am hosting my server app and client app in iis.

    client app has domain : miconfig.com server app has domain: miconfigserver.com

    so also let's say i have added two bindings called default.miconfig.com for client app and default.miconfig.server.com for server app.

    and these are my settings file.

    Client App Settings

    {
      "remoteServiceBaseUrl": "{TENANCY_NAME}.miconfigserver.com",
      "appBaseUrl": "{TENANCY_NAME}.miconfig.com"
    }
    

    Server App Settings

    "App": {
        "WebSiteRootAddress": "{TENANCY_NAME}.miconfig.com",
        "AllowedDomainsForCors": [ "http://default.miconfig.com", "http://miconfig.com" ]
      }
    

    so here are two things that i need to ask. in the server side DomainTenantResolveContributer the code is like this.

    var hostName = httpContext.Request.Host.Host.RemovePreFix("http://", "https://"); 
                var domainFormat = _multiTenancyConfiguration.DomainFormat.RemovePreFix("http://", "https://").Split(':')[0];
                var result = new FormattedStringValueExtracter().Extract(hostName, domainFormat, true);
    

    so basically my client app will ask with <a class="postlink" href="http://default.miconfigserver.com/..">http://default.miconfigserver.com/..</a>. and hostname will be default.miconfigserver.com and the domainFormat in the appsettings was {TENANCY_NAME}.miconfig.com which does not match with it. So it will return null value. So no tenantid will be assigned. Please correct me if i am missing sth.

    second thing i want to ask is with angular app you have this code in AppPreBootstrap.ts

    private static getApplicationConfig(callback: () => void) {
            return abp.ajax({
                url: '/assets/appconfig.json',
                method: 'GET',
                headers: {
                    'Abp.TenantId': abp.multiTenancy.getTenantIdCookie()
                }
            }).done(result => {
    
                let subdomainTenancyNameFinder = new SubdomainTenancyNameFinder();
                var tenancyName = subdomainTenancyNameFinder.getCurrentTenancyNameOrNull(result.appBaseUrl);
    
                AppConsts.appBaseUrlFormat = result.appBaseUrl;
                AppConsts.appBaseUrl = result.appBaseUrl.replace(AppConsts.tenancyNamePlaceHolderInUrl, tenancyName);
    
                AppConsts.remoteServiceBaseUrlFormat = result.remoteServiceBaseUrl;
                AppConsts.remoteServiceBaseUrl = result.remoteServiceBaseUrl.replace(AppConsts.tenancyNamePlaceHolderInUrl, tenancyName);
    
                callback();
            });
        }
    

    so in this code you are having the tenancy name from SubdomainTenancyNameFinder but if i call miconfig.com from the browser this value will be null and there is no condition for null value. So when i try to call my application from <a class="postlink" href="http://miconfig.com">http://miconfig.com</a> it tries to call <a class="postlink" href="http://null.miconfigserver.com">http://null.miconfigserver.com</a> which does not exist. Sorry for the long messages but i am trying to understand what am i missing.

    I hope i made myself clear with the situation and thanks for the help.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Thank you for your detailed explanation and work. It seems like there is a bug in this case.

    We will try this scenario and fix if there is a problem as soon as possible.

    Thanks again.

  • User Avatar
    0
    cangunaydin created

    Hello, Is there any progress on tenancy detection? Did you find time to look at that?

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    I have tried it with the following steps and made it working locally.

    Consider we have below addresses for our host and ng2 clietn apps host app: zerong2host.com client app: zerong2client.com

    1. First upgrade to lates ABP (v1.5), because it fixes a problem related to this.
    2. After publishing your host project, be sure it publishes with ABP v1.5 because sometimes VS retrieves an older version of ABP. It took an hour of mine to determine this :).
    3. Change getApplicationConfig in AppPreBootstrap.ts to following (we will include in the next version):
    private static getApplicationConfig(callback: () => void) {
        return abp.ajax({
            url: '/assets/appconfig.json',
            method: 'GET',
            headers: {
                'Abp.TenantId': abp.multiTenancy.getTenantIdCookie()
            }
        }).done(result => {
    
            let subdomainTenancyNameFinder = new SubdomainTenancyNameFinder();
            var tenancyName = subdomainTenancyNameFinder.getCurrentTenancyNameOrNull(result.appBaseUrl);
    
            AppConsts.appBaseUrlFormat = result.appBaseUrl;
            AppConsts.remoteServiceBaseUrlFormat = result.remoteServiceBaseUrl;
    
            if (tenancyName == null) {
                AppConsts.appBaseUrl = result.appBaseUrl.replace(AppConsts.tenancyNamePlaceHolderInUrl + ".", "");
                AppConsts.remoteServiceBaseUrl = result.remoteServiceBaseUrl.replace(AppConsts.tenancyNamePlaceHolderInUrl + ".", "");
            } else {
                AppConsts.appBaseUrl = result.appBaseUrl.replace(AppConsts.tenancyNamePlaceHolderInUrl, tenancyName);
                AppConsts.remoteServiceBaseUrl = result.remoteServiceBaseUrl.replace(AppConsts.tenancyNamePlaceHolderInUrl, tenancyName);
            }
    
            callback();
        });
    }
    
    1. modify appconfig.json for ng2 client to
    {
      "remoteServiceBaseUrl": "http://{TENANCY_NAME}.zerong2host.com",
      "appBaseUrl": "http://{TENANCY_NAME}.zerong2client.com"
    }
    
    1. modify appsettings.json for host app to
    "App": {
        "WebSiteRootAddress": "http://{TENANCY_NAME}.zerong2host.com",
        "CorsOrigins": "http://zerong2client.com/,http://default.zerong2client.com"
    }
    

    After those steps I was able to use <a class="postlink" href="http://zerong2client.com">http://zerong2client.com</a> (for host) and <a class="postlink" href="http://default.zerong2client.com(for">http://default.zerong2client.com(for</a> default tenant) successfully.

    I have added port numbers to both clietn and server to run them locally but removed them in the above examples.

    Please let us know if this does not work for you.

  • User Avatar
    0
    cangunaydin created

    Hello, thank you for the help, i make it work. I was confused at first because in the website root address of the app.config file it has the configuration like this as default.

    "App": {
        "WebSiteRootAddress": "http://localhost:4200/",
        "CorsOrigins": "http://localhost:4200"
      }
    

    which is pointing out the client app address. but in your example it is pointing out to the server app root address. So maybe you should change the default value to server address.

    On the other hand, i have a small problem with the solution. i have a configuration that you can see below. When i visit the url default.miconf.bitlogic.se, tenant user interface is hidden which i have expected. After that when i login as admin account and log out it is redirecting me to default.miconf.bitlogic.se which is an expected behavior also. But when i change the url to miconf.bitlogic.se , i was expecting to see tenant user interface which i couldn't see. So after i login and logout with subdomain url if i visit the root url in my example it is miconf.bitlogic.se i can not change the tenant. The app doesn't give me that option. Could you guide me so i can fix it also? Thank you for the assistance.

    "App": {
        "WebSiteRootAddress": "http://{TENANCY_NAME}.miconfserver.bitlogic.se",
        "CorsOrigins": "http://miconf.bitlogic.se,http://default.miconf.bitlogic.se"
      }
    
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    I'm glad that it is fixed. We designed the tenancy change on host url to be invisible on purpose. You can change it here if you like <a class="postlink" href="https://github.com/aspnetzero/aspnet-zero-core/blob/dev/angular/src/account/account.component.ts#L32">https://github.com/aspnetzero/aspnet-ze ... ent.ts#L32</a>

  • User Avatar
    0
    cangunaydin created

    Hello, What i don't understand is when the application is first started, when it first starts i can see the ui for tenant change, and i can select a tenant . Maybe sth that is stayed in my cache? or is it also an expected behavior? Because according to the code in account.component.ts if i visit root url without tenancyname i shouldn't see the ui. But i am seeing when the app is first deployed.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Let us check this, it shouldn't be visible as you said. We will fix it if there is a problem.

    Thanks.