Welcome to the backend of the Transportation Management App, a robust and scalable system designed to manage travelers, routes, ticketing, and vehicle operations. This project is architected with Clean Architecture principles to ensure high modularity, testability, and long-term maintainability. This project is inspired by sites like Booking.com and Alibaba.ir
π‘ This backend is designed to work seamlessly with the Transportation Management Frontend, a React-based SPA that consumes the RESTful APIs exposed by this project.
| Layer | Technologies |
|---|---|
| Presentation (API) | |
| Application | |
| Infrastructure | |
| Domain |
This project follows Clean Architecture as its foundation, separating the system into clearly defined layers:
Reference: View this article
Description:
Contains the Enterprise Business Rules β the core of the system. This layer is completely independent of any frameworks or infrastructure.
Includes:
- Entities: Pure business objects like
Account,Person,TicketOrder - Enums and Rules: Domain constraints and constants
- Interfaces: Contracts like
IEntity<TKey>,IRepository<T>
Domain Modeling Details:
- β ERD follows Third Normal Form (3NF) to avoid redundancy and ensure referential integrity.
- β Uses a Code-First Approach: database schema generated from C# model classes.
- β Base Entity & Interface provide consistency and generic flexibility:
public interface IEntity<TKey>
{
public TKey Id { get; set; }
}- Generic base class
Entity<TKey>standardizes ID usage:
public class Account : Entity<long>
{
public required string PhoneNumber { get; set; }
public required string Password { get; set; }
public string? Email { get; set; }
public long? PersonId { get; set; }
public decimal CurrentBalance { get; private set; }
public virtual Person? Person { get; set; }
public virtual BankAccountDetail? BankAccountDetail { get; set; }
public virtual ICollection<Transaction> Transactions { get; set; }
public virtual ICollection<TicketOrder> BoughtTicketOrders { get; set; }
public virtual ICollection<AccountRole> AccountRoles { get; set; }
public virtual ICollection<Person> CreatedPeople { get; set; }
public void Deposit(decimal amount) { ... }
public void Withdraw(decimal amount) { ... }
}Description:
Contains the Use Cases and orchestrates domain logic without depending on external concerns. Acts as the bridge between the domain and outside world (e.g., API controllers).
Key Responsibilities:
- Application Services
- Defines service contracts like
IAuthService,ITransportationService- Operates on DTOs, uses repositories and domain logic
- Returns structured
Result<T>objects
- Use of DTOs + AutoMapper
- Entities are never exposed directly to the API
- Uses Data Transfer Objects (DTOs) to control data flow
- Maps entities to DTOs and vice versa, using AutoMapper:
CreateMap<City, CityDto>();-
Result Wrapping with
Result<T>- All service responses are wrapped in a
Result<T>class, which:- Unifies success/error response logic
- Enhances readability
- Avoids throwing exceptions for business flow
- Enables easy status mapping at controller level Example structure:
public class Result<T> { public ResultStatus Status { get; set; } public string? ErrorMessage { get; set; } public T? Data { get; set; } public bool IsSuccess => Status == ResultStatus.Success; public static Result<T> Success(T data) => ... }; public static Result<T> Error(string errorMessage) => ... }; public static Result<T> NotFound() => new() { ... }; public static Result<T> Unauthorized() => new() {... }; }
With corresponding status
enum:public enum ResultStatus { Success, NotFound, ValidationError, Conflict, Unauthorized, Forbidden, Error }
- All service responses are wrapped in a
Description: This layer provides the actual implementations of interfaces defined in the Domain and Application layers. It deals with data access, external services, file storage, and configuration of frameworks like Entity Framework.
Entity Framework Core (EF Core) The project uses EF Core as the ORM (Object-Relational Mapper) for interacting with a SQL-based relational database (SQL Server).
- The
DbContextimplementation is calledApplicationDBContext, which manages access to all entities and repositories. - Repositories are injected into services via dependency injection and work through
ApplicationDbContext.
Entity Configurations
EF Core configurations are applied using the Fluent API, via IEntityTypeConfiguration<T> classes.
Example:
public class AccountConfiguration : IEntityTypeConfiguration<Account>
{
public void Configure(EntityTypeBuilder<Account> builder)
{
builder.HasKey(a => a.Id);
builder.Property(a => a.Id).ValueGeneratedOnAdd();
builder.Property(a => a.PhoneNumber)
.IsRequired()
.IsUnicode(false)
.HasMaxLength(20);
//...
//Relationships
builder.HasOne(a => a.Person)
.WithOne()
.HasForeignKey<Account>(a => a.PersonId)
.OnDelete(DeleteBehavior.Restrict);
}
}Migrations
-
The project follows Code-First Migrations using EF Core.
-
Database schema is automatically created and updated using:
dotnet ef migrations add InitialCreate dotnet ef database update
-
This enables safe, version-controlled database evolution as the domain model changes.
Repository Pattern & Unit of Work This app uses the Repository Pattern and Unit of Work to encapsulate data access logic and abstract away infrastructure concerns like Entity Framework Core.
Benefits:
- Abstraction from ORM
- Better Code Organization
- Improved Testability
- Encapsulation of Query Logic
- Centralized and Consistent Data Access
Implementation Structure:
- Interfaces in the Domain Layer
IRepository<T>: Generic base repository interfaceIEntityRepositoryor other entity-specific interfaces (e.g.,ITicketOrderRepository)- These define contracts for data access and allow the application and domain layers to remain independent of implementation details.
- Implementations in the Infrastructure Layer
Repository<T>: A generic implementation ofIRepository<T>using Entity Framework- Entity-specific repositories (e.g.,
TicketOrderRepository) implement their respective interfaces - Infrastructure-specific logic like query optimizations and eager loading are encapsulated here
- Unit of Work
- Wraps repository access in a single transactional boundary
- Guarantees:
- Data Consistency
- Performance
- Atomicity across multiple repositories
Description:
This layer contains the HTTP API controllers that expose the application's features to clients like the React frontend, mobile apps, or third-party services.
Responsibilities:
- Provides RESTful endpoints for all operations (CRUD, queries, authentication)
- Maps HTTP verbs to application services (
GET,POST,PUT,PATCH,DELETE) - Accepts and returns DTOs β never exposes domain entities
- Keeps logic minimal β delegates all behavior to the Application Layer
- Uses attributes and filters for model validation, authorization, and routing
- Returns structured HTTP responses with meaningful status codes (
200,201,400,404,500, etc.)
REST Compliance: The presentation layer adheres to REST principles like:
- Statelessness
- Resource identification via URIs
- Proper use of HTTP methods
- Standard status codes
Dependency Injection Setup
The app uses constructor-based dependency injection to wire up all services and repositories via the built-in .NET Core DI container.
All interfaces from the Domain and Application layers are registered with their Infrastructure or Application implementations in Program.cs:
builder.Services.AddScoped<ICityRepository, CityRepository>();
builder.Services.AddScoped<ILocationRepository, LocationRepository>();
builder.Services.AddScoped<IAuthService, AuthService>();
builder.Services.AddScoped<ITransportationService, TransportationService>();
//...This approach:
- Promotes loose coupling
- Supports easy testing and mocking
- Enables lifetime control (
Scoped,Singleton,Transient) - Keeps project modular and extendable
- Full CRUD support for all domain entities.
- Advanced Transportation Search: Supports optional filters like
vehicleType,departure/arrival cities, andstart/end time. - Ticket Ordering System:
- Supports both individual and group purchases.
- Allows one buyer and multiple travelers.
- Coupon support and auto-generated PDF ticket using QuestPDF.
- Transaction Logging & Reports:
- All transactions (e.g., top-up, ticket purchase) are logged.
- Export account transaction history as CSV.
- Custom JWT Authentication:
- Auth token is generated with a custom method, embedding account roles and account data.
- Each
Accountsupports multiple roles through a join table (AccountRole).
- Role-Based Authorization integrated into API endpoints.
- Password Hashing using SHA256 for secure credential storage.
- Add and manage personal details, bank account information, and saved people.
- View and manage traveler profiles associated with ticket orders.
- Built with Clean Architecture principles: layered, testable, decoupled.
- Interface-driven Services (e.g.,
IAuthService,ITransportationService) for modular growth. - AutoMapper used to separate DTOs from domain models cleanly.
- Structured response handling with a Result wrapper for service responses.
- Dependency Injection used throughout for loose coupling and flexibility.
- Persistence-Agnostic: Business logic is decoupled from EF Core and SQL Server.
- High testability through separation of concerns and use of interfaces.
- Easy to switch out implementations or add new providers thanks to DI and layered structure.
- Application layer remains untouched when swapping infrastructure components.
/src
β£ /Domain
β β£ Aggregates/
β β£ Framework/
β β£ Base/
β β£ Interfaces/
β£ /Application
β β£ DTOs/
β β£ Interfaces/
β β£ Mappers/
β β£ Result/
β β£ Services/
β β Utils/
β£ /Infrastructure
β β£ Persistence/
β β£ ExternalAPIs/
β β Mappings/
β£ /WebAPI
β β£ Authentication/
β β£ Controllers/
β β£ appsettings.json
β β Program.cs
β /Tests
β£ Unit/
β Integration/
The backend uses JWT (JSON Web Token) authentication with role-based access control to secure API endpoints.
Highlights:
- β Stateless: No server-side session; each request carries a token.
- π Roles Included: User roles are embedded in the token payload and enforced via policy-based authorization.
- π¦ Library Used:
Microsoft.AspNetCore.Authentication.JwtBearer - π― Ideal for SPAs like the React frontend.
Tokens follow the standard Header.Payload.Signature structure, and are passed via the Authorization: Bearer <token> header.
This backend adheres to RESTful design principles for clarity, scalability, and consistency across client-server communication.
-
Statelessness
Each HTTP request contains all necessary information; no server-side session state is maintained. -
Resource Identification via URIs
Resources likeaccounts,tickets, andtransportationsare identified using clean, noun-based endpoints. -
Standard HTTP Methods
GETβ Retrieve dataPOSTβ Create new recordsPUTβ Fully update existing recordsDELETEβ Remove a resource
-
Standard HTTP Status Codes
Responses use appropriate status codes like:200 OK201 Created404 Not Found500 Internal Server Error
If you're planning to test or contribute to the project, make sure to:
The develop branch contains the latest features and active work in progress.
git checkout developUpdate your connection string in appsettings.json:
{
"ConnectionStrings": {
"DefaultConnection": "Server=YOUR_SERVER;Database=YOUR_DB;Trusted_Connection=True;TrustServerCertificate=True"
}
}Make sure the values match your local SQL Server setup.
To enable JWT-based authentication, also include:
"Jwt": {
"Key": "YOUR_SECRET_KEY_HERE",
"Issuer": "YOUR_APP_NAME_OR_DOMAIN",
"Audience": "MyAppUsers",
"ExpiryMinutes": 360
}To create the schema and apply the current migrations:
dotnet ef migrations add InitialCreate
dotnet ef database updateβ This sets up your SQL database using the current domain models and Entity Framework configuration.
We follow Clean Architecture not just in code but in our workflow. PRs should:
- Target the correct layer.
- Avoid leaking infrastructure logic into core layers.
- Include tests for new business logic.
-
Clean Architecture:
Clean Architecture -
Dependency Injection in .NET Core:
Dependency Injection
- EF Core Code First Tutorial (Video) by Patrick God:
.NET 8 Web API & Entity Framework π Full CRUD Course (with Code-First Migrations & SQL Server) - EF Core Modeling & Configurations (Official Docs):
Creating and Configuring a Model
- Repository Design Pattern (Video) by Patrick God:
The Repository Pattern explained for EVERYONE (with Code Examples) π - Generic Repository Pattern by Milan JovanoviΔ How I Use The Generic Repository Pattern In Clean Architecture
- Repository & Unit of Work Pattern (Video) by Mosh
Repository Pattern with C# and Entity Framework, Done Right | Mosh - Infrastructure & Persistence Layer Design (Microsoft Docs):
Design the infrastructure persistence layer
- Official AutoMapper documentation:
https://automapper.org/
- REST API Tutorial & Best Practices: https://restfulapi.net/
- JWT Introduction and Guide (jwt.io): https://jwt.io/introduction/
QuestPDF(PDF generation library example used in project):
QuestPDF GitHub
This project is part of the first initiative by The Order of the Phoenix β a student-led movement aimed at building a culture of self-driven learning, teamwork, and meaningful project development. What started as a grassroots .NET learning group evolved into a full-stack travel management system inspired by platforms like Alibaba.ir, built with clean architecture on the backend and a modern React frontend.
π For more information, and to explore the full documentation and creation process, visit: ASP.NET Project Documentation
I should specially thank:
For their guidance, help and accompaniment.
MIT License β see LICENSE file for details.

