Skip to content

Conversation

@suhaib-mousa
Copy link
Contributor

Adds a new tenant resolve contributor that resolves the tenant ID or name
from appsettings.json, under the key:
"MultiTenancy:Tenant"

@maliming maliming self-requested a review June 24, 2025 00:33
@maliming
Copy link
Member

hi

This tenant resolver reads the tenant identifier from application configuration appsettings.json.
It is intended primarily for development or testing environments where setting the tenant manually is helpful, especially in non-HTTP contexts (e.g., console apps, background workers).

The multi-tenant middleware primarily obtains the tenant from the HTTP request, and the application configuration has no relation to the HTTP request.

especially in non-HTTP contexts (e.g., console apps, background workers).

Can you explain more about this case?

Thanks.

@suhaib-mousa
Copy link
Contributor Author

hi

This tenant resolver reads the tenant identifier from application configuration appsettings.json.
It is intended primarily for development or testing environments where setting the tenant manually is helpful, especially in non-HTTP contexts (e.g., console apps, background workers).

The multi-tenant middleware primarily obtains the tenant from the HTTP request, and the application configuration has no relation to the HTTP request.

especially in non-HTTP contexts (e.g., console apps, background workers).

Can you explain more about this case?

Thanks.

The ConfigurationTenantResolveContributor currently works only in HTTP-based apps via the middleware pipeline.

For non-HTTP scenarios (e.g. console apps, workers), tenant resolution is still possible manually using the ITenantResolver.

Since non-HTTP scenarios are rare and not officially supported at the moment, related documentation will be removed.

If needed in the future, a dedicated resolver can still be implemented and invoked manually.

@maliming
Copy link
Member

hi

These TenantResolveContributor are easy to set the current tenant.
Why do we still need a configurable tenant? I can't think of any use cases for it.

For example, you can add a query string or cookies to change the current tenant. It's very easy.

QueryStringTenantResolveContributor
RouteTenantResolveContributor
HeaderTenantResolveContributor
CookieTenantResolveContributor

If we really need a default tenant, We can add an DefaultTenant property to AbpMultiTenancyOptions or AbpAspNetCoreMultiTenancyOptions

Then we can configure the options. which also support get value from appsettings.json.

The DefaultTenantResolveContributor should be at the end of the list.

QueryStringTenantResolveContributor
RouteTenantResolveContributor
HeaderTenantResolveContributor
CookieTenantResolveContributor
DefaultTenantResolveContributor

Thanks.

@suhaib-mousa
Copy link
Contributor Author

The case where I used ConfigurationTenantResolveContributor is when I rely on domain-based tenant resolution in production, but during development it's not practical to resolve by domain because of localhost.

So I conditionally register the configuration resolver like this:

if (env.IsDevelopment())
{
    options.TenantResolvers.InsertAfter(
        r => r is CurrentUserTenantResolveContributor,
        new ConfigurationTenantResolveContributor()
    );
}
else
{
    options.AddDomainTenantResolver(configuration["App:Wildcard"]!);
    options.TenantResolvers.InsertBefore(
        r => r is DomainTenantResolveContributor,
        new CustomHostnameTenantResolveContributor()
    );
}

I agree that it may not be suitable to include this as a default resolver in AbpMultiTenancyOptions. However, I used it in this specific development scenario where falling back to configuration made things simpler.

If this is considered too specific for the framework, I’m okay with removing it and instead write a small article to demonstrate how developers can handle this pattern manually when needed — or I can contribute a DefaultTenantResolveContributor that works similarly and can be placed last in the resolver chain.

@suhaib-mousa
Copy link
Contributor Author

Hi @maliming

I went ahead and pushed the implementation before your response — wanted to proactively address the scenario, especially for local development where domain-based resolution isn’t always practical.

If you think this doesn’t align with the core framework direction, I’m okay with shifting it to an article community post instead. Just let me know your take.

@maliming maliming added this to the 10.0-preview milestone Jun 25, 2025
@maliming maliming requested a review from hikalkan June 25, 2025 01:43
Copy link
Member

@hikalkan hikalkan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we add this to AbpAspNetCoreMultiTenancyOptions, only ASP.NET Core apps can use this, not console and other apps.

My suggestion:

Introduce string AbpTenantResolveOptions.FallbackTenant property.
In TenantResolver.ResolveTenantIdOrNameAsync method, just before the return result; statement, set result.TenantIdOrName if FallbackTenant was not null or empty.
In this way, it will be backward compatible and usable in any scenario. Please also update the documentation.

@suhaib-mousa
Copy link
Contributor Author

If we add this to AbpAspNetCoreMultiTenancyOptions, only ASP.NET Core apps can use this, not console and other apps.

My suggestion:

Introduce string AbpTenantResolveOptions.FallbackTenant property. In TenantResolver.ResolveTenantIdOrNameAsync method, just before the return result; statement, set result.TenantIdOrName if FallbackTenant was not null or empty. In this way, it will be backward compatible and usable in any scenario. Please also update the documentation.

Thanks , @hikalkan

That was actually the idea from the beginning — to solve the local dev scenario using a configuration-based resolver. But I agree that having a FallbackTenant directly on AbpTenantResolveOptions is a more robust and flexible solution, especially since it works across all application types.

I’ll proceed with your suggestion and update the implementation and documentation accordingly.

@suhaib-mousa suhaib-mousa requested a review from hikalkan June 26, 2025 11:27
@maliming
Copy link
Member

Thanks @suhaib-mousa
I will review the code and merge it.
Thanks.

@hikalkan
Copy link
Member

The implementation is fine, thanks. But I will revise the documentation part. Then we can merge @maliming

@hikalkan hikalkan merged commit e0fd626 into abpframework:dev Jun 27, 2025
1 of 2 checks passed
@hikalkan
Copy link
Member

I will separately update the doc.

@suhaib-mousa suhaib-mousa deleted the configuration-tenant-resolver branch June 27, 2025 12:55
@hikalkan
Copy link
Member

Updated: 8fdc5c1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants