A RESTful Todo API built with .NET 9.0, PostgreSQL, and Entity Framework Core.
- ✅ Full CRUD operations (Create, Read, Update, Delete)
- 🔄 Partial updates with PATCH endpoints
- 🐘 PostgreSQL database with Entity Framework Core
- 📚 Comprehensive API documentation with Swagger/OpenAPI
- 🔒 IP-based access restriction for production
- 🏗️ Clean architecture with separated DTOs and entities
- ⚡ Async/await throughout for optimal performance
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/todos |
Get all todos |
| GET | /api/todos/{id} |
Get a specific todo |
| POST | /api/todos |
Create a new todo |
| PUT | /api/todos/{id} |
Update an entire todo |
| PATCH | /api/todos/{id} |
Partially update a todo |
| DELETE | /api/todos/{id} |
Delete a todo |
-
Clone the repository
git clone <repository-url> cd tasks-api/TodoApi
-
Configure the database
Update
appsettings.Development.json:{ "ConnectionStrings": { "DefaultConnection": "Host=localhost;Port=5432;Database=todoapi;Username=your_username;Password=your_password" } } -
Run database migrations
dotnet ef database update
-
Start the API
dotnet run
-
Access Swagger documentation
Open your browser to:
https://localhost:5001/swagger
Run the entire application with PostgreSQL using Docker Compose:
# Start services
docker-compose up -d
# View logs
docker-compose logs -f todoapi
# Stop services
docker-compose downThe API will be available at http://localhost:8080
Use the pre-built image from GitHub Container Registry with your hosted PostgreSQL:
# Run with external database
docker run -d -p 8080:8080 \
-e ASPNETCORE_ENVIRONMENT=Production \
-e ConnectionStrings__DefaultConnection="Host=your-postgres-host;Port=5432;Database=todoapi;Username=user;Password=pass" \
-e AllowedIPs__0="203.0.113.1" \
-e AllowedIPs__1="203.0.113.2" \
--restart unless-stopped \
ghcr.io/YOUR_USERNAME/tasks-api:latestBefore first run, create the database schema:
# Run migrations (one-time setup)
docker run --rm \
-e ConnectionStrings__DefaultConnection="Host=your-postgres-host;Port=5432;Database=todoapi;Username=user;Password=pass" \
ghcr.io/YOUR_USERNAME/tasks-api:latest \
dotnet ef database update# Build the image
cd TodoApi
docker build -t todoapi .
# Run with external PostgreSQL
docker run -d -p 8080:8080 \
-e ConnectionStrings__DefaultConnection="Host=your-postgres;Port=5432;Database=todoapi;Username=user;Password=pass" \
todoapi{
"id": 1,
"name": "Complete project documentation",
"description": "Write comprehensive README and API docs",
"status": "In Progress",
"date": "2024-01-15",
"assignee": "John Doe",
"creator": "Jane Smith"
}curl -X POST "https://localhost:5001/api/todos" \
-H "Content-Type: application/json" \
-d '{
"name": "Learn .NET",
"description": "Complete the .NET tutorial",
"status": "Not Started",
"date": "2024-01-20",
"assignee": "Developer",
"creator": "Manager"
}'curl -X PATCH "https://localhost:5001/api/todos/1" \
-H "Content-Type: application/json" \
-d '{
"status": "Completed"
}'For production, override settings using environment variables:
# Database connection
export ConnectionStrings__DefaultConnection="Host=prod-host;Port=5432;Database=todoapi;Username=prod_user;Password=secure_password"
# IP restrictions (optional)
export AllowedIPs__0="203.0.113.1"
export AllowedIPs__1="203.0.113.2"
# Set production environment
export ASPNETCORE_ENVIRONMENT=ProductionThe API includes IP-based access restriction for production environments. Configure allowed IP addresses in appsettings.json or via environment variables.
Note: IP restrictions are disabled in Development mode for easier local development.
TodoApi/
├── Controllers/ # API controllers
├── Services/ # Business logic layer
├── Models/ # DTOs and data models
│ ├── Entities/ # Database entities
│ └── *.cs # DTO classes
├── Data/ # Entity Framework DbContext
├── Extensions/ # Service collection extensions
├── Middleware/ # Custom middleware
└── Migrations/ # EF Core migrations
- Repository Pattern: Encapsulated via Entity Framework DbContext
- DTO Pattern: Separation between API models and database entities
- Extension Methods: Clean Program.cs organization
- Dependency Injection: Built-in .NET DI container
- Record Types: Immutable DTOs with inheritance
# Run with auto-reload
dotnet watch run
# Build the project
dotnet build
# Run tests (when added)
dotnet test
# Create new migration
dotnet ef migrations add <MigrationName>
# Update database
dotnet ef database update- Create/update entity in
Models/Entities/ - Update
AppDbContextif needed - Create migration:
dotnet ef migrations add <Name> - Update service layer in
Services/ - Add/update controller endpoints
- Update DTOs in
Models/
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
This project is licensed under the MIT License.