- Exception message and full stack trace:  Exception of type 'Volo.Abp.BusinessException' was thrown at Volo.Saas.Tenants.TenantManager.ValidateNameAsync(String normalizeName, Nullable1 expectedId) at Volo.Saas.Tenants.TenantManager.CreateAsync(String name, Nullable1 editionId)
How do I know what validations are in place for TenantManager (part of ABP Commercial)? I'm particularly interested in what's happening within ValidateNameAsync.
Thanks
2 Answer(s)
- 
    0The Volo.Saas.Tenants.TenantManager.CreateAsync(string name, Nullable<Guid> editionId)method in ABP Commercial uses internal validation logic to ensure tenant names are valid and unique. The core of this validation is performed in theValidateNameAsyncmethod.Here are the key validations performed by ValidateNameAsync:- Name Not Null or Empty: The tenant name must not be null, empty, or whitespace.
- Name Length: The tenant name must not exceed the maximum allowed length (typically 64 characters, but this can be checked in your entity definition).
- Name Uniqueness: The normalized tenant name must be unique. If another tenant already exists with the same normalized name (case-insensitive, trimmed, etc.), a BusinessExceptionis thrown.
- Name Format: The name may be checked for allowed characters (e.g., no whitespace or special characters), depending on your implementation or any customizations.
- Custom Rules: If you have overridden the TenantManageror repository, you may have additional custom rules (e.g., removing whitespace, regex checks).
 If any of these validations fail, a Volo.Abp.BusinessExceptionis thrown, which is what you are seeing in your stack trace.Example of a custom name validation (from community guidance): public override async Task<Tenant> FindByNameAsync(string name, bool includeDetails = true, CancellationToken cancellationToken = default) { var tenants = await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .OrderBy(t => t.Id).ToListAsync(); return tenants .FirstOrDefault(t => (t.Name == name || TestUrlNamingConvention(t.Name, name))); } private bool TestUrlNamingConvention(string tenantName, string inputName) { var i = string.Concat(inputName.Where(c => !char.IsWhiteSpace(c))).ToLowerInvariant(); var t = string.Concat(tenantName.Where(c => !char.IsWhiteSpace(c))).ToLowerInvariant(); return i == t; }This shows how you can extend or customize the validation logic. Summary: - The default validations are: not null/empty, length, uniqueness, and possibly allowed characters.
- You can override or extend these by customizing the TenantManageror repository.
 Sources: 
 This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon. 
- 
    0hi The latest code of ValidateAsyncmethodpublic virtual async Task ValidateAsync(Tenant tenant) { Check.NotNullOrWhiteSpace(tenant.Name, nameof(tenant.Name)); Check.NotNullOrWhiteSpace(tenant.NormalizedName, nameof(tenant.NormalizedName)); var owner = await TenantRepository.FindByNameAsync(tenant.NormalizedName); if (owner != null && owner.Id != tenant.Id) { throw new BusinessException("Volo.Saas:DuplicateTenantName").WithData("Name", tenant.NormalizedName); } }
 
                                