Open Closed

Add HttpClient for each tenant in configure services #2029


User avatar
0
rcalv002 created
  • ABP Framework version: v4.4.3
  • UI type: MVC
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): No
  • Exception message and stack trace:
  • Steps to reproduce the issue:"

I'm storing tenant level configuration using the SettingsManager on each tenant. I'd like to register an httpclient in configureservices for each tenant using this configuration data for each tenant.

Whats the correct way to do this? I would need to

  • Get the list of tenants
  • Change to each tenant
  • Retrieve the configuration with the setting manager?
  • Register the named httpclient with the configuration values (baseurl, etc)

Could you provide an example or documentation of how to consume these services (settingmanager?, tenantmanager?) in configure service method of the application module?

I can then use the correct httpclient when a call is needed to the external remote service of that tenant.

What happens when the tenant updates their configuration, I'd need to deregister and register a new httpclient for them?


11 Answer(s)
  • User Avatar
    0
    enisn created
    Support Team .NET Developer

    Hi,

    Have you tried to configure your HttpContext in ConfigureServices:

    context.Services.AddTransient<HttpClient>(sp =>
    {
        // Get services you need.
        var currentTenant = sp.GetService<ICurrentTenant>();
        var settingManager = sp.GetService<ISettingManager>();
    
        // Create instance of HttpClient
        var httpClient = new HttpClient();
        
        // Make your modifications here
        httpClient.DefaultRequestHeaders.Add("Tenant", currentTenant.Name);
    
        // Return it to DI Container, It'll inject where you use.
        return httpClient;
    });
    
  • User Avatar
    0
    enisn created
    Support Team .NET Developer

    Also you can use AsyncHelper to execute async actions in ConfigureServices:

    var baseAddress = AsyncHelper.RunSync(() => settingManager.GetOrNullForCurrentTenantAsync("BaseAddress"));
    httpClient.BaseAddress = new Uri(baseAddress);
    
  • User Avatar
    0
    rcalv002 created

    Hi Enisn, Thanks for the feedback on this. I will try this, but I thought it was bad practice to spool up new httpclients everytime it was needed and instead we should use httpclientfactory? Can I share what I have done so far for this point and get your feedback?

    P.S before opening the question I tried for some hours and couldnt get any service back in configure service, always receive the exception

    System.ArgumentNullException: 'Value cannot be null. (Parameter 'provider')'

  • User Avatar
    0
    enisn created
    Support Team .NET Developer

    Hi Enisn, Thanks for the feedback on this. I will try this, but I thought it was bad practice to spool up new httpclients everytime it was needed and instead we should use httpclientfactory? Can I share what I have done so far for this point and get your feedback?

    P.S before opening the question I tried for some hours and couldnt get any service back in configure service, always receive the exception

    System.ArgumentNullException: 'Value cannot be null. (Parameter 'provider')'

    Can you share more code? I can't understand from this line why your ServiceProvider is null

  • User Avatar
    0
    rcalv002 created

    Hi Enisn, sure. Im looking for the list of tenants so i can then get the settings for each and register these clients

    The call for ICurrentTenant inside the add transient seems to work as it returns null (expected right?) But just trying to retrieve from the getrequireservice is null

  • User Avatar
    0
    enisn created
    Support Team .NET Developer

    You can't call a service out of a Configure method, because DI Container hasn't be built yet.

    In the .AddTransient method, I'm sure it works. When you inject a HttpClient, that method will be executed and create a HttpClient to inject to your required class. If you want to debug, put a breakpoint inside .AddTransient() method, and create a request to an method of appservice which injects HttpClient

  • User Avatar
    0
    rcalv002 created

    Hi Enisn,

    Thanks for the info, yes I know how to add an http client, if you check my original question here its how to loop through the list of tenants so i can add http clients for each tenant, could you please provide an example of how to loop the tenants in my configure services so i can add required httpclients?

    You can see currently I'm doing this, I'm missing the tenant list and specific settings part.

  • User Avatar
    0
    rcalv002 created

    bump

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi rcalv002

    Maybe you can consider to use AbpDynamicOptionsManager, Call SetAsync method before using HTTP client.

    https://github.com/abpframework/abp/pull/6333#issue-749741707

  • User Avatar
    0
    rcalv002 created

    Hi Maliming

    Can I list the tenants in my DB in my configureservices on application module? If yes, can you show a sample please?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Can I list the tenants in my DB in my configureservices on application module?

    The built-in service does not support this.

Made with ❤️ on ABP v8.2.0-preview Updated on March 25, 2024, 15:11