Open Closed

SaaS tenant connection strings not saving + Clarification about SQL Server remote instance support #10190


User avatar
0
Belen.molinaMA created

Hello ABP Team,

I would like to request support regarding two related issues with SaaS tenant connection strings in ABP Commercial.

  1. The main issue: the connection string is validated but never saved

When using the Angular UI to configure a tenant's connection string:

The endpoint CheckConnectionStringAsync is called correctly.

The backend validates the connection successfully (returns true).

However, when clicking Save, the Angular application never sends the PUT request:

PUT /api/saas/tenants/{id}/connection-strings

This PUT action never appears in browser Network logs, and therefore the backend never receives it.

Permissions are not the problem — my admin role has all SaaS tenant permissions including ManageConnectionStrings.

Questions:

Under what conditions does the Angular SaaS UI skip the PUT request?

Does the UI require the connection string name to always be "Default"?

If the database already contains a connection string with a different name (e.g., "Financial"), does the UI ignore it and therefore never trigger the update?

Is this a known issue in the current ABP Angular version?

  1. Question regarding SQL Server remote instances (critical):

I am trying to use a remote SQL Server instance with the following format:

Server=45.xxx.xxx.xxx\SQLEXPRESS2014;Database=Financial;User Id=xxx;Password=xxx;TrustServerCertificate=True;

The CheckConnectionString endpoint returns TRUE, so the connection works.

However, I want to confirm the expected/official behavior:

Questions:

Does ABP support SQL Server remote instances using IP\InstanceName format, or is ABP officially limited to localhost connections?

If ABP supports remote SQL servers, what is the correct recommended connection-string format for:

Named instances?

SQL Browser disabled?

Specific ports?

When using:

Server=45.xxx.xxx.xxx\InstanceName;

should ABP automatically resolve the SQL Browser port, or must the instance be accessed using:

Server=45.xxx.xxx.xxx,PortNumber;

Is there any known limitation in ABP SaaS tenant connection-string checking related to remote or named SQL Server instances?

Additional context

ABP Commercial 8.x

Frontend: Angular

Backend: ASP.NET Core

Multi-tenancy enabled (Database-per-tenant mode)

CheckConnectionString works fine in all tests

The actual save/PUT never happens

I can provide a SQL dump of SaasTenantConnectionStrings if needed

Thank you very much, I will wait for your guidance.


