HttpClient Not fetching BaseAddress

Prathamesh Shende 376 Reputation points
2021-06-15T15:59:35.55+00:00

I have create
Blazore WASM App and with Identity Server 4 So
IHttpClientFactory and add default httpClient scope
but its showin Null HttpClient.BaseAddress after I fetching into services.cs file

this is files
Program.cs

public class Program
{
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.Logging.SetMinimumLevel(LogLevel.Debug);
//builder.Logging.AddProvider(new CustomLoggingProvider(LogLevel.Error));
builder.RootComponents.Add<App>("#app");

        builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

        // We register a named HttpClient here for the API
        builder.Services.AddHttpClient("api")
            .AddHttpMessageHandler(sp =>
            {
                var handler = sp.GetService<AuthorizationMessageHandler>()
                    .ConfigureHandler(
                        authorizedUrls: new[] { new Uri(builder.HostEnvironment.BaseAddress).ToString() },
                        scopes: new[] { "api1", "email" });
                return handler;
            });

        // we use the api client as default HttpClient
        builder.Services.AddScoped(sp => sp.GetService<IHttpClientFactory>().CreateClient("api"));

        builder.Services
            .AddOidcAuthentication(options =>
            {
                builder.Configuration.Bind("oidc", options.ProviderOptions);
                options.UserOptions.RoleClaim = "role";
            }).AddAccountClaimsPrincipalFactory<ArrayClaimsPrincipalFactory<RemoteUserAccount>>();


        builder.Services.AddScoped<SetupsService>();
        await builder.Build().RunAsync();
    }
}

public class SetupsService
{

    HttpClient _httpClient;
    IHttpClientFactory _httpClientFactory;
    public SetupsService(IHttpClientFactory httpClientFactory)
    {
        _httpClientFactory = httpClientFactory;
        _httpClient = _httpClientFactory.CreateClient("api");
    }

    public async Task<List<Setup>> GetSetupsAsync()
    {
        return await _httpClient.GetFromJsonAsync<List<Setup>>($"{ _httpClient.BaseAddress } api/Setups");
    }

``}

here its show null and not fetching baseaddress

Blazor
Blazor
A free and open-source web framework that enables developers to create web apps using C# and HTML being developed by Microsoft.
1,383 questions
0 comments No comments
{count} votes

Accepted answer
  1. Prathamesh Shende 376 Reputation points
    2021-06-15T16:41:55.16+00:00

    If I Remove the AddHttpClient("api") code then
    builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
    it will fetch code directly and it will set the base Address as per environment.

    Identity Server 4 Applied IHttpClientFactory that's why this problem occurs
    Is there any option to Set Base Adderss in Program.cs File and use it into service.cs files?

    1 person found this answer helpful.

2 additional answers

Sort by: Most helpful
  1. Michael Taylor 47,806 Reputation points
    2021-06-15T16:10:45.003+00:00

    I don't see in your HttpClient setup code that you ever set BaseAddress. You define a custom message handler but nowhere is the base address set.

    Also, in your actual client usage you shouldn't include the base address, it is added automatically. When you provide a URI to any of the methods it looks to see if it is an absolute URL or not. If it is absolute then it uses the address as is. This is the non-standard approach, in my opinion. If you go this route then you don't need to set BaseAddress as it won't use it.

    However in most cases you use a relative URL. In that case the BaseAddress value is automatically added to the call. This is the preferred approach as each client should ideally be for the same base address and only the resource(s) change. Note however that when setting the bae address ensure it ends with a slash. In older versions of the implementation (may not be an issue now) the client doesn't join the addresses properly without it.

    //Set up (just an example of setting the base address, use your existing code
    new HttpClient() { BaseAddress = "https://www.tempuri.org/" };
    
    //Usage
    client.GetFromJsonAsync<List<Setup>>("api/setups");
    
    1 person found this answer helpful.

  2. AgaveJoe 26,191 Reputation points
    2021-06-15T19:48:34.573+00:00

    I think you misunderstand named HttpClients and factories. You get to configure the HttpClient factory to return a named client. The named client can have a base address that you configure. This is very convenient when you have one or many REST services. Anyway, the standard docs cover all the details. I think you'll be interested in giving the docs a good reading.

    Keep in mind your current configuration always points to the current host. That might be fine if your application never calls a remote service. I usually have configuration similar to the following where the API URL is stored in configuration.

    var DefaultApi = builder.Configuration.GetValue<string>("ApiUrl:DefaultApi");  
      
    builder.Services.AddScoped(sp =>   
        new HttpClient { BaseAddress = new Uri(DefaultApi) });  
    

    Configuration

    {  
      "ApiUrl": {  
        "DefaultApi": "https://localhost:44384/"  
      }  
    
    1 person found this answer helpful.
    0 comments No comments