Offline-first field documentation for teams that cannot afford to lose evidence.
DocuRelay Field is a portfolio project demonstrating a realistic .NET MAUI workflow: a field worker opens a dossier, captures evidence, queues it while offline, and syncs it to an ASP.NET Core API when connectivity returns.
This repository was built to demonstrate mobile engineering concerns that are easy to describe but harder to prove:
- REST API consumption with typed DTOs and
HttpClient. - A durable SQLite cache for dossiers and a persisted upload queue.
- Retryable document uploads that remain visible to the user when offline.
- Cross-platform .NET MAUI UI, testing, CI, and Android release packaging.
It is a standalone portfolio project. It has no relationship with an employer or customer.
Field worker -> MAUI app -> local SQLite cache -> upload queue
| |
+-- offline ----------+
|
connectivity restored
|
ASP.NET Core API
- Refresh dossiers from the API; the latest result is cached locally.
- Add a document to a dossier. If the network is unavailable, the upload is queued.
- Sync retries queued work in a controlled order and clearly reports failures.
| Area | Choice |
|---|---|
| Mobile | .NET MAUI, MVVM, XAML, iOS and Android |
| Local persistence | SQLite via sqlite-net-pcl |
| Backend | ASP.NET Core Minimal API |
| Integration | REST, HttpClient, JSON, multipart upload |
| Quality | xUnit, GitHub Actions |
| Release | Android AAB artifact workflow, iOS release checklist |
| Cloud learning environment | Azure App Service, Azure SQL, Microsoft Entra ID, Service Bus, Container Apps and managed identities |
dotnet run --project src/DocuRelay.ApiWithout Azure configuration, the API starts with seeded dossiers in a temporary local database and exposes a health endpoint at /health. Set ConnectionStrings:AzureSql through user-secrets to use a real Azure SQL Database instead.
dotnet workload restore
dotnet build src/DocuRelay.Mobile/DocuRelay.Mobile.csproj -f net10.0-androidSet ApiOptions:BaseUrl in src/DocuRelay.Mobile/appsettings.json to an API that is reachable from your device. An Android emulator typically needs 10.0.2.2 instead of localhost.
src/
DocuRelay.Api/ REST API with dossier and document endpoints
DocuRelay.Contracts/ Shared API contracts
DocuRelay.Mobile/ .NET MAUI client, cache and sync queue
tests/
DocuRelay.Domain.Tests/ Fast, deterministic sync policy tests
docs/
architecture.md Design decisions and data flow
offline-sync.md Queue contract, retry semantics and failure handling
release-checklist.md Android and iOS release proof checklist
azure-learning-guide.md Azure architecture, identity setup and deployment proof
local-demo.md End-to-end local upload and processing walkthrough
portfolio-walkthrough.md Five-minute technical interview / demo script
- Start at
SyncServicefor the offline upload policy. - Read
SqliteOfflineStorefor durable local state. - Inspect
Program.csfor the runnable REST API. - CI validates the API and unit tests; tag builds produce an Android package artifact.
The current release APK was built independently by GitHub Actions, installed on a Pixel 3a Android 14 emulator, and validated against the current local API. The selected dossier shows a real README.md: Completed result from the outbox and worker flow. See the Completed-state screenshot and compact GIF walkthrough. Full evidence and the historical capture are recorded in runtime-validation.md.
- Dossier retrieval and local cache
- Persisted upload queue and retry policy
- API document endpoint and seeded data
- Automated API and sync-policy tests
- Android 14 emulator smoke test and runtime screenshot/demo
- Physical Android device smoke test
- iOS TestFlight internal build
The API and a separate background worker are ready for an Azure implementation: uploads and their outgoing queue messages are committed together to Azure SQL, an outbox dispatcher publishes a versioned job on Azure Service Bus, and the worker updates the status once work completes. The Bicep environment uses managed identities rather than application secrets.
Read the Azure learning guide for the complete setup, Entra ID registration, Service Bus retry/dead-letter behaviour and GitHub OIDC deployment. Infrastructure is in infra/main.bicep.
The same workflow runs fully locally: uploaded files are stored outside Git, an outbox dispatches messages to an in-process worker, and documents progress from Pending to Completed. Start the API, then open /demo for a visual live console or follow the local demo guide for the full walkthrough and OpenAPI contract.
For a ready-made presentation flow, use the portfolio walkthrough. It covers the mobile offline queue, retry handling, live worker processing, automated integration test and the Azure service mapping.
MIT. See LICENSE.
