| MAUI-CommunityToolkit-8 :👈 | 👉:MAUI-CommunityToolkit-10 |
Hour 9 – REST APIs, HttpClient, JSON & Offline Sync |
📘 Hour 9 – REST APIs, HttpClient, JSON & Offline Sync
Welcome to Hour 9 of your MAUI MVVM learning series. Today we cover how your MAUI app communicates with online services using:
- âž¡ REST API calls
- âž¡ HttpClient (best practices)
- âž¡ JSON serialization/deserialization
- âž¡ Offline sync pattern (SQLite + API)
✨ 1. Using HttpClient in MAUI
In .NET MAUI, HttpClient should be created using Dependency Injection.
🔧 1.1 Register HttpClient in MauiProgram
builder.Services.AddHttpClient();
builder.Services.AddTransient<ApiService>();
🧩 1.2 ApiService using HttpClient
public class ApiService
{
private readonly HttpClient http;
public ApiService(HttpClient client)
{
http = client;
http.BaseAddress = new Uri("https://jsonplaceholder.typicode.com/");
}
public async Task<List<TodoItem>> GetTodosAsync()
{
var json = await http.GetStringAsync("todos");
return JsonSerializer.Deserialize<List<TodoItem>>(json);
}
}
✔ HttpClient is reused efficiently by DI ✔ BaseAddress is configurable ✔ JSON is parsed using System.Text.Json
✨ 2. JSON Models
📄 2.1 Define the Model
public class TodoItem
{
public int Id { get; set; }
public int UserId { get; set; }
public string Title { get; set; }
public bool Completed { get; set; }
}
✔ Properties match API JSON fields.
✨ 3. ViewModel Calling the API
public partial class TodoViewModel : ObservableObject
{
private readonly ApiService api;
public TodoViewModel(ApiService service)
{
api = service;
}
[ObservableProperty]
private List<TodoItem> todos;
[RelayCommand]
private async Task LoadTodos()
{
Todos = await api.GetTodosAsync();
}
}
✔ Command-based loading ✔ Auto properties via source generators
✨ 4. Displaying API Results in XAML
<CollectionView ItemsSource="{Binding Todos}">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Padding="10">
<Label Text="{Binding Title}" />
<Label Text="{Binding Completed}" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
✔ Simple collection rendering ✔ Works cross-platform
✨ 5. POST, PUT & DELETE Requests
📤 5.1 POST (Create)
public async Task<TodoItem> CreateTodoAsync(TodoItem item)
{
var json = JsonSerializer.Serialize(item);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await http.PostAsync("todos", content);
return JsonSerializer.Deserialize<TodoItem>(await response.Content.ReadAsStringAsync());
}
📥 5.2 PUT (Update)
public async Task UpdateTodoAsync(TodoItem item)
{
var json = JsonSerializer.Serialize(item);
await http.PutAsync($"todos/{item.Id}",
new StringContent(json, Encoding.UTF8, "application/json"));
}
🗑 5.3 DELETE
public Task DeleteTodoAsync(int id)
{
return http.DeleteAsync($"todos/{id}");
}
✔ Complete API CRUD support
✨ 6. Offline Sync Pattern
Offline-first apps store data locally in SQLite and sync with API when online.
- ✔ SQLite stores cached items
- ✔ API updates data when online
- ✔ Merge logic keeps both sides in sync
🗂 6.1 Local Database Table
public class LocalTodo
{
[PrimaryKey, AutoIncrement]
public int LocalId { get; set; }
public int RemoteId { get; set; }
public string Title { get; set; }
public bool Completed { get; set; }
public bool IsSynced { get; set; }
}
🔄 6.2 Sync Service
public class SyncService
{
private readonly ApiService api;
private readonly TodoDatabase db;
public SyncService(ApiService a, TodoDatabase d)
{
api = a;
db = d;
}
public async Task SyncAsync()
{
var pending = await db.GetUnsyncedTodosAsync();
foreach (var item in pending)
{
var created = await api.CreateTodoAsync(new TodoItem
{
Title = item.Title,
Completed = item.Completed
});
item.RemoteId = created.Id;
item.IsSynced = true;
await db.SaveTodoAsync(item);
}
var remote = await api.GetTodosAsync();
await db.ReplaceLocalCopyAsync(remote);
}
}
✔ Local → remote push ✔ Remote → local refresh ✔ Makes your app work offline
✨ 7. Connectivity Check
Use MAUI’s Connectivity API to detect network state:
if (Connectivity.NetworkAccess == NetworkAccess.Internet)
{
await syncService.SyncAsync();
}
✔ Prevents sync errors when offline.
📘 Hour 9 Summary
- ✔ HttpClient should be DI-driven
- ✔ JSON serialization via System.Text.Json
- ✔ CRUD operations over REST APIs
- ✔ Offline Sync pattern for robust apps
- ✔ Use SQLite + API + Connectivity for reliability
| MAUI-CommunityToolkit-8 :👈 | 👉:MAUI-CommunityToolkit-10 |