MAUI icon

.NET MAUI Quick Start Guide

Get started with FacePing's face recognition API using .NET MAUI

Prerequisites

Installation

Create a new .NET MAUI project:

dotnet new maui -n FacePingDemo
cd FacePingDemo

Step 1: Create Face Group

Create ViewModels/CreateGroupViewModel.cs:

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

namespace FacePingDemo.ViewModels;

public partial class CreateGroupViewModel : ObservableObject
{
    private readonly HttpClient _client;
    private const string ApiKey = "your_api_key_here";

    [ObservableProperty]
    private string groupName;

    [ObservableProperty]
    private string status;

    public CreateGroupViewModel()
    {
        _client = new HttpClient();
        _client.DefaultRequestHeaders.Add("Authorization", $"Bearer {ApiKey}");
    }

    [RelayCommand]
    private async Task CreateGroupAsync()
    {
        try
        {
            var response = await _client.PostAsync(
                $"https://api.faceping.ai/groups/{GroupName}", 
                null);

            if (response.IsSuccessStatusCode)
                Status = "Group created successfully";
            else
                throw new Exception("Failed to create group");
        }
        catch (Exception ex)
        {
            Status = "Error creating group";
        }
    }
}

Create Views/CreateGroupPage.xaml:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="FacePingDemo.Views.CreateGroupPage">
    <VerticalStackLayout Spacing="20" Padding="20">
        <Entry Placeholder="Enter group name" 
               Text="{Binding GroupName}" />
        
        <Button Text="Create Group"
                Command="{Binding CreateGroupCommand}" />
        
        <Label Text="{Binding Status}"
               IsVisible="{Binding Status, Converter={StaticResource StringNotEmptyConverter}}" />
    </VerticalStackLayout>
</ContentPage>

Step 2: Upload Face Image

Create ViewModels/UploadFaceViewModel.cs:

public partial class UploadFaceViewModel : ObservableObject
{
    private readonly HttpClient _client;
    private const string ApiKey = "your_api_key_here";

    [ObservableProperty]
    private ImageSource imageSource;

    [ObservableProperty]
    private string status;

    public UploadFaceViewModel()
    {
        _client = new HttpClient();
        _client.DefaultRequestHeaders.Add("Authorization", $"Bearer {ApiKey}");
    }

    [RelayCommand]
    private async Task SelectImage()
    {
        var result = await MediaPicker.PickPhotoAsync();
        if (result != null)
        {
            ImageSource = ImageSource.FromFile(result.FullPath);
            await UploadImage(result);
        }
    }

    private async Task UploadImage(FileResult image)
    {
        try
        {
            var content = new MultipartFormDataContent();
            var stream = await image.OpenReadAsync();
            content.Add(new StreamContent(stream), "image", image.FileName);

            var response = await _client.PostAsync(
                "https://api.faceping.ai/groups/my-group/faces", 
                content);

            if (response.IsSuccessStatusCode)
                Status = "Face uploaded successfully";
            else
                throw new Exception("Failed to upload face");
        }
        catch (Exception ex)
        {
            Status = "Error uploading face";
        }
    }
}

Create Views/UploadFacePage.xaml:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="FacePingDemo.Views.UploadFacePage">
    <VerticalStackLayout Spacing="20" Padding="20">
        <Button Text="Select Image"
                Command="{Binding SelectImageCommand}" />
        
        <Image Source="{Binding ImageSource}"
               HeightRequest="200"
               IsVisible="{Binding ImageSource, Converter={StaticResource NotNullConverter}}" />
        
        <Label Text="{Binding Status}"
               IsVisible="{Binding Status, Converter={StaticResource StringNotEmptyConverter}}" />
    </VerticalStackLayout>
</ContentPage>

Step 3: Search for Faces

Create ViewModels/SearchFacesViewModel.cs:

public partial class SearchFacesViewModel : ObservableObject
{
    private readonly HttpClient _client;
    private const string ApiKey = "your_api_key_here";

    [ObservableProperty]
    private ImageSource imageSource;

    [ObservableProperty]
    private string status;

    [ObservableProperty]
    private ObservableCollection<MatchResult> matches = new();

    public SearchFacesViewModel()
    {
        _client = new HttpClient();
        _client.DefaultRequestHeaders.Add("Authorization", $"Bearer {ApiKey}");
    }

    [RelayCommand]
    private async Task SelectImage()
    {
        var result = await MediaPicker.PickPhotoAsync();
        if (result != null)
        {
            ImageSource = ImageSource.FromFile(result.FullPath);
            await SearchImage(result);
        }
    }

    private async Task SearchImage(FileResult image)
    {
        try
        {
            var content = new MultipartFormDataContent();
            var stream = await image.OpenReadAsync();
            content.Add(new StreamContent(stream), "image", image.FileName);

            var response = await _client.PostAsync(
                "https://api.faceping.ai/groups/my-group/search", 
                content);

            if (response.IsSuccessStatusCode)
            {
                var result = await response.Content.ReadFromJsonAsync<SearchResult>();
                Matches.Clear();
                foreach (var match in result.Matches)
                    Matches.Add(match);
                Status = $"Found {Matches.Count} matches";
            }
            else
                throw new Exception("Failed to search faces");
        }
        catch (Exception ex)
        {
            Status = "Error searching faces";
            Matches.Clear();
        }
    }
}

public class MatchResult
{
    public double Score { get; set; }
}

public class SearchResult
{
    public List<MatchResult> Matches { get; set; }
}

Create Views/SearchFacesPage.xaml:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="FacePingDemo.Views.SearchFacesPage">
    <VerticalStackLayout Spacing="20" Padding="20">
        <Button Text="Select Image"
                Command="{Binding SelectImageCommand}" />
        
        <Image Source="{Binding ImageSource}"
               HeightRequest="200"
               IsVisible="{Binding ImageSource, Converter={StaticResource NotNullConverter}}" />
        
        <Label Text="{Binding Status}"
               IsVisible="{Binding Status, Converter={StaticResource StringNotEmptyConverter}}" />
        
        <CollectionView ItemsSource="{Binding Matches}"
                        IsVisible="{Binding Matches.Count, Converter={StaticResource NotZeroConverter}}">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Label Text="{Binding Score, StringFormat='Match Score: {0:F2}'}" />
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </VerticalStackLayout>
</ContentPage>

Security Notes

  • Images are immediately discarded after vector conversion
  • Face vectors cannot be reverse-engineered into images
  • Always use HTTPS for all API calls
  • Store your API keys securely in configuration

Ready to get started?

Take a look at the API documentation
API docs