Open Closed

Unable to set TenantConnectionString for NonDefaultDatabase only #9562


User avatar
0
jfistelmann created

For reference: Github Issue 23187

Module: Volo.SaaS UI: Found at blazor server & wasm (or blazor webapp or whatever this is called by now)

I am not able to save here because of the way the default connection string get's validated. Why do I need that? Because I reverse engineered an existing third party DB using EF Core Power Tools and made it a AbpDbContext which I want to set the connection string for each tenant in my system:

Why can't I just replace TenantManagement you may ask: Because for some reason - when replacing the component - the replaced component is only used when switched to wasm. when still rendering on blazor server - the component does not get replaced :-| (that's maybe worth another issue)

First weird thing - edit modal and create modal seem to validate differently:

they should both use ValidateDefaultConnectionString IMHO

next issue is the validation


protected virtual void ValidateDefaultConnectionString(ValidatorEventArgs e) 
{
    e.Status = !ConnectionStrings.UseSharedDatabase && ConnectionStrings.Default.IsNullOrWhiteSpace()
        ? ValidationStatus.Error
        : ValidationStatus.Success;
    
    e.ErrorText = e.Status == ValidationStatus.Error ? L["The {0} field is required.", L[$"DisplayName:{nameof(ConnectionStrings.Default)}"]] : null;
}

a better version would be:


protected virtual void ValidateDefaultConnectionString(ValidatorEventArgs e) 
{
    if (ConnectionStrings.Default.IsNullOrWhiteSpace())
    {
        e.Status = ValidationStatus.Success;
        return;
    }
    e.Status = !ConnectionStrings.UseSharedDatabase && ConnectionStrings.Default.IsNullOrWhiteSpace()
        ? ValidationStatus.Error
        : ValidationStatus.Success;
    
    e.ErrorText = e.Status == ValidationStatus.Error ? L["The {0} field is required.", L[$"DisplayName:{nameof(ConnectionStrings.Default)}"]] : null;
}

this is because connection string that are NullOrEmpty() get removed anyway - even the default one.


4 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent

    To set a tenant-specific connection string for a non-default (module-specific) database in ABP SaaS, but not require a "Default" connection string, you are running into a limitation of the current validation logic in the SaaS module UI. The validation enforces that the "Default" connection string is required unless "Use Shared Database" is checked, even if you only want to provide a module-specific connection string (e.g., for your DthOrderDb).

    Problem

    • The UI and backend validation require a "Default" connection string, blocking you from saving tenants with only a module-specific connection string.
    • This is a known issue and has been discussed in the community and on GitHub (abpframework/abp#23187).

    Workarounds

    1. Provide a Dummy Default Connection String

    As a temporary workaround, you can provide a valid but unused connection string in the "Default" field (e.g., point it to a harmless or empty database). This will satisfy the validation, and your module-specific connection string will be used by your custom DbContext.

    2. Patch the Validation Logic

    If you control the source, you can patch the validation logic in your fork or override the relevant Blazor component to relax the requirement for the "Default" connection string when at least one module-specific connection string is provided.

    Example (pseudo-code for validation):

    protected virtual void ValidateDefaultConnectionString(ValidatorEventArgs e) 
    {
        var hasAnyModuleConnectionString = ConnectionStrings.ModuleConnectionStrings.Any(x => !x.Value.IsNullOrWhiteSpace());
        e.Status = (!ConnectionStrings.UseSharedDatabase && ConnectionStrings.Default.IsNullOrWhiteSpace() && !hasAnyModuleConnectionString)
            ? ValidationStatus.Error
            : ValidationStatus.Success;
        e.ErrorText = e.Status == ValidationStatus.Error ? L["The {0} field is required.", L[$"DisplayName:{nameof(ConnectionStrings.Default)}"]] : null;
    }
    

    This would allow saving if at least one module-specific connection string is present.

    3. Track the Issue

    The ABP team is aware of this limitation. You can follow or contribute to the discussion and possible fix here:

    • [GitHub Issue #23187](https://github.com/abpframework/abp/issues/23187)

    References


    This is a known gap in the current SaaS module UI logic. Until it's addressed in the framework, the above workarounds are recommended.


    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.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    when replacing the component - the replaced component is only used when switched to wasm. when still rendering on blazor server - the component does not get replaced :-| (that's maybe worth another issue)

    Your custom component needs to add both MyProject and MyProject.Client projects.

    eg: Add a component class in both projects, OR Add this component class to MyProject.Client, and then manually add it to the DI in MyProject.

    Because the web app actual two projects. One is Blazor Server and the other is Blazor WebAssembly (WASM).

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    First weird thing - edit modal and create modal seem to validate differently:

    I will check this.

    Thanks.


    We changed the code after Volo.Saas >= 9.1.0

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    A better version would be:

    protected virtual void ValidateDefaultConnectionString(ValidatorEventArgs e) 
    {
        if (ConnectionStrings.Default.IsNullOrWhiteSpace())
        {
            e.Status = ValidationStatus.Success;
            return;
        }
        e.Status = !ConnectionStrings.UseSharedDatabase && ConnectionStrings.Default.IsNullOrWhiteSpace()
            ? ValidationStatus.Error
            : ValidationStatus.Success;
        
        e.ErrorText = e.Status == ValidationStatus.Error ? L["The {0} field is required.", L[$"DisplayName:{nameof(ConnectionStrings.Default)}"]] : null;
    }
    

    If you select the Use the shared database UI element will show up and we will check the ConnectionStrings.Default

Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.0.0-preview. Updated on July 11, 2025, 11:35