let’s wire up a sample UI page in .NET MAUI that consumes a REST API with HttpClient, supports CRUD operations, and includes a search feature.
This will give you a complete working example.
📁 Project Structure (Networking Example)
MyMauiApp/
│
├── Models/
│ └── Post.cs
│
├── Services/
│ └── ApiService.cs
│
├── ViewModels/
│ └── PostViewModel.cs
│
├── Views/
│ └── PostPage.xaml
│ └── PostPage.xaml.cs
│
├── MauiProgram.cs
└── App.xaml / App.xaml.cs
🧩 Code Walkthrough
1. Models/Post.cs
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Body { get; set; }
}
2. Services/ApiService.cs
using System.Net.Http.Json;
public class ApiService
{
private readonly HttpClient _httpClient;
public ApiService(HttpClient httpClient)
{
_httpClient = httpClient;
_httpClient.BaseAddress = new Uri("https://jsonplaceholder.typicode.com/");
}
// GET
public async Task<List<Post>> GetPostsAsync() =>
await _httpClient.GetFromJsonAsync<List<Post>>("posts");
// SEARCH
public async Task<List<Post>> SearchPostsAsync(string keyword)
{
var posts = await GetPostsAsync();
return posts.Where(p => p.Title.Contains(keyword, StringComparison.OrdinalIgnoreCase)).ToList();
}
// POST
public async Task<Post> CreatePostAsync(Post newPost)
{
var response = await _httpClient.PostAsJsonAsync("posts", newPost);
response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<Post>();
}
// PUT
public async Task<Post> UpdatePostAsync(Post updatedPost)
{
var response = await _httpClient.PutAsJsonAsync($"posts/{updatedPost.Id}", updatedPost);
response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<Post>();
}
// DELETE
public async Task DeletePostAsync(int id)
{
var response = await _httpClient.DeleteAsync($"posts/{id}");
response.EnsureSuccessStatusCode();
}
}
3. ViewModels/PostViewModel.cs
using System.Collections.ObjectModel;
public class PostViewModel : BindableObject
{
private readonly ApiService _api;
public ObservableCollection<Post> Posts { get; } = new();
public PostViewModel(ApiService api)
{
_api = api;
LoadPosts();
}
private async void LoadPosts()
{
var posts = await _api.GetPostsAsync();
Posts.Clear();
foreach (var post in posts)
Posts.Add(post);
}
public async Task AddPost(string title, string body)
{
var newPost = new Post { Title = title, Body = body };
await _api.CreatePostAsync(newPost);
LoadPosts();
}
public async Task UpdatePost(Post post)
{
await _api.UpdatePostAsync(post);
LoadPosts();
}
public async Task DeletePost(Post post)
{
await _api.DeletePostAsync(post.Id);
LoadPosts();
}
public async Task SearchPosts(string keyword)
{
var results = await _api.SearchPostsAsync(keyword);
Posts.Clear();
foreach (var post in results)
Posts.Add(post);
}
}
4. Views/PostPage.xaml
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
x:Class="MyMauiApp.Views.PostPage"
Title="Posts">
<VerticalStackLayout Padding="20">
<!-- Add new post -->
<Entry x:Name="TitleEntry" Placeholder="Title" />
<Entry x:Name="BodyEntry" Placeholder="Body" />
<Button Text="Add Post" Clicked="OnAddClicked" />
<!-- Search -->
<Entry x:Name="SearchEntry" Placeholder="Search posts..." />
<Button Text="Search" Clicked="OnSearchClicked" />
<!-- List of posts -->
<CollectionView ItemsSource="{Binding Posts}">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Padding="5">
<Label Text="{Binding Title}" FontAttributes="Bold" />
<Label Text="{Binding Body}" />
<Button Text="Delete" CommandParameter="{Binding .}" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
</ContentPage>
5. Views/PostPage.xaml.cs
public partial class PostPage : ContentPage
{
private readonly PostViewModel _vm;
public PostPage(PostViewModel vm)
{
InitializeComponent();
BindingContext = _vm = vm;
}
private async void OnAddClicked(object sender, EventArgs e)
{
if (!string.IsNullOrWhiteSpace(TitleEntry.Text) && !string.IsNullOrWhiteSpace(BodyEntry.Text))
{
await _vm.AddPost(TitleEntry.Text, BodyEntry.Text);
TitleEntry.Text = string.Empty;
BodyEntry.Text = string.Empty;
}
}
private async void OnSearchClicked(object sender, EventArgs e)
{
if (!string.IsNullOrWhiteSpace(SearchEntry.Text))
await _vm.SearchPosts(SearchEntry.Text);
else
await _vm.SearchPosts(string.Empty); // reload all
}
}
6. MauiProgram.cs
builder.Services.AddHttpClient<ApiService>();
builder.Services.AddTransient<PostViewModel>();
builder.Services.AddTransient<PostPage>();
✅ Features Covered
- Create: Add new posts.
- Read: Fetch posts from API.
- Update: Modify posts.
- Delete: Remove posts.
- Search: Filter posts by keyword.
This gives you a complete REST API consumer in MAUI with HttpClient, CRUD, and search.