100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Consuming REST APIs

Learn how to call web APIs from a .NET MAUI app using IHttpClientFactory, System.Text.Json, and connectivity-aware error handling.

Practical MAUIIntermediate10 min readJul 10, 2026
Analogies

Consuming REST APIs in .NET MAUI

Most real-world MAUI apps are thin clients over a backend: they fetch data from a REST API, render it, and push changes back. .NET MAUI reuses the same HTTP stack as ASP.NET Core, so the patterns you already know from server-side C# — HttpClient, System.Text.Json, async/await — carry over directly, with a few mobile-specific wrinkles around connectivity, certificates, and platform networking permissions.

🏏

Cricket analogy: Just as a cricket team relies on a scouting report from the analytics department before walking out to bat, a MAUI screen relies on data pulled from a REST API before it can render anything meaningful to the user.

HttpClient and IHttpClientFactory

Creating a raw new HttpClient() per request is a well-known anti-pattern because each instance holds its own connection pool, and disposing them rapidly can exhaust available sockets under load — a problem that is just as real on a phone juggling background sync as on a server. MAUI apps should instead register clients through IHttpClientFactory, wired up in MauiProgram.cs via builder.Services.AddHttpClient("Api", c => c.BaseAddress = new Uri("https://api.example.com/")), and then inject IHttpClientFactory (or a named/typed client) into view models via the DI container that MAUI configures for you.

🏏

Cricket analogy: It's like a franchise not letting every branch buy its own delivery van outright — instead a central fleet-management service issues vehicles on demand and reclaims them, which is exactly what IHttpClientFactory does with connections.

csharp
// MauiProgram.cs
public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts => fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"));

        builder.Services.AddHttpClient("Api", client =>
        {
            client.BaseAddress = new Uri("https://api.example.com/");
            client.Timeout = TimeSpan.FromSeconds(15);
        });

        builder.Services.AddSingleton<IProductService, ProductService>();
        builder.Services.AddTransient<ProductsViewModel>();

        return builder.Build();
    }
}

Serializing and Deserializing JSON

System.Text.Json is the default serializer in MAUI, exposed through JsonSerializer.Deserialize<T> and its async counterpart ReadFromJsonAsync<T> on HttpContent. Model classes should mirror the API's casing (JsonPropertyName attributes when the API uses snake_case), and for apps that publish with Native AOT or full trimming you should switch to a source-generated JsonSerializerContext so reflection-based serialization doesn't get trimmed away or slow the first request.

🏏

Cricket analogy: It's like translating a scorecard from one cricket board's format into your own broadcaster's on-screen graphics template before you can display it — JSON deserialization maps the API's shape onto your app's model.

csharp
public record Product(
    [property: JsonPropertyName("product_id")] int Id,
    [property: JsonPropertyName("product_name")] string Name,
    decimal Price);

public class ProductService : IProductService
{
    private readonly HttpClient _http;

    public ProductService(IHttpClientFactory factory)
        => _http = factory.CreateClient("Api");

    public async Task<List<Product>> GetProductsAsync(CancellationToken ct = default)
    {
        var products = await _http.GetFromJsonAsync<List<Product>>("api/products", ct);
        return products ?? new List<Product>();
    }
}

Calling APIs from a ViewModel

View models typically expose an [RelayCommand] (from the CommunityToolkit.Mvvm source generator) that wraps the API call, toggles an IsBusy boolean the XAML binds an ActivityIndicator to, and catches exceptions so a failed call surfaces as a friendly message instead of crashing the app. Because MAUI runs everything on a single UI thread per platform, long-running network calls must always be awaited rather than blocked on, or the UI will freeze mid-scroll.

🏏

Cricket analogy: It's like a captain who won't walk out to review a DRS decision themselves — they delegate to the on-field umpire and just wait for the signal, exactly as the UI thread delegates the network call and awaits the result instead of blocking.

On Android, network access requires the android.permission.INTERNET permission in the platform manifest — it's included by default in new MAUI projects, but double-check Platforms/Android/AndroidManifest.xml if HTTP calls silently fail only on device.

Both Android (API 28+) and iOS block plain HTTP by default — Android via Network Security Config and iOS via App Transport Security. Calling a non-HTTPS endpoint will throw at runtime unless you explicitly whitelist the domain for development, which you should never ship to production.

  • Register HTTP clients through IHttpClientFactory in MauiProgram.cs rather than instantiating HttpClient directly, to avoid socket exhaustion.
  • Use named or typed clients (AddHttpClient("Api", ...)) and inject IHttpClientFactory into services via MAUI's built-in DI container.
  • System.Text.Json with JsonPropertyName attributes maps API field names onto your C# model properties.
  • Wrap API calls in async RelayCommands with an IsBusy flag so the UI thread never blocks and stays responsive.
  • Android requires the INTERNET permission and both platforms block plain HTTP by default (ATS on iOS, Network Security Config on Android).
  • Always await network calls; never use .Result or .Wait() on a Task in a MAUI UI-thread context, as it can deadlock.
  • Consider Connectivity.Current.NetworkAccess to check connectivity before firing a request on mobile, where networks are far less reliable than on desktop or server.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#NETMAUIStudyNotes#ConsumingRESTAPIs#Consuming#REST#APIs#NET#StudyNotes#SkillVeris#ExamPrep