This repository contains a modular Port Logistics prototype API built with .NET 9, demonstrating Domain-Driven Design (DDD) with Entity Framework, following an Onion/Clean architectural style. It supports core features like Vessel Type management and will evolve to cover vessels and vessel visit notifications.
This example includes:
- Clear separation between (i) REST API, (ii) Domain and (iii) Infrastructure (Persistence)
- Implementation of business rules/validation in the domain
- Performance improvements: String length validation to prevent unlimited string size issues
- Immutability: Use of init-only properties in DTOs for safer data transfer
The domain includes Business Entities, Services (use cases) involving these entities, and DTOs (in/out for domain services). For simplicity, these are packaged by aggregate.
- User Story 2.2.1 – Vessel Type Management:
- Create and update Vessel Types with attributes: name, description, capacity (TEU), and operational constraints (max rows, bays, tiers).
- Search/filter by name and description using query parameters.
- Documentation and models are available under Docs/SprintA (UML/PlantUML, C4, and specs).
Related documentation and models are available under Docs/SprintA (UML/PlantUML, C4, and specs).
- .NET SDK 9.0.305 (or newer 9.0.x)
- A code editor like Visual Studio, Visual Studio Code, or JetBrains Rider
If you haven't already, ensure you have the project files in your local directory.
dotnet restoredotnet builddotnet run --launch-profile PortLogisticsNote: You can also use the generic reference dotnet run --launch-profile https in many .NET projects, but for this specific project, the HTTPS profile is named "PortLogistics".
This will start the application with:
- HTTPS:
https://localhost:5001 - HTTP:
http://localhost:5000
dotnet run --launch-profile "IIS Express"This will start the application with:
- HTTP:
http://localhost:44786 - HTTPS:
https://localhost:44343
dotnet rundotnet watch runThis is useful during development as it automatically restarts the application when you make changes to the code.
Once the application is running, you can access the following endpoints:
- Base URL:
https://localhost:5001(or the URL shown in your terminal) - Vessel Types:
/api/vesseltypes(supports query params:?name=...&description=...)
You can test the API using:
- Browser: Navigate to
https://localhost:5001/api/values - Postman: Import and test the endpoints
- curl: Command line HTTP requests
- Swagger/OpenAPI: If configured, usually available at
/swagger
Example curl command:
curl -k https://localhost:5001/api/valuesVessel Types API examples:
- Query by name/description
curl -k "https://localhost:5001/api/vesseltypes?name=Feeder&description=short"- Create a vessel type
curl -k -X POST https://localhost:5001/api/vesseltypes \
-H "Content-Type: application/json" \
-d '{
"name": "Feeder",
"description": "Small regional feeder",
"capacityTeu": 1500,
"maxRows": 16,
"maxBays": 20,
"maxTiers": 6
}'- Update a vessel type (replace )
curl -k -X PUT https://localhost:5001/api/vesseltypes/<id> \
-H "Content-Type: application/json" \
-d '{
"id": "<id>",
"name": "Feeder (updated)",
"description": "Updated description",
"capacity": 1600,
"maxRows": 16,
"maxBays": 22,
"maxTiers": 6
}'dotnet builddotnet cleandotnet restoredotnet publish -c Release -o ./publish# Development
dotnet run --environment Development
# Production
dotnet run --environment Production├── Controllers/ # API Controllers (REST endpoints)
├── Domain/
│ ├── AuditLog/
│ ├── CargoManifests/
│ ├── Docks/
│ ├── OrganizationRepresentative/
│ ├── Qualifications/
│ ├── Resources/
│ ├── ShippingOrganization/
│ ├── StaffMembers/
│ ├── StorageAreas/
│ ├── VesselRecords/
│ ├── VesselTypes/
│ ├── VesselVisit/
│ └── Shared/
├── Infrastructure/
│ ├── AuditLogging/
│ ├── CargoManifests/
│ ├── Docks/
│ ├── OrganizationRepresentative/
│ ├── Qualifications/
│ ├── Resources/
│ ├── ShippingOrganization/
│ ├── StaffMembers/
│ ├── StorageAreas/
│ ├── VesselRecords/
│ ├── VesselTypes/
│ ├── VesselVisits/
│ └── Shared/
├── Docs/ # Project documentation (UML, C4, specs)
├── Properties/ # Launch settings and configuration
├── appsettings.json # Application configuration
├── Program.cs # Application entry point
└── Startup.cs # Startup (for compatibility with minimal hosting)
The application uses Entity Framework with an In-Memory database for simplicity. Configuration can be found in:
appsettings.json- General application settingsappsettings.Development.json- Development-specific settings
If you get a port conflict error, you can specify a different port:
dotnet run --urls="https://localhost:5555;http://localhost:5556"If you encounter HTTPS certificate issues, you can trust the development certificate:
dotnet dev-certs https --trustIf you encounter build errors, try:
dotnet clean
dotnet restore
dotnet build- Project upgraded to .NET 9 (SDK 9.0.305). The hosting model now uses the minimal hosting bootstrap in
Program.cswhile preserving the existingStartupclass. - The database is configured to use In-Memory storage for simplicity
- Authentication is not implemented in this sample
- This is a learning/template project demonstrating DDD concepts
- Recent improvements:
- Added maximum string length validation for key domain properties to avoid performance issues
- Made DTO properties init-only for improved immutability
This is an educational/example project. Please check with the original authors for licensing information.
By default, this project uses the in-memory EF Core provider, so you can run the API without any external database setup.
You can switch to a real database by editing appsettings files:
- appsettings.json (shared defaults)
- appsettings.Development.json (overrides for local dev)
Settings:
- Database.Provider: InMemory | Sqlite | SqlServer
- ConnectionStrings: provide the matching connection string when using Sqlite or SqlServer
Examples
- Keep default InMemory (no external DB needed)
appsettings.Development.json { "Database": { "Provider": "InMemory" } }
- Use SQLite (creates a local file portlogistics.db)
appsettings.Development.json { "Database": { "Provider": "Sqlite" }, "ConnectionStrings": { "Sqlite": "Data Source=portlogistics.db" } }
- Use SQL Server LocalDB
appsettings.Development.json { "Database": { "Provider": "SqlServer" }, "ConnectionStrings": { "SqlServer": "Server=(localdb)\MSSQLLocalDB;Database=PortLogisticsDB;Trusted_Connection=True;MultipleActiveResultSets=true" } }
About H2 databases
H2 (jdbc:h2:...) is a Java database that is accessed via JDBC. Entity Framework Core and .NET do not natively support H2/JDBC. To work with your H2 database (e.g., jdbc:h2:~\eapliexemplo with user sa and empty password) from this .NET project, you have two practical options:
- Migrate/replicate the schema/data to a supported provider (SQLite or SQL Server). This is the simplest path and integrates seamlessly with the current EF Core repositories.
- Use a third-party H2 ADO.NET/ODBC driver and rework repositories to use raw ADO.NET instead of EF Core. This is a non‑minimal change and not recommended unless H2 is mandatory.
If you prefer, we can help you script a one-time migration from H2 to SQLite/SQL Server so the API can run against a real DB with minimal code changes.