API Integration with .NET MAUI

Learn how to integrate with RESTful APIs in your .NET MAUI applications using modern C# and .NET features.

Introduction to API Integration

Modern mobile and desktop applications often need to interact with backend services to fetch and send data. .NET MAUI, leveraging the power of .NET, provides robust tools for making HTTP requests and handling responses efficiently.

Note: Ensure you have a stable internet connection for API calls to succeed.

Using HttpClient

The HttpClient class is the primary way to send HTTP requests. It's designed to be instantiated once and reused throughout the life of an application.

Making a GET Request

Let's fetch data from a public API. We'll use the JSONPlaceholder API as an example.


using System;
using System.Net.Http;
using System.Threading.Tasks;

public class ApiService
{
    private readonly HttpClient _httpClient;

    public ApiService()
    {
        // It's recommended to instantiate HttpClient once and reuse it.
        _httpClient = new HttpClient
        {
            BaseAddress = new Uri("https://jsonplaceholder.typicode.com/")
        };
    }

    public async Task<string> GetPostsAsync()
    {
        try
        {
            HttpResponseMessage response = await _httpClient.GetAsync("posts");
            response.EnsureSuccessStatusCode(); // Throws an exception if the status code is not 2xx

            string responseBody = await response.Content.ReadAsStringAsync();
            return responseBody;
        }
        catch (HttpRequestException e)
        {
            Console.WriteLine($"Request error: {e.Message}");
            return null; // Or throw a custom exception
        }
    }
}
            

Deserializing JSON Responses

The data returned from APIs is often in JSON format. .NET provides powerful tools for deserializing JSON into C# objects.

First, define a C# class that matches the structure of the JSON data:


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

Then, use System.Text.Json.JsonSerializer to deserialize the response:


using System.Collections.Generic;
using System.Text.Json;

public class ApiService
{
    // ... (HttpClient initialization as above) ...

    public async Task<List<Post>> GetPostsAsObjectsAsync()
    {
        try
        {
            HttpResponseMessage response = await _httpClient.GetAsync("posts");
            response.EnsureSuccessStatusCode();

            string responseBody = await response.Content.ReadAsStringAsync();
            var options = new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true // Handles case differences in JSON property names
            };
            List<Post> posts = JsonSerializer.Deserialize<List<Post>>(responseBody, options);
            return posts;
        }
        catch (HttpRequestException e)
        {
            Console.WriteLine($"Request error: {e.Message}");
            return null;
        }
        catch (JsonException e)
        {
            Console.WriteLine($"JSON deserialization error: {e.Message}");
            return null;
        }
    }
}
            
Tip: For complex JSON structures, consider using online JSON to C# converters or Visual Studio's built-in tools.

Making a POST Request

To send data to an API, you'll typically use a POST request with a JSON payload.


using System.Net.Http.Json; // Requires System.Net.Http.Json NuGet package

public class ApiService
{
    // ... (HttpClient initialization as above) ...

    public async Task<Post> CreatePostAsync(Post newPost)
    {
        try
        {
            HttpResponseMessage response = await _httpClient.PostAsJsonAsync("posts", newPost);
            response.EnsureSuccessStatusCode();

            Post createdPost = await response.Content.ReadFromJsonAsync<Post>();
            return createdPost;
        }
        catch (HttpRequestException e)
        {
            Console.WriteLine($"Request error: {e.Message}");
            return null;
        }
        catch (JsonException e)
        {
            Console.WriteLine($"JSON deserialization error: {e.Message}");
            return null;
        }
    }
}
            

Handling Authentication

Many APIs require authentication. Common methods include:

Adding Authorization Headers


public class ApiService
{
    private readonly HttpClient _httpClient;
    private readonly string _apiKey = "YOUR_API_KEY"; // Replace with your actual API key

    public ApiService()
    {
        _httpClient = new HttpClient
        {
            BaseAddress = new Uri("https://api.example.com/")
        };
        // Add a default header for API key authentication
        _httpClient.DefaultRequestHeaders.Add("X-API-Key", _apiKey);
    }

    public async Task<string> GetDataWithApiKeyAsync()
    {
        try
        {
            HttpResponseMessage response = await _httpClient.GetAsync("data");
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync();
        }
        catch (HttpRequestException e)
        {
            Console.WriteLine($"Request error: {e.Message}");
            return null;
        }
    }
}
            
Warning: Never hardcode sensitive credentials like API keys or tokens directly in your client-side code in production applications. Use secure storage mechanisms or backend proxies.

Error Handling and Resilience

Network requests can fail. Implement robust error handling and consider patterns for resilience:

Configuring Timeouts


using System.Net;

public class ApiService
{
    private readonly HttpClient _httpClient;

    public ApiService()
    {
        var httpClientHandler = new HttpClientHandler
        {
            AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
        };

        _httpClient = new HttpClient(httpClientHandler)
        {
            BaseAddress = new Uri("https://jsonplaceholder.typicode.com/"),
            Timeout = TimeSpan.FromSeconds(30) // Set a default timeout of 30 seconds
        };
    }
    // ... rest of the service ...
}
            

Best Practices

By following these guidelines, you can effectively integrate your .NET MAUI applications with external APIs, building powerful and data-rich user experiences.