Calling a Web API with HttpClient
Use HttpClient through a typed service to retrieve JSON data from a web API and display it safely.
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;
}
}
}
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.