Lesson 9 of 10

Calling a Web API with HttpClient

Use HttpClient through a typed service to retrieve JSON data from a web API and display it safely.

Visual Studio 2026.NET 10Beginner friendly

Blazor applications often retrieve data from web APIs. For server-side components, a clean approach is to use HttpClient through a typed service registered with dependency injection.

1. Create the API model

Create Models/Post.cs:

namespace BlazorTutorialApp.Models;

public class Post
{
    public int Id { get; set; }
    public string Title { get; set; } = "";
    public string Body { get; set; } = "";
}

2. Create PostApiService.cs

using System.Net.Http.Json;
using BlazorTutorialApp.Models;

namespace BlazorTutorialApp.Services;

public class PostApiService
{
    private readonly HttpClient http;

    public PostApiService(HttpClient http)
    {
        this.http = http;
    }

    public async Task<List<Post>> GetPostsAsync()
    {
        return await http.GetFromJsonAsync<List<Post>>("posts?_limit=5")
               ?? new List<Post>();
    }
}

3. Register the typed HttpClient

Add this before builder.Build() in Program.cs:

builder.Services.AddHttpClient<PostApiService>(client =>
{
    client.BaseAddress = new Uri("https://jsonplaceholder.typicode.com/");
});

4. Create ApiDemo.razor

@page "/api-demo"
@using BlazorTutorialApp.Models
@using BlazorTutorialApp.Services
@inject PostApiService Api

<h1>Web API Demo</h1>

@if (isLoading)
{
    <p>Loading posts...</p>
}
else if (!string.IsNullOrWhiteSpace(errorMessage))
{
    <p class="text-danger">@errorMessage</p>
}
else
{
    @foreach (var post in posts)
    {
        <div class="card p-3 mb-3">
            <h4>@post.Title</h4>
            <p>@post.Body</p>
        </div>
    }
}

@code {
    private List<Post> posts = new();
    private bool isLoading = true;
    private string errorMessage = "";

    protected override async Task OnInitializedAsync()
    {
        try
        {
            posts = await Api.GetPostsAsync();
        }
        catch (Exception ex)
        {
            errorMessage = $"Could not load data: {ex.Message}";
        }
        finally
        {
            isLoading = false;
        }
    }
}
This example uses a public demo API.

An internet connection is required. In a production app, replace the base address with your own API and use appropriate authentication, validation, and error handling.

5. Important pattern

Keep HTTP logic in a service instead of scattering API calls across pages. This makes components easier to read and lets you replace the API implementation later.

Try it yourself

Change the query from _limit=5 to _limit=10 and show the post ID before each title.