Table of contents

Can I use HttpClient (C#) in Blazor applications?

Yes, you can use HttpClient in Blazor applications, and it's a core component for making HTTP requests in both Blazor hosting models. Blazor provides excellent support for HTTP operations through dependency injection and async patterns.

Blazor Hosting Models

Blazor offers two hosting models, each with different HttpClient considerations:

  1. Blazor WebAssembly: Runs in the browser using WebAssembly, with HTTP requests executed client-side
  2. Blazor Server: Runs on the server with UI updates sent over SignalR connections

Setup and Configuration

Blazor WebAssembly Setup

In Program.cs (NET 6+):

using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");

// Register HttpClient with base address
builder.Services.AddScoped(sp => new HttpClient 
{ 
    BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) 
});

// Or use HttpClientFactory (recommended)
builder.Services.AddHttpClient("API", client => 
{
    client.BaseAddress = new Uri("https://api.example.com/");
    client.DefaultRequestHeaders.Add("User-Agent", "BlazorApp/1.0");
});

await builder.Build().RunAsync();

Blazor Server Setup

In Program.cs (NET 6+) or Startup.cs:

var builder = WebApplication.CreateBuilder(args);

// Add services
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();

// Register HttpClient using factory pattern (recommended)
builder.Services.AddHttpClient();

// Named HttpClient for specific APIs
builder.Services.AddHttpClient("WeatherAPI", client =>
{
    client.BaseAddress = new Uri("https://api.weather.com/");
    client.Timeout = TimeSpan.FromSeconds(30);
});

var app = builder.Build();

Using HttpClient in Components

Basic Injection and Usage

@page "/weather"
@inject HttpClient Http
@inject IHttpClientFactory HttpClientFactory

<h3>Weather Data</h3>

@if (weather == null)
{
    <p>Loading...</p>
}
else
{
    <ul>
        @foreach (var forecast in weather)
        {
            <li>@forecast.Date.ToShortDateString(): @forecast.Summary (@forecast.TemperatureC°C)</li>
        }
    </ul>
}

@code {
    private WeatherForecast[]? weather;

    protected override async Task OnInitializedAsync()
    {
        try
        {
            // Using injected HttpClient
            weather = await Http.GetFromJsonAsync<WeatherForecast[]>("api/weather");
        }
        catch (HttpRequestException ex)
        {
            // Handle HTTP errors
            Console.WriteLine($"Error fetching weather: {ex.Message}");
        }
    }

    public class WeatherForecast
    {
        public DateTime Date { get; set; }
        public int TemperatureC { get; set; }
        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
        public string? Summary { get; set; }
    }
}

Using Named HttpClient with Factory

@page "/api-data"
@inject IHttpClientFactory HttpClientFactory

@code {
    private ApiResponse? data;

    protected override async Task OnInitializedAsync()
    {
        var client = HttpClientFactory.CreateClient("API");

        try
        {
            data = await client.GetFromJsonAsync<ApiResponse>("data");
        }
        catch (Exception ex)
        {
            // Handle errors
        }
    }
}

HTTP Operations Examples

GET Requests

@code {
    // Simple GET with string response
    private async Task<string> GetStringData()
    {
        return await Http.GetStringAsync("api/text");
    }

    // GET with JSON deserialization
    private async Task<List<Product>> GetProducts()
    {
        return await Http.GetFromJsonAsync<List<Product>>("api/products") ?? new();
    }

    // GET with custom headers
    private async Task<ApiResponse> GetWithHeaders()
    {
        var request = new HttpRequestMessage(HttpMethod.Get, "api/secure-data");
        request.Headers.Add("Authorization", "Bearer " + token);

        var response = await Http.SendAsync(request);
        response.EnsureSuccessStatusCode();

        return await response.Content.ReadFromJsonAsync<ApiResponse>();
    }
}

POST Requests

@code {
    // POST with JSON content
    private async Task<bool> CreateProduct(Product product)
    {
        try
        {
            var response = await Http.PostAsJsonAsync("api/products", product);
            return response.IsSuccessStatusCode;
        }
        catch (HttpRequestException)
        {
            return false;
        }
    }

    // POST with form data
    private async Task<bool> SubmitForm(Dictionary<string, string> formData)
    {
        var formContent = new FormUrlEncodedContent(formData);
        var response = await Http.PostAsync("api/form", formContent);

        return response.IsSuccessStatusCode;
    }

    // POST with file upload
    private async Task<bool> UploadFile(IBrowserFile file)
    {
        using var content = new MultipartFormDataContent();
        using var fileContent = new StreamContent(file.OpenReadStream());

        content.Add(fileContent, "file", file.Name);

        var response = await Http.PostAsync("api/upload", content);
        return response.IsSuccessStatusCode;
    }
}

PUT and DELETE Requests

