locked
Blazor wasm problem with using httpClient to access appsettings.json file! RRS feed

  • Question

  • User-79977429 posted

    Hi

    In my blazor wasm project, i have a method inside a class which consume web api to get data like this :

    public async Task<List<Patient>> GetPatientsAsync()
            {
                List<Patient> lstPatients = null;
                HttpClient httpClient = new HttpClient();
                httpClient.BaseAddress = new Uri("http://localhost:27083");
                lstPatients = await httpClient.GetJsonAsync<List<Patient>>("api/Patients");

                return lstPatients;
            }

    The above codes works correctly. However, to avoid hard coding apiUrl i've add appsettings.json file inside wwwroot folder and add my apiUrl setting as follow :

    {
      "ApiUrl": "http://localhost:27083"
    }

    Then, add a separate class to hold settings as follow :

    public class Settings
        {
            public string ApiUrl { get; set; }
        }

    And then add another class named Utils, to access settings as follow :

    public static async Task<string> GetApiUrl()
            {
                string strResult = string.Empty;
                using (HttpClient httpClient = new HttpClient())
                {
                    var objSetting = await httpClient.GetJsonAsync<Settings>("appsettings.json");
                    strResult = objSetting.ApiUrl;
                }
                return strResult;
            }

    And changed GetPatientsAsync as follow (to get apiUrl from appsettings.json instead of hard coding) :

    public async Task<List<Patient>> GetPatientsAsync()
            {
                List<Patient> lstPatients = null;
                HttpClient httpClient = new HttpClient();          
                httpClient.BaseAddress = new Uri(Utils.GetApiUrl().Result);
                lstPatients = await httpClient.GetJsonAsync<List<Patient>>("api/Patients");

                return lstPatients;
            }

    But i'm facing this error in my browser's console :

    Unhandled exception rendering component: An invalid request URI was provided. The request URI must either be an absolute URI or BaseAddress must be set. System.InvalidOperationException: An invalid request URI was provided. The request URI must either be an absolute URI or BaseAddress must be set.

    Where is my problem & how to solve it?

    Thanks in advance

    Monday, March 29, 2021 10:10 PM

Answers

  • User475983607 posted

    I do not understand the new code.  Go back to the first code and just use HttpClient options to set the base URL.  Keep in mind, the default Blazor template is configured to use the current Blazor web app URL.  If you are not sure what to do, just create a new Blazor application and take a look at the project.cs file.

    public static async Task Main(string[] args)
    {
        var builder = WebAssemblyHostBuilder.CreateDefault(args);
        builder.RootComponents.Add<App>("#app");
    
        builder.Services.AddScoped(sp => 
        new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
    
        await builder.Build().RunAsync();
    }

    Then take a look at the FetchData.razor page.  Notice the host is not hard coded...

        protected override async Task OnInitializedAsync()
        {
            forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/weather.json");
        }

    Replace builder.HostEnvironment.BaseAddress with whatever URL you like.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, March 29, 2021 10:23 PM
  • User475983607 posted

    Now i want to get the above url (http://localhost:27083) from appsettings.json file which i told in my first post at this thread.

    Can u help me how to accomplish this?

    The appsettings.json file is in the wwwroot folder.

    {
      "ApiUrl": {
        "DefaultApi": "https://localhost:44384/"
      }
    }

    Main() reads the configuration using standard syntax and uses it to set the base URL.

    public class Program
    {
        public static async Task Main(string[] args)
        {
            var builder = WebAssemblyHostBuilder.CreateDefault(args);
            builder.RootComponents.Add<App>("#app");
    
            var DefaultApi = builder.Configuration.GetValue<string>("ApiUrl:DefaultApi");
    
            builder.Services.AddScoped(sp => 
                new HttpClient { BaseAddress = new Uri(DefaultApi) });
    
            await builder.Build().RunAsync();
        }
    }

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, March 30, 2021 12:04 AM

All replies

  • User475983607 posted

    I do not understand the new code.  Go back to the first code and just use HttpClient options to set the base URL.  Keep in mind, the default Blazor template is configured to use the current Blazor web app URL.  If you are not sure what to do, just create a new Blazor application and take a look at the project.cs file.

    public static async Task Main(string[] args)
    {
        var builder = WebAssemblyHostBuilder.CreateDefault(args);
        builder.RootComponents.Add<App>("#app");
    
        builder.Services.AddScoped(sp => 
        new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
    
        await builder.Build().RunAsync();
    }

    Then take a look at the FetchData.razor page.  Notice the host is not hard coded...

        protected override async Task OnInitializedAsync()
        {
            forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/weather.json");
        }

    Replace builder.HostEnvironment.BaseAddress with whatever URL you like.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, March 29, 2021 10:23 PM
  • User-79977429 posted

    Hi again!

    Many thanks, It works!

    In main method (at Program.cs class) I've replaced this line :

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

    with this :

    builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri("http://localhost:27083") });

    And it works!

    Now i want to get the above url (http://localhost:27083) from appsettings.json file which i told in my first post at this thread.

    Can u help me how to accomplish this?

    Thanks in advance

    Monday, March 29, 2021 10:57 PM
  • User475983607 posted

    Now i want to get the above url (http://localhost:27083) from appsettings.json file which i told in my first post at this thread.

    Can u help me how to accomplish this?

    The appsettings.json file is in the wwwroot folder.

    {
      "ApiUrl": {
        "DefaultApi": "https://localhost:44384/"
      }
    }

    Main() reads the configuration using standard syntax and uses it to set the base URL.

    public class Program
    {
        public static async Task Main(string[] args)
        {
            var builder = WebAssemblyHostBuilder.CreateDefault(args);
            builder.RootComponents.Add<App>("#app");
    
            var DefaultApi = builder.Configuration.GetValue<string>("ApiUrl:DefaultApi");
    
            builder.Services.AddScoped(sp => 
                new HttpClient { BaseAddress = new Uri(DefaultApi) });
    
            await builder.Build().RunAsync();
        }
    }

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, March 30, 2021 12:04 AM
  • User-79977429 posted

    Thanks mgebhard

    It works!

    Tuesday, March 30, 2021 1:25 PM