Blazor is an experimental project. It changes frequently and evolves rapidly. Therefore, it is possible that some content on this website is already outdated.
Developers who are used to writing C# code in ASP.NET will find it very simple to consume web APIs with Blazor. All the usual classes (e.g. System.Net.Http.HttpClient
) and language constructs (e.g. async
and await
) are available. Therefore, reading data from a server and printing it in the console looks like this in Blazor:
@page "/"
@inject HttpClient Http
<button onclick=@(async () => await PrintWebApiResponse())>Print Web API Response</button>
@functions {
private async Task PrintWebApiResponse()
{
var response = await Http.GetStringAsync("/api/Customer");
Console.WriteLine(response);
}
}
Note that we are using dependency injection to get an instance of the System.Net.Http.HttpClient
class. Once we have it, it is business as usual.
The browser’s firewall would not allow Blazor to directly do network communication. All network traffic has to go through the browser. Therefore, Blazor’s C# implementation has to pass our HTTP request to Blazor’s JavaScript-part. How is that possible if we use C# usual System.Net.Http.HttpClient
class?
The solution is the abstract base class System.Net.Http.HttpMessageHandler
. It represents an abstraction layer for sending HTTP requests as an asynchronous operation. HttpClient
takes an instance of this class in one of its constructor. Blazor contains an implementation of HttpMessageHandler
that hands over HTTP requests to JavaScript (Microsoft.AspNetCore.Blazor.Browser.Http.BrowserHttpMessageHandler
, see source on GitHub). If you get your HttpClient
using Blazor’s dependency injection, you will get an instance that is already wired up with BrowserHttpMessageHandler
.
The real HTTP request is sent using the browser’s fetch API (see source on GitHub).
Blazor comes with SimpleJson embedded (source code is part of the Blazor DLLs, not a referenced NuGet package), a JSON library for portable .NET apps. The static class Microsoft.AspNetCore.Blazor.HttpClientJsonExtensions
(see source on GitHub) contains extensions methods for HttpClient
that make it easier to consume JSON-based web APIs in Blazor.
The following sample demonstrates the use of a RESTful Web API implemented with ASP.NET Core and Entity Framework. You can find the complete sample on GitHub.
@page "/"
@using RestApi.Shared
@inject HttpClient Http
<h1>Customer List</h1>
<p>This component demonstrates fetching data from the server.</p>
<button onclick=@(async () => await PrintWebApiResponse())>Print Web API Response</button>
<button onclick=@(async () => await FillWithDemoData())>Fill with demo data</button>
<button onclick=@(async () => await DeleteAllCustomers())>Delete all customers</button>
@if (Customers == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class='table'>
<thead>
<tr>
<th>ID</th>
<th>First Name</th>
<th>Last Name</th>
<th>Department</th>
</tr>
</thead>
<tbody>
@foreach (var customer in Customers)
{
<tr>
<td>@customer.ID</td>
<td>@customer.FirstName</td>
<td>@customer.LastName</td>
<td>@customer.Department</td>
</tr>
}
</tbody>
</table>
}
@functions {
private Customer[] Customers { get; set; }
protected override async Task OnInitAsync()
{
await RefreshCustomerList();
}
private async Task RefreshCustomerList()
{
Customers = await Http.GetJsonAsync<Customer[]>("/api/Customer");
StateHasChanged();
}
private async Task FillWithDemoData()
{
for (var i = 0; i < 10; i++)
{
await Http.SendJsonAsync(HttpMethod.Post, "/api/Customer", new Customer
{
FirstName = "Tom",
LastName = $"Customer {i}",
Department = i % 2 == 0 ? "Sales" : "Research"
});
}
await RefreshCustomerList();
}
private async Task DeleteAllCustomers()
{
foreach (var c in Customers)
{
await Http.DeleteAsync($"/api/Customer/{c.ID}");
}
await RefreshCustomerList();
}
private async Task PrintWebApiResponse()
{
var response = await Http.GetStringAsync("/api/Customer");
Console.WriteLine(response);
}
}