4 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    1. Solution Part 1 — Angular SaaS tenant connection string “Save” never sends PUT

    Why the PUT may be skipped

    • The SaaS Angular UI only enables the Save action when:
      • The form is valid.
      • The connection string check has succeeded for the current “Default” connection.
      • The value is actually changed compared to the loaded value.
    • The modal manages one “Default” connection string entry. Arbitrary names (like “Financial”) are not supported by the built-in UI. If a tenant has only a non-Default entry in the database, the UI will not bind it and Save may remain disabled (thus no PUT).
    • If you customized encryption or altered the DTO without reflecting the UI state (e.g., Check succeeded on a different temporary value but the bound control is unchanged), the UI may consider there is “no change” and skip PUT.
    • If you do not have the “ManageConnectionStrings” permission in the browser session (e.g., token mismatch, stale claims), the Save button is disabled and no PUT is issued.

    Definitive checks and fixes

    • Use “Default” as the connection name when working with the built-in SaaS Tenants modal. The Angular UI expects only “Default” for the editable field.
    • Ensure the form control value actually changes before saving. Type or paste the final connection string into the Default field and click Test, then Save.
    • Verify the permission in the current session: AbpSaas.Tenants.ManageConnectionStrings. If you recently granted the permission, re-login to refresh claims.
    • Confirm there is no validation error on the modal: the UI will not submit if the form is invalid.
    • If you previously stored a differently named connection string (e.g., “Financial”), migrate it to “Default” for the built-in modal, or extend the UI (custom component) to manage multiple named connection strings and call PUT /api/saas/tenants/{id}/connection-strings with your own payload.
    • If you encrypt connection strings on the client or server, make sure the value bound to the input is the same one that passed CheckConnectionString and is considered “dirty” so the Save button becomes enabled.

    Server-side note for encrypted scenarios (ABP ≥ 7.0 validates connection strings):

    • The SaaS module validates connection strings before saving. If you store encrypted values, replace the default IConnectionStringChecker (or override the TenantAppService’s internal check) to decrypt before validation:
    [Dependency(ReplaceServices = true)]
      [ExposeServices(typeof(IConnectionStringChecker))]
      public class EncryptedConnectionStringChecker
          : SqlServerConnectionStringChecker, IConnectionStringChecker, ITransientDependency
      {
          private readonly IStringEncryptionService _encryption;
    
          public EncryptedConnectionStringChecker(IStringEncryptionService encryption)
          {
              _encryption = encryption;
          }
    
          public override async Task<AbpConnectionStringCheckResult> CheckAsync(string connectionString)
          {
              var decrypted = _encryption.Decrypt(connectionString);
              return await base.CheckAsync(decrypted);
          }
      }
    
    • This guarantees that the server “Test connection” endpoint and the save pipeline both succeed when values are encrypted at rest.

    Part 2 — SQL Server remote/named instance support and formats

    What ABP supports

    • ABP uses ADO.NET/EF Core providers. It fully supports remote SQL Server hosts, named instances, and custom ports. There is no localhost limitation in ABP.

    Recommended connection string formats

    • Named instance (SQL Browser enabled):
      • Server=45.xxx.xxx.xxx\InstanceName;Database=Financial;User Id=...;Password=...;TrustServerCertificate=True;
      • The SQL client will query SQL Browser (UDP 1434) to resolve the dynamic port.
    • SQL Browser disabled or firewalled:
      • You must specify the port explicitly (no backslash instance in practice):
      • Server=45.xxx.xxx.xxx,14330;Database=Financial;User Id=...;Password=...;TrustServerCertificate=True;
      • If you still want to keep InstanceName for clarity, it won’t be used to resolve the port without SQL Browser; the port takes precedence.
    • Default instance on a custom port:
      • Server=45.xxx.xxx.xxx,PortNumber;Database=...;...

    Behavior expectations

    • With Server=IP\InstanceName:
      • If SQL Browser is reachable, resolution to the instance’s port is automatic.
      • If SQL Browser is not reachable, the connection will fail unless you use the explicit port form Server=IP,Port.
    • ABP’s CheckConnectionString endpoint does not add any special logic for instance resolution; it relies on the provider. If a manual port is needed in your environment, use the comma + port format.
    • Known limitations: none ABP-specific regarding remote or named instances. Connectivity issues generally come from SQL Browser disabled, firewall rules, or TCP/IP protocol not enabled on the SQL Server.

    Actionable guidance for your case

    • Prefer the simplest working format for production stability:
      • If SQL Browser is disabled: Server=45.xxx.xxx.xxx,14330;Database=Financial;User Id=...;Password=...;TrustServerCertificate=True;
      • If SQL Browser is enabled and allowed: Server=45.xxx.xxx.xxx\SQLEXPRESS2014;Database=Financial;User Id=...;Password=...;TrustServerCertificate=True;
    • Keep using the “Default” connection name in the SaaS modal.
    • Since CheckConnectionString already returns true, focus on ensuring:
      • The UI field is “Default”, changed and valid, then Save should send PUT.
      • If you store encrypted values, replace IConnectionStringChecker to decrypt before validation as shown above so both Test and Save paths succeed.
    1. Sources
    • https://github.com/abpframework/abp
    • https://abp.io/docs/latest/solution-templates/layered-web-application/database-configurations
    • https://abp.io/support/questions/4132

    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
    Belen.molinaMA created

    The ABP application host cannot reach the remote SQL Server because the required TCP port is not open / reachable.

    This explains the behavior:

    Using localhost works → The API host can reach the SQL instance immediately.

    Using the remote connection string fails → ABP rejects the string as “invalid” because the host cannot establish a TCP connection to the SQL server.

    It does not depend on permissions → I can save other connection strings (e.g., localhost) in the same session with the same user.

    The PUT endpoint only fails for the remote connection → The same user, same role, same claims, same token can save local DBs successfully.

    The error appears ONLY when the SQL server is remote → This confirms that the network path, not ABP permissions, is blocking the connection.

    So, the 403 response from:

    PUT /api/saas/tenants/{id}/connection-strings

    is triggered because ABP internally considers the connection string invalid, due to the SQL host being unreachable from the application server (port closed, SQL Browser unreachable, or firewall blocking).

    Once the required SQL port is opened and reachable, the connection string should save correctly.

  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    1. Solution Your diagnosis is correct and matches ABP SaaS behavior since the connection string validation was introduced: when the application host cannot establish a TCP connection to the SQL Server defined in the tenant’s connection string, the SaaS service marks the connection string as invalid and rejects saving it. In that case, the Angular UI will attempt to save, the server-side validation fails, and the save endpoint can return 403/validation error based on the implementation.

    What to do

    • Ensure network reachability from the application host to the SQL Server:
      • Open the SQL Server TCP port on the target host and firewall.
      • If you use a named instance with SQL Browser, allow UDP 1434.
      • If SQL Browser is disabled or blocked, use Server=IP,Port in the connection string.
      • Verify TCP/IP protocol is enabled on SQL Server.
    • Use a connection string format appropriate to your environment:
      • Named instance, SQL Browser reachable:
        • Server=45.xxx.xxx.xxx\InstanceName;Database=...;User Id=...;Password=...;TrustServerCertificate=True;
      • SQL Browser disabled/firewalled or static port:
        • Server=45.xxx.xxx.xxx,14330;Database=...;User Id=...;Password=...;TrustServerCertificate=True;
    • Re-test with the CheckConnectionString action. Once it returns Connected=true from the app host to the remote SQL Server, Save should succeed.
    • If you store encrypted tenant connection strings, replace IConnectionStringChecker to decrypt before validation (this avoids false negatives during validation):
    [Dependency(ReplaceServices = true)]
      [ExposeServices(typeof(IConnectionStringChecker))]
      public class EncryptedConnectionStringChecker
          : SqlServerConnectionStringChecker, IConnectionStringChecker, ITransientDependency
      {
          private readonly IStringEncryptionService _encryption;
    
          public EncryptedConnectionStringChecker(IStringEncryptionService encryption)
          {
              _encryption = encryption;
          }
    
          public override async Task<AbpConnectionStringCheckResult> CheckAsync(string connectionString)
          {
              var decrypted = _encryption.Decrypt(connectionString);
              return await base.CheckAsync(decrypted);
          }
      }
    

    Key points

    • ABP does not limit connections to localhost. It relies on the ADO.NET/EF Core provider; remote SQL Servers, named instances, and custom ports are fully supported. Failures here are almost always networking or SQL configuration (port, firewall, SQL Browser, TCP/IP).
    • The save flow rejects connection strings when the checker cannot connect. Fix network reachability or specify the correct port, and the PUT will succeed.
    1. Sources
    • https://github.com/abpframework/abp
    • https://abp.io/support/questions/4132
    • https://abp.io/support/questions/9507

    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

    You are right. ABP will check your connection strings (SqlServerConnectionStringChecker) before saving to the database.

    https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo/Abp/EntityFrameworkCore/ConnectionStrings/SqlServerConnectionStringChecker.cs#L14-L38

    Thanks.

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.1.0-preview. Updated on December 08, 2025, 08:24
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.