@code {
    // PUT request
    private async Task<bool> UpdateProduct(int id, Product product)
    {
        var response = await Http.PutAsJsonAsync($"api/products/{id}", product);
        return response.IsSuccessStatusCode;
    }

    // DELETE request
    private async Task<bool> DeleteProduct(int id)
    {
        var response = await Http.DeleteAsync($"api/products/{id}");
        return response.IsSuccessStatusCode;
    }
}

Error Handling and Best Practices

Comprehensive Error Handling

@code {
    private async Task<T?> SafeHttpCall<T>(Func<Task<T>> httpCall) where T : class
    {
        try
        {
            return await httpCall();
        }
        catch (HttpRequestException ex)
        {
            Console.WriteLine($"HTTP Error: {ex.Message}");
            return null;
        }
        catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException)
        {
            Console.WriteLine("Request timed out");
            return null;
        }
        catch (JsonException ex)
        {
            Console.WriteLine($"JSON parsing error: {ex.Message}");
            return null;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Unexpected error: {ex.Message}");
            return null;
        }
    }

    // Usage
    private async Task LoadData()
    {
        var data = await SafeHttpCall(async () => 
            await Http.GetFromJsonAsync<ApiResponse>("api/data"));

        if (data != null)
        {
            // Process data
        }
    }
}

Response Status Checking

@code {
    private async Task<(bool Success, T? Data, string? Error)> GetWithStatusCheck<T>(string endpoint)
    {
        var response = await Http.GetAsync(endpoint);

        if (response.IsSuccessStatusCode)
        {
            var data = await response.Content.ReadFromJsonAsync<T>();
            return (true, data, null);
        }

        var error = response.StatusCode switch
        {
            HttpStatusCode.NotFound => "Resource not found",
            HttpStatusCode.Unauthorized => "Unauthorized access",
            HttpStatusCode.Forbidden => "Access forbidden",
            HttpStatusCode.InternalServerError => "Server error occurred",
            _ => $"Request failed with status: {response.StatusCode}"
        };

        return (false, default(T), error);
    }
}

Blazor-Specific Considerations

CORS in Blazor WebAssembly

// When calling external APIs, ensure CORS is configured on the server
@code {
    protected override async Task OnInitializedAsync()
    {
        try
        {
            // This may fail due to CORS if the API doesn't allow your domain
            var data = await Http.GetFromJsonAsync<ApiData>("https://external-api.com/data");
        }
        catch (HttpRequestException ex)
        {
            // Could be a CORS issue
            Console.WriteLine($"Request failed - check CORS configuration: {ex.Message}");
        }
    }
}

Authentication with HttpClient

@page "/secure-data"
@inject HttpClient Http
@inject IJSRuntime JSRuntime

@code {
    protected override async Task OnInitializedAsync()
    {
        // Get token from localStorage or cookie
        var token = await JSRuntime.InvokeAsync<string>("localStorage.getItem", "authToken");

        if (!string.IsNullOrEmpty(token))
        {
            Http.DefaultRequestHeaders.Authorization = 
                new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
        }

        var secureData = await Http.GetFromJsonAsync<SecureData>("api/secure");
    }
}

Performance Tips

  1. Use IHttpClientFactory: Prevents socket exhaustion and enables better configuration
  2. Dispose appropriately: HttpClient is typically managed by DI container
  3. Use streaming for large responses: Use GetStreamAsync() for large files
  4. Configure timeouts: Set reasonable timeout values
  5. Cache responses: Implement caching for frequently accessed data
// Example of streaming large responses
@code {
    private async Task DownloadLargeFile()
    {
        using var response = await Http.GetAsync("api/large-file", HttpCompletionOption.ResponseHeadersRead);
        using var stream = await response.Content.ReadAsStreamAsync();

        // Process stream in chunks
        var buffer = new byte[8192];
        int bytesRead;

        while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
        {
            // Process chunk
        }
    }
}

HttpClient is fully supported and essential for HTTP operations in Blazor applications. The key is proper configuration through dependency injection and following async/await patterns consistently.

Try WebScraping.AI for Your Web Scraping Needs

Looking for a powerful web scraping solution? WebScraping.AI provides an LLM-powered API that combines Chromium JavaScript rendering with rotating proxies for reliable data extraction.

Key Features:

  • AI-powered extraction: Ask questions about web pages or extract structured data fields
  • JavaScript rendering: Full Chromium browser support for dynamic content
  • Rotating proxies: Datacenter and residential proxies from multiple countries
  • Easy integration: Simple REST API with SDKs for Python, Ruby, PHP, and more
  • Reliable & scalable: Built for developers who need consistent results

Getting Started:

Get page content with AI analysis:

curl "https://api.webscraping.ai/ai/question?url=https://example.com&question=What is the main topic?&api_key=YOUR_API_KEY"

Extract structured data:

curl "https://api.webscraping.ai/ai/fields?url=https://example.com&fields[title]=Page title&fields[price]=Product price&api_key=YOUR_API_KEY"

Try in request builder

Related Questions

Get Started Now

WebScraping.AI provides rotating proxies, Chromium rendering and built-in HTML parser for web scraping
Icon