"Dal cacciavite al compilatore."
Un sistema di gestione officina Enterprise-grade costruito con .NET 10 e Clean Architecture.
MotoLogPro nasce dall'esigenza reale di unire la precisione meccanica con l'astrazione del software. Sviluppato da un Montatore Meccanico e Software Developer, questo progetto mira a simulare uno scenario aziendale completo per la gestione di flotte moto, interventi di manutenzione e clienti.
L'obiettivo tecnico Γ¨ dimostrare l'applicazione di pattern architetturali avanzati e l'uso delle ultimissime tecnologie Microsoft (.NET 10) in un contesto distribuito (Mobile + Cloud).
La soluzione segue rigorosamente i principi della Clean Architecture per garantire la separazione delle responsabilitΓ , la scalabilitΓ e la testabilitΓ . Γ suddivisa in 6 progetti distinti:
| Progetto | ResponsabilitΓ |
|---|---|
MotoLogPro.Domain |
EntitΓ (Motorcycle, ApplicationUser), interfacce e logica di business pura. Nessuna dipendenza esterna. |
MotoLogPro.Shared |
DTO e contratti condivisi tra API e Client. |
MotoLogPro.Infrastructure |
Accesso ai dati (EF Core), DbContext, migrazioni e implementazione dei service. |
MotoLogPro.API |
Backend ASP.NET Core Web API. Endpoint REST, autenticazione JWT, error handling globale. |
MotoLogPro.Client |
Frontend Cross-Platform in .NET MAUI. UI, MVVM, storage sicuro locale. |
MotoLogPro.Tests |
Unit test (xUnit + Moq) e Integration test. |
Durante lo sviluppo del flusso di aggiunta veicoli (CRUD), un test unitario sul Controller falliva simulando l'inserimento di un Telaio (VIN) duplicato. Invece di "hackerare" il test per farlo passare ciecamente, Γ¨ stata blindata l'architettura:
- Clean Controller: Il Controller REST non ha idea di cosa sia Entity Framework. Non contiene blocchi
catchperDbUpdateException, mantenendo intatta la Separation of Concerns. - GlobalExceptionMiddleware: Come una centralina diagnostica (ECU), un middleware globale cattura le eccezioni non gestite (es. violazioni di unicitΓ nel DB), le decodifica e restituisce al client un JSON standard
ProblemDetails(HTTP 409 Conflict). - Test Architetturale: Il test unitario Γ¨ stato allineato per verificare l'architettura e non le singole stringhe: il test si assicura che l'eccezione "attraversi" il Controller senza essere bloccata, destinata ad essere gestita in totale trasparenza dal Middleware.
- Client Resiliente: L'app MAUI (tramite
System.Text.Jsonpuro) spacchetta in sicurezza ilProblemDetailsJSON e restituisce all'utente un messaggio diagnostico pulito, evitando crash dell'applicazione.
Questo documento delinea i principi fondamentali di ingegneria del software applicati nello sviluppo di MotoLogPro, dimostrando un approccio Enterprise-ready alla costruzione di sistemi distribuiti.
Il sistema Γ¨ diviso in layer rigorosi (Domain, Shared, Infrastructure, API, Client) applicando la Regola della Dipendenza.
- Il vantaggio: Il livello di Dominio (
Motorcycle,ApplicationUser) non ha dipendenze esterne. Le modifiche al database (EF Core) o all'interfaccia utente (MAUI) non impattano mai la logica di business core.
- Single Responsibility Principle (SRP): Nel Client, i ViewModel si occupano esclusivamente dello stato dell'interfaccia (Presentation Logic), delegando l'accesso ai dati e le chiamate di rete ai Service (
IVehicleService,ICatalogService). - Dependency Inversion Principle (DIP): Moduli di alto livello dipendono da astrazioni. I ViewModel ricevono interfacce (es.
IVehicleService) tramite Dependency Injection, garantendo un'altissima TestabilitΓ (Γ¨ possibile iniettare Mock isolati dalla rete).
Massimizzazione del riutilizzo del codice sia lato backend che frontend.
- Esempio: La pagina
VehicleDetailPagein MAUI funge sia da schermata di "Creazione" che di "Modifica". Tramite l'uso dei[QueryProperty]e del data-binding, la UI e la logica si adattano dinamicamente alla presenza o meno di un parametro in ingresso, azzerando la duplicazione degli XAML.
Prevenzione degli errori alla radice (Fail-Fast) per evitare esecuzioni inutili, allocazione di memoria a vuoto e l'anti-pattern "Arrow Code" (codice annidato).
- Esempio: Nel backend e nei comandi del client vengono usate le Guard Clauses (
ArgumentException.ThrowIfNullOrWhiteSpace,moto is null). Se i parametri in ingresso non sono validi, il flusso si interrompe immediatamente alla riga 1, garantendo linearitΓ e robustezza.
Architettura pragmatica, pensata per l'utente finale (un meccanico con le mani sporche), evitando l'over-engineering.
- Esempio: L'implementazione di feedback visivi immediati (Optimistic UI Updates) per la cancellazione o modifica dei record, evitando architetture di caching distribuito inutilmente complesse per il contesto.
- Global Exception Handling: Il backend implementa un Middleware globale che cattura le eccezioni non gestite (es. violazioni di vincoli DB), restituendo
ProblemDetailsRFC 7807, prevenendo crash del client. - Soft Delete: Applicazione della cancellazione logica (
IsDeleted) e degli EF Core Global Query Filters. Questo preserva l'integritΓ referenziale dei dati storici (fatture, tagliandi) garantendo al contempo che i dati eliminati non vengano esposti per errore nelle query future.
- Sicurezza & Autenticazione: Login e Registrazione gestiti tramite ASP.NET Core Identity API Endpoints. Token JWT immagazzinati tramite SecureStorage nativo.
- Gestione Veicoli (CRUD Completo):
- Dashboard MVVM con lista veicoli tramite CollectionView.
- Flusso d'inserimento nuova moto (VehicleDetailPage) protetto da JWT automatico.
- Gestione e visualizzazione di errori server/strutturali (es. VIN duplicato) senza impattare l'esperienza utente.
- Dizionario Moto (Catalogo Reattivo):
- Selezione guidata di Brand e Modello tramite menu a tendina a cascata (Pickers) alimentati da dati strutturati.
- EF Core Data Seeding per popolare dinamicamente i Brand e i relativi Modelli al primo avvio.
- Eliminazione dell'inserimento libero di testo: garantisce l'integritΓ relazionale nel database e migliora l'UX da "officina" (mani sporche, meno tap possibili).
- Automazione HTTP: Il client MAUI intercetta e inietta dinamicamente gli header di Autorizzazione (Bearer) in tutte le chiamate API grazie al VehicleService.
- Framework: .NET 10
- Linguaggio: C# 13
- Frontend: .NET MAUI (Android, iOS, Windows, macOS)
- Backend: ASP.NET Core Web API
- Database: SQL Server (LocalDB per sviluppo)
- ORM: Entity Framework Core 10 β Code First
- Autenticazione: ASP.NET Core Identity + JWT Bearer Tokens
- Sicurezza: SecureStorage (Keychain/Keystore), RBAC
- Testing: xUnit, Moq, EF Core InMemory
- Architettura: Clean Architecture a 6 layer configurata e stabile.
- Database: Migrazioni EF Core, relazioni 1:N (Utente β Moto), campo
LicensePlateallineato su domain e DTO. - Autenticazione: Registrazione, Login, Logout e refresh JWT Token.
- Client Mobile: Login/Logout funzionante, Dashboard con lista veicoli, stati di errore e lista vuota distinti.
- Error Handling: Middleware globale su API con risposte
ProblemDetailsstandardizzate (RFC 7807). - Dizionario Moto: Catalogo reattivo con Pickers a cascata, Data Seeding EF Core e integritΓ relazionale garantita.
- Gestione Moto: CRUD completo lato client (aggiunta, modifica, cancellazione veicolo).
- Interventi: Storico manutenzione per veicolo (tagliandi, riparazioni, revisioni).
- Dashboard: Viste differenziate per ruolo (Admin, Meccanico, Cliente).
- Integrazione esterna: Decodifica VIN tramite API NHTSA.
- Visual Studio 2022 con workload .NET MAUI e ASP.NET installati.
- .NET 10 SDK.
- SQL Server Express o LocalDB.
-
Clona la repository:
git clone https://github.com/Mugen85/MotoLogPro.git
-
Crea il database dalla Package Manager Console di Visual Studio:
Update-Database -Project MotoLogPro.Infrastructure -StartupProject MotoLogPro.API
-
Registra il primo utente avviando
MotoLogPro.APIe usando Swagger (/swagger) βPOST /register. -
Avvia il Client selezionando
MotoLogPro.Clientcome progetto di avvio.Nota Android: l'emulatore usa
10.0.2.2per raggiungere il localhost del PC. La configurazione Γ¨ giΓ gestita inMauiProgram.cs.
dotnet testIl progetto MotoLogPro.Tests include:
- Unit test sul service layer (
MotorcycleServiceTests) con DB InMemory. - Unit test sul controller layer (
MotorcyclesControllerTests) con Moq.
Progetto open-source nato per passione e apprendimento. Feedback, PR e suggerimenti sono benvenuti, specialmente su:
- Ottimizzazioni EF Core.
- Miglioramenti UI/UX in MAUI.
- Copertura dei test.
Se questo progetto ti è utile o ti ha ispirato, considera di offrirmi un caffè!
Developed with β€οΈ, passion and mechanical precision.
"From the wrench to the compiler." An Enterprise-grade workshop management system built with .NET 10 and Clean Architecture.
MotoLogPro was born from a real need to bridge mechanical precision with software abstraction. Developed by a Mechanical Assembler turned Software Developer, this project simulates a complete business scenario for managing motorcycle fleets, maintenance jobs, and customers.
The technical goal is to demonstrate advanced architectural patterns and the latest Microsoft technologies (.NET 10) in a distributed context (Mobile + Cloud).
The solution strictly follows Clean Architecture to ensure Separation of Concerns, scalability, and testability. It is split into 6 distinct projects:
| Project | Responsibility |
|---|---|
MotoLogPro.Domain |
Entities (Motorcycle, ApplicationUser), interfaces and pure business logic. No external dependencies. |
MotoLogPro.Shared |
DTOs and shared contracts between API and Client. |
MotoLogPro.Infrastructure |
Data access (EF Core), DbContext, migrations and service implementations. |
MotoLogPro.API |
ASP.NET Core Web API backend. REST endpoints, JWT auth, global error handling. |
MotoLogPro.Client |
Cross-Platform frontend in .NET MAUI. UI, MVVM, secure local storage. |
MotoLogPro.Tests |
Unit tests (xUnit + Moq) and Integration tests. |
While developing the add vehicle flow (CRUD), a Controller unit test failed when simulating a duplicate VIN insertion. Instead of blindly "hacking" the test to make it pass, the architecture was bulletproofed:
- Clean Controller: The REST Controller has no knowledge of Entity Framework. It avoids using
catchblocks forDbUpdateException, keeping the Separation of Concerns intact. - GlobalExceptionMiddleware: Acting like a diagnostic control unit (ECU), a global middleware catches unhandled exceptions (e.g., DB uniqueness violations), decodes them, and returns a standard
ProblemDetailsJSON to the client (HTTP 409 Conflict). - Architectural Testing: The unit test was refactored to verify the architecture rather than hardcoded strings: the test ensures the exception "passes through" the Controller unblocked, intended to be handled seamlessly by the Middleware.
- Resilient Client: The MAUI app (using pure
System.Text.Json) safely unpacks theProblemDetailsJSON and returns a clean diagnostic message to the user, preventing application crashes.
This document outlines the core software engineering principles applied in the development of MotoLogPro, demonstrating an Enterprise-ready approach to building distributed systems.
The system is divided into strict layers (Domain, Shared, Infrastructure, API, Client) applying the Dependency Rule.
- The advantage: The Domain layer (
Motorcycle,ApplicationUser) has no external dependencies. Changes to the database (EF Core) or the user interface (MAUI) never impact the core business logic.
- Single Responsibility Principle (SRP): On the Client, ViewModels exclusively manage interface state (Presentation Logic), delegating data access and network calls to Services (
IVehicleService,ICatalogService). - Dependency Inversion Principle (DIP): High-level modules depend on abstractions. ViewModels receive interfaces (e.g.,
IVehicleService) via Dependency Injection, guaranteeing extremely high Testability (isolated Mocks can be injected without network dependencies).
Maximizing code reuse on both the backend and the frontend.
- Example: The
VehicleDetailPagein MAUI serves as both a "Create" and an "Edit" screen. Through the use of[QueryProperty]and data-binding, the UI and logic adapt dynamically to the presence or absence of an input parameter, eliminating XAML duplication entirely.
Preventing errors at the root (Fail-Fast) to avoid unnecessary execution, wasted memory allocation, and the "Arrow Code" anti-pattern (deeply nested conditionals).
- Example: Guard Clauses are used in both the backend and client commands (
ArgumentException.ThrowIfNullOrWhiteSpace,moto is null). If input parameters are invalid, the flow stops immediately at line 1, ensuring linearity and robustness.
Pragmatic architecture, designed for the end user (a mechanic with greasy hands), avoiding over-engineering.
- Example: Implementation of immediate visual feedback (Optimistic UI Updates) for record deletion or modification, avoiding unnecessarily complex distributed caching architectures for the given context.
- Global Exception Handling: The backend implements a global Middleware that catches unhandled exceptions (e.g., DB constraint violations), returning
ProblemDetailsRFC 7807, preventing client crashes. - Soft Delete: Implementation of logical deletion (
IsDeleted) and EF Core Global Query Filters. This preserves the referential integrity of historical data (invoices, service records) while ensuring that deleted data is never accidentally exposed in future queries.
- Security & Authentication: Login and Registration handled via ASP.NET Core Identity API Endpoints. JWT tokens are securely stored using the device's native SecureStorage.
- Vehicle Management (Full CRUD):
- MVVM Dashboard featuring a vehicle list via CollectionView.
- New motorcycle insertion flow (VehicleDetailPage) protected by automatic JWT authorization.
- Graceful handling and visualization of server/structural errors (e.g., duplicate VIN) without impacting the user experience.
- Motorcycle Dictionary (Reactive Catalog):
- Guided Brand and Model selection via cascading dropdown Pickers fed by structured data.
- EF Core Data Seeding to dynamically populate Brands and their related Models on first run.
- Free-text input eliminated: guarantees relational data integrity in the database and improves the workshop UX (greasy hands, minimum taps required).
- HTTP Automation: The MAUI client dynamically intercepts and injects Authorization headers (Bearer) into all API calls thanks to the VehicleService.
- Framework: .NET 10
- Language: C# 13
- Frontend: .NET MAUI (Android, iOS, Windows, macOS)
- Backend: ASP.NET Core Web API
- Database: SQL Server (LocalDB for development)
- ORM: Entity Framework Core 10 β Code First
- Authentication: ASP.NET Core Identity + JWT Bearer Tokens
- Security: SecureStorage (Keychain/Keystore), RBAC
- Testing: xUnit, Moq, EF Core InMemory
- Architecture: 6-layer Clean Architecture configured and stable.
- Database: EF Core migrations, 1:N relationships (User β Motorcycle),
LicensePlatefield aligned across domain and DTO. - Authentication: Registration, Login, Logout and JWT Token refresh.
- Mobile Client: Login/Logout working, Dashboard with vehicle list, distinct error and empty states.
- Error Handling: Global middleware on API with standardized
ProblemDetailsresponses (RFC 7807). - Motorcycle Dictionary: Reactive catalog with cascading Pickers, EF Core Data Seeding and guaranteed relational integrity.
- Motorcycle Management: Full CRUD on client side (add, edit, delete vehicle).
- Service History: Maintenance log per vehicle (services, repairs, inspections).
- Dashboard: Role-based views (Admin, Mechanic, Customer).
- External Integration: VIN decoding via NHTSA API.
- Visual Studio 2022 with .NET MAUI and ASP.NET workloads installed.
- .NET 10 SDK.
- SQL Server Express or LocalDB.
-
Clone the repository:
git clone https://github.com/Mugen85/MotoLogPro.git
-
Create the database from Visual Studio's Package Manager Console:
Update-Database -Project MotoLogPro.Infrastructure -StartupProject MotoLogPro.API
-
Register the first user by running
MotoLogPro.APIand using Swagger (/swagger) βPOST /register. -
Launch the Client by setting
MotoLogPro.Clientas the startup project.Android note: the emulator uses
10.0.2.2to reach the PC's localhost. This is already handled inMauiProgram.cs.
dotnet testThe MotoLogPro.Tests project includes:
- Unit tests on the service layer (
MotorcycleServiceTests) with InMemory DB. - Unit tests on the controller layer (
MotorcyclesControllerTests) with Moq.
Open-source project born from passion and learning. Feedback, PRs and suggestions are welcome, especially on:
- EF Core optimizations.
- UI/UX improvements in MAUI.
- Test coverage.
If this project was useful or inspired you, consider buying me a coffee!
Developed with β€οΈ, passion and mechanical precision.

