Base solution for your next web application

Activities of "cyklussoftware"

@maliming Thanks for the clarification

I'll take a look. Thanks!

@maliming Thanks for pointing me to those issues. When it comes to Entity Framework Core, would those changes be considered breaking changes? By breaking change, I mean a change that shouldn't be applied to a database that is currently in production. Or, if I create a new database for a new tenant, would it create an inconsistency between the existing database and the new database?

@chauey We pushed custom branding futher back in our backlog, so I haven't worked on this tool for a while. I think the biggest thing it needs is a way to export a tenant-specific CSS file for them to upload.

Feel free to expand or even rewrite the existing logic.

@ismcagdas

I wasn't trying to complain about the number of colors. I was just saying that my tool doesn't consolidate colors that are very similar in color value. I played around with consolidating colors based on the HSV color space, but the version I put on GitHub doesn't do that. It is a potential improvement for my tool.

I wanted to post here to let people know that I made a tool that helped me with my Tenant Custom CSS problem. I am hoping that someone else might find it useful.

@alper @rbreton This probably isn't related, but there was an issue that I came across the other day while generating an Entity called EventCategory.

This was the problematic code before:

modelBuilder.Entity<EventCategory>(e =>
{
    e.HasIndex(e => new { e.TenantId });
});

And after I changed the name of my entity:

modelBuilder.Entity<SchoolEventCategory>(s =>
{
    s.HasIndex(e => new { e.TenantId });
});

The tool picks what to call the first variable based on the first letter of the entity name. So if anything starts with E, there will be a compile error.

So, like I said, it's unrelated but a problem.

@rbreton Did you try building your project after generating all of the code? The specific error would likely show up then.

I put together a little "hack" to get this to work.

This is my new "getApplicationConfig" method from the AppPreBootstrap.ts file in my Angular project:

private static getApplicationConfig(appRootUrl: string, callback: () => void) {
let type = 'GET';
let url = appRootUrl + 'assets/' + environment.appConfig;
let customHeaders = [
{
name: 'Abp.TenantId',
value: abp.multiTenancy.getTenantIdCookie() + ''
}];


XmlHttpRequestHelper.ajax(type, url, customHeaders, null, (result) => {
    const subdomainTenancyNameFinder = new SubdomainTenancyNameFinder();
    const tenancyName = subdomainTenancyNameFinder.getCurrentTenancyNameOrNull(result.appBaseUrl);

    // CUSTOM ADDITION HERE
    let getTenantIdURL = result.remoteServiceBaseUrl + '/api/services/app/Account/IsTenantAvailable';
    let getTenantIdData =
    {
        tenancyName: tenancyName
    };
    XmlHttpRequestHelper.ajax('POST', getTenantIdURL, null, JSON.stringify(getTenantIdData), (tenantResult) => {
        abp.multiTenancy.setTenantIdCookie(tenantResult.result.tenantId);

        // pulled from surrounding ajax method
        AppConsts.appBaseUrlFormat = result.appBaseUrl;
        AppConsts.remoteServiceBaseUrlFormat = result.remoteServiceBaseUrl;
        AppConsts.localeMappings = result.localeMappings;

        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();
    });
    // END CUSTOM ADDITION
});

Now my appconfig.json in my Angular project includes this:

"remoteServiceBaseUrl": "https://api.websitename.io",
"appBaseUrl": "https://{TENANCY_NAME}.websitename.io",

and my appsettings.json file for the Host project includes this:

"ServerRootAddress": "https://api.websitename.io",
"ClientRootAddress": "https://dev.websitename.io",
"CorsOrigins": "https://*.websitename.io"

With this implementation, I can navigate my browser to default.websitename.io and I am logged into the default tenant. I can go to host.websitename.io or any other URL that contains an invalid tenant name and I am logged in the Host.

It's probably not the best way to do things, but it seems to work just fine.

@ryancyq I actually found that post a couple of days ago. I was having that problem and fixed it before I tried switching to the {TENANCY_NAME} based tenant resolution.

Anyways, my proxy and the whole system works just fine if I don't get the TENANCY_NAME from the URL and manually specify it in the Login page instead.

@ismcagdas

You are correct. The Host project and Angular project are completely separated apps. I'm using Nginx instead of IIS, but it's the same concept. If I navigate my browser to api.websitename.com, I see the Swagger UI.

Everything works fine between Angular and the Host in this configuration if I manually set the tenant name on the Login page of the Angular app. This is because all of the API requests get an HTTP header of Abp.TenantId added to them.

If I try to resolve the tenant name from the URL, the Angular app is aware that my tenant name is Default, but because the URL to the Host is just api.websitename.com, the Host doesn't know what tenant I am. I am logged into the Host rather than the Default Tenant.

Basically, using {TENANCY_NAME}.websitename.com for Angular and api.websitename.com for the Host project logs me into the Host rather than the Default tenant because Angular isn't sending the Abp.TenantId header and the Host project isn't expecting the tenant name to be in the URL.

Hopefully that makes sense.

I guess my questions is this: How do I use a common API URL (rather than a {TENANCY_NAME} based URL) for the Host project and a {TENANCY_NAME} based URL for the Angular project?

@emadah Did you run the NSwag utility using nswag/refresh.bat in the Angular project? I ran into a problem with Angular earlier this week where my service files were not generated properly, so when I ran Angular for the first time it wouldn't compile.

On second glance this might not be the problem, but it's an important step anyways.

Showing 1 to 10 of 23 entries