This project showcases a comprehensive full-stack solution, combining a robust ASP.NET Core Web API backend, an MVC web frontend, and a modern React single-page application — all seamlessly integrated to provide a highly secure, scalable, and user-friendly system.
Note: All services are hosted on Free Tier plans.
- 🗄️ Database automatically enters paused mode after inactivity. On the initial request, please allow 1-2 minutes for it to wake up.
- ⚡ Redis Cloud is used for distributed caching — cache may be evicted or unavailable during inactivity. The application automatically falls back to In-Memory Cache to ensure uninterrupted availability.
- 📊 OpenTelemetry is enabled in the live demo — telemetry data may be unavailable or delayed due to free tier limits on the observability backend.
| Application | Platform | Link |
|---|---|---|
| ASP.NET Core API |
| View API Documentation 🡥 |
| ASP.NET Web MVC |
| Launch MVC Frontend 🡥 |
| React SPA |
| Launch React Frontend 🡥 |
| React SPA |
| Launch React Frontend 🡥 |
Note: These demo credentials are provided for testing and demonstration purposes only.
| Username | Password | Role | Description |
|---|---|---|---|
| og | og | SuperAdmin | Full CRUD access, data export, and role management |
| aa | aa | Admin | CRUD operations + exporting data |
| uu | uu | User | Read and filter data only |
- Clone the repository
git clone https://github.com/crni99/airport-automation.git- Navigate to the backend API project
cd airport-automation/backend/AirportAutomationApi- Configure Database Provider and Connection String
- Open
appsettings.jsonand choose your preferred database provider. - Update the
DatabaseProvidervalue to match your choice (SqlServer,Postgres, orMySql). - Update the corresponding connection string with your local server details, credentials, and port.
"DatabaseProvider": "SqlServer", // <- CHANGE this to your selected provider!
"ConnectionStrings": {
"SqlServerConnection": "Data Source=YOUR_SQL_SERVER_INSTANCE;Initial Catalog=AirportAutomation;Integrated Security=True;TrustServerCertificate=True;MultipleActiveResultSets=true;",
"PostgresConnection": "Host=localhost;Port=5432;Username=YOUR_USER;Password=YOUR_PASSWORD;Database=AirportAutomation",
"MySqlConnection": "Server=localhost;Port=3306;Database=AirportAutomation;Uid=YOUR_USER;Pwd=YOUR_PASSWORD;"
}- Initialize the database
- You will need to run the appropriate SQL script for your chosen provider to create and seed the database.
- These scripts are located in Data folder.
| Database Provider | SQL File to Run | Action |
|---|---|---|
|
|
mssql.sql 🡥 |
Execute script against SQL Server instance. |
|
|
npgsql.sql 🡥 |
Execute script against PostgreSQL server (e.g., via pgAdmin). |
|
|
mysql.sql 🡥 |
Execute script against MySQL server (e.g., via MySQL Workbench). |
- Optional: Enable Redis Caching
- By default, the application uses In-Memory Cache for seamless local development.
- However, for better performance and distributed environments, you can easily switch that.
"ConnectionStrings": {
"Redis": "[host]:[port],password=[password],ssl=True,abortConnect=False"
},
"Redis": {
"Enabled": true
}- Optional: Enable OpenTelemetry
- By default, the application has telemetry disabled for seamless local development.
- However, for observability in distributed environments, you can easily switch that.
"OpenTelemetry": {
"Enabled": true,
"Endpoint": "https://otlp-gateway-prod-eu-central-0.grafana.net/otlp",
"Headers": "Authorization=Basic YOUR_BASE64_TOKEN",
"ServiceName": "your-service-name",
"ServiceVersion": "1.0.0"
}- In your IDE (e.g., Visual Studio / JetBrains Rider):
- Set
AirportAutomationApi(Web API) andAirportAutomationWeb(MVC Web) as the startup projects. - This ensures the API and MVC frontend run together.
- Alternatively (using CLI/VS Code): Open two separate terminal windows in the
airport-automation/backenddirectory and run the following commands concurrently:- For the Web API:
dotnet run --project AirportAutomationApi/AirportAutomationApi.csproj - For the MVC Frontend:
dotnet run --project AirportAutomationWeb/AirportAutomationWeb.csproj
- For the Web API:
- Start the application
dotnet run- Navigate to the React frontend
cd ../../react-frontend- Install dependencies
npm install- Start the React frontend
npm run start- Built on
.NET 8 (LTS)- Long-term support until November 2026 C# 12features - Primary constructors, collection expressions- Clean Architecture Principles - Separation of concerns through dedicated layers and shared package versioning.
- Support multiple database providers: SQL Server, PostgreSQL, and MySQL.
- Manage database schema and migrations via Entity Framework Core for version control.
- Abstract database operations through repository pattern in dedicated layers.
- Configure entities, relationships, and migrations for schema management.
- Design and implement RESTful endpoints following HTTP best practices.
- Support standard HTTP methods (GET, POST, PUT, PATCH, DELETE) with appropriate status codes.
- Structure endpoints with consistent naming conventions and resource hierarchies.
- Implement comprehensive input validation using data annotations and custom validators.
- Validate requests at multiple layers (DTOs, model binding, business logic).
- Return detailed validation error messages following RFC 9457 problem details standard.
- Implement RFC 9457 standard for structured error responses.
- Return detailed problem details including:
- Error type and title
- HTTP status code
- Trace identifier for debugging
- Specific validation errors per field
- Provide consistent error format across all API endpoints.
- Leverage ASP.NET Core's built-in dependency injection container.
- Register services with appropriate lifetimes (Scoped, Transient, Singleton).
- Implement service interfaces for loose coupling and testability.
- Organize business logic in dedicated service layer separate from controllers.
- Implement advanced features such as searching, filtering, and paging to improve the API’s usability and performance.
- Implement a hybrid caching strategy using
Redisfor distributed environments andIn-Memory Cacheas a secondary fallback. - Smart Switch Mechanism: The system automatically detects if Redis is enabled and reachable; if not, it seamlessly falls back to local memory to ensure 100% uptime.
- Resilient Cache Layer: If Redis becomes unavailable or runs out of memory during runtime, the system gracefully handles the failure and falls back to the database, ensuring uninterrupted API availability.
- Use caching to optimize performance-heavy operations, such as frequently accessed lookups and search results.
- Cache Stampede Prevention: Under high concurrency, a
SemaphoreSlimlock per cache key ensures only one request hits the database on a cache miss — all other concurrent requests wait and read from cache once it's populated.
- Implement a unified observability stack using
OpenTelemetryfor distributed tracing, metrics collection, and structured log export. - Smart Switch Mechanism: OpenTelemetry instrumentation is conditionally enabled via configuration — if disabled, the application runs without any telemetry overhead, ensuring zero performance impact in lightweight environments.
- Distributed Tracing: Instrument ASP.NET Core request pipeline, outbound HTTP calls, and Entity Framework Core database queries to produce end-to-end traces across service boundaries.
- Metrics Collection: Capture runtime, HTTP, and application-level metrics using ASP.NET Core and HTTP client instrumentation for real-time performance monitoring.
- Structured Log Export: Export enriched, formatted log entries (including scopes) via OTLP to a centralized observability backend for centralized analysis and alerting.
- Export all telemetry signals (traces, metrics, logs) over
OTLP/HTTPProtobuf to a configurable endpoint, enabling integration with backends such asGrafana,Jaeger,Tempo, or any OpenTelemetry-compatible collector.
- Implement dedicated filter classes for each entity type (PassengerSearchFilter, PilotSearchFilter, etc.) to enable multi-field search capabilities.
- Create filter extension methods to encapsulate query building logic and promote reusability.
- Support case-insensitive search across multiple fields simultaneously (e.g., search passengers by first name, last name, UPRN, passport, address, and phone).
- Apply filter pattern to maintain clean separation between controller logic and query construction.
- Implement endpoints to export data in PDF and Excel formats for reporting and offline analysis.
- Ensure exported documents preserve formatting and reflect applied filters or search criteria.
- Use
QuestPDFto generate high-quality, customizablePDFdocuments. - Use
ClosedXMLto create Excel files with structured data, formatting, and support for advancedExcelfeatures.
- Enable a global CORS policy (
_AllowAll) for development to facilitate frontend-backend communication. - Important: Configure more restrictive CORS policies for production environments:
- Specify allowed origins (e.g., your frontend domain)
- Define allowed HTTP methods and headers
- Enable credentials if needed
- Plan migration from permissive to strict CORS policies before production deployment.
- Implement role-based access control with policies:
RequireSuperAdminRoleRequireAdminRoleRequireUserRole
- Enable fine-grained endpoint access control based on user roles to ensure secure handling of sensitive data.
- Manage API versions to maintain backward compatibility.
- Document API endpoints comprehensively for developer-friendly integration.
- Customize Swagger UI with advanced features:
- Toggleable dark/light theme for enhanced usability
- Custom branding with favicon and logo
- Custom styling and behavior via injected CSS and JavaScript
- Custom controller ordering using SwaggerControllerOrder attribute
- Integrate Serilog for structured, centralized logging with configuration from appsettings.json.
- Implement custom middleware for enhanced diagnostics:
- RequestLogContextMiddleware - Enriches logs with request context (trace IDs, user info)
- GlobalExceptionHandler - Standardizes error responses and captures unhandled exceptions
- Configure logging levels and outputs (console, file, external services) for different environments.
- Centralize all configurations (e.g., Serilog, rate limiting, authentication secrets, pagination settings) in
appsettings.jsonfor better maintainability and environment flexibility.
- Implement a rate limiter to protect API resources from abuse, mitigate DDoS attacks, and enhance overall API performance.
- Maintain all NuGet package versions in
Directory.Packages.propsat solution root. - Enable
ManagePackageVersionsCentrallyfor unified version control across all projects. - Benefits:
- Version consistency - All projects use identical package versions
- Easy updates - Change version once, updates everywhere
- Cleaner .csproj files - Package references without version attributes
- No conflicts - Eliminates version mismatch issues
- Write comprehensive unit tests using the xUnit framework to validate individual components in isolation.
- Ensure tests improve code reliability, support refactoring, and simplify debugging.
- Monitor the health of critical components with custom health check implementations:
DatabaseHealthCheck- Verifies database connectivity and accessibilityApiHealthCheck- Monitors API availability and responsiveness
- Configure health check endpoints to provide visibility into system status and integrate them into Swagger documentation for easy access.
- Return detailed health status with Healthy/Degraded/Unhealthy states and custom messages.
🌐 MVC Web Frontend 🡥
- Implement HttpClientFactory with Polly resilience policies:
- Transient fault handling with exponential backoff
- Circuit breaker for prolonged failures
- Request timeout enforcement
- Centralize HttpClient configuration for consistent headers.
- Create generic CRUD methods (CreateData, ReadData, etc.) for type-safe communication.
- Dynamically construct endpoints with custom pluralization rules.
- Support advanced filtering, pagination, and data export.
- Handle data presentation with MVC templates and model binding.
- Develop validated input forms with Bootstrap 5 styling.
- Implement AJAX requests for asynchronous updates.
- Leverage JavaScript, jQuery, and AJAX to build responsive and interactive user interfaces, enabling asynchronous data fetching and partial page updates without full reloads.
- Implement Resource Files (.resx) for centralized alert and error message management.
- Create
AlertServiceto retrieve localized messages from resource files. - Use ResourceManager to access messages dynamically based on message keys.
- Prepare foundation for future internationalization (i18n) support.
- Integrate the export functionality from the API into the MVC frontend, allowing users to generate and download PDF and Excel reports directly from the web interface.
- Provide options to reflect applied filters or search terms in the exported documents, ensuring consistency between the UI and downloaded data.
- Ensure user-friendly interactions with appropriate UI components (e.g., export buttons, spinners, error handling) for a seamless reporting experience.
- Enforce HTTPS to secure data transmission between client and server.
- Implement protections against common vulnerabilities such as
Cross-Site Scripting (XSS),Cross-Site Request Forgery (CSRF), and controlCross-Origin Resource Sharing (CORS). - Secure API calls with bearer token authorization headers automatically added to all HTTP requests.
⚛️ React Frontend 🡥
- Build the frontend using functional components and
React Hooks. - Design a responsive, mobile-friendly layout with modern styling techniques.
- Utilize the rich set of components from
Material UI (MUI)to implement a sleek, professional, and accessible user interface based on Material Design principles. - Implement toggleable dark/light theme with user preference persistence in localStorage.
- Customize Material-UI theme configuration for consistent styling across the application.
- Manage application state via
Context APIwith multiple dedicated contexts:DataContext- Centralized API URL configurationThemeContext- User theme preference (dark/light mode)SidebarContext- Sidebar collapse/expand state
- Handle asynchronous operations efficiently using the native
fetchAPI and middleware where necessary.
- Implement custom hooks to abstract common data operations and promote code reuse:
useFetch- Generic data fetching with pagination, filtering, and error handlinguseCreate- Unified logic for creating new entities with validationuseUpdate- Consistent update operations across all entitiesuseDelete- Reusable delete functionality with confirmationuseExport- Centralized export logic for PDF and Excel generation
- Fully integrate with the backend API to retrieve and manage data such as flights, passengers, and airport operations.
- Dynamically render components based on API responses and user interactions.
- Manage form inputs using custom hooks (useCreate, useUpdate) with built-in validation.
- Provide real-time validation with user-friendly error handling and feedback via Snackbar notifications.
- Implement entity-specific validation rules with 245+ lines of validation logic.
- Support multiple validation types:
- Required fields, string lengths, numeric ranges, date/time formats, foreign keys
- Validate specific business rules (e.g., UPRN 13 chars, Passport 9 chars, FlyingHours 0-40000).
- Provide real-time error messages with centralized validation utilities.
- Implement centralized error handling with
CustomErrorclass for consistent error messages. - Use
errorUtilsto differentiate between network errors, server errors, and validation errors. - Provide user-friendly error messages and graceful degradation for edge cases.
- Handle navigation using
React Router, including dynamic and nested routes for scalability. - Enable seamless page transitions without full reloads.
- Integrate the frontend with API endpoints to allow users to export data to PDF and Excel formats.
- Allow users to apply filters or search terms before export, with generated documents reflecting those criteria.
- Accompany export actions with UI feedback such as loading spinners and error messages for an improved user experience.
- Provide download links directly in the UI for quick access to exported files.
- Implement secure user login using
JWT-based authentication. - Apply role-based access control with
ProtectedRoutecomponent to restrict features based on user permissions. - Automatically redirect unauthenticated users to login page.
- Store authentication tokens securely and manage token expiration.
- Integrate Google Maps embedding to display destination locations visually.
- Implement
MapEmbedcomponent for dynamic map rendering based on address input. - Use iframe embedding with lazy loading for optimized performance.
- Provide visual context for airport destinations with interactive maps.
- Improve performance through
lazy loading,code splitting, andmemoization. - Optimize re-renders using React best practices to enhance responsiveness.
- Implement a complete web app manifest (manifest.json) including appropriate names, unique ID, theme colors (#009be5), and icons (including a maskable icon).
- Configure
service-worker.jsfor offline functionality and caching strategies. - Ensure the application meets all core PWA installability criteria (served over HTTPS, valid manifest, and service worker) to allow users to install it as a native application on their devices.
🚀 Deployment 🡥
- The .NET API is deployed to Azure Web App (service name
airport-automation) via the automated GitHub Actions CI/CD pipeline. - The .NET Web MVC is deployed to Azure Web App.
- The React Frontend is deployed to two platforms to ensure high availability and redundancy:
- Integrate basic logging and monitoring solutions to track application health and capture errors in production environments.
🔄 Mirroring 🡥
- The project is mirrored from
GitHubtoGitLabandBitbucket, where customGitHub Actionsare configured to automatically triggerCI/CD pipelineson code changes. - This mirroring setup ensures continuous integration and deployment on both GitLab and Bitbucket by synchronizing code changes pushed to GitHub.
- Both GitLab and Bitbucket automatically pick up the changes pushed from GitHub, triggering their respective CI/CD pipelines for seamless integration and deployment.
