A clean layered architecture REST API for managing todo items with API key authentication.
The solution follows a three-layer architecture:
- Entities: Domain models (
TodoItem) - Interfaces: Service and repository contracts (
ITodoService,ITodoRepository) - Services: Business logic implementation (
TodoService) - Dependencies: None
- Data: EF Core DbContext configuration
- Repositories: Data access implementations (
TodoRepository) - Dependencies: Core layer, Entity Framework Core, SQL Server provider
- Controllers: REST API endpoints (
TodoController) - Middleware: API key authentication
- Configuration: Dependency injection, API key options
- Dependencies: Core and Repository layers
- RESTful API for Todo management
- API Key authentication via custom middleware
- Swagger/OpenAPI documentation
- Entity Framework Core with SQL Server
- Dependency Injection
- Clean separation of concerns
- .NET 10 SDK
- SQL Server or SQL Server LocalDB
Create or update appsettings.secrets.json in the CopilotDemo.Web folder:
{
"ApiKey": {
"Key": "your-secret-api-key-here"
}
}Important: This file is excluded from git via .gitignore to keep your API key secure.
Update the connection string in appsettings.json if needed:
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=CopilotDemoTodoDb;Trusted_Connection=true;TrustServerCertificate=true"
}
}# From the solution root directory
dotnet ef migrations add InitialCreate --project CopilotDemo.Repository --startup-project CopilotDemo.Web
dotnet ef database update --project CopilotDemo.Repository --startup-project CopilotDemo.Webdotnet run --project CopilotDemo.WebThe API will be available at:
- HTTPS:
https://localhost:7001 - HTTP:
http://localhost:5001 - Swagger UI:
https://localhost:7001/swagger
All endpoints require the X-Api-Key header with your configured API key.
GET /api/todo
GET /api/todo/{id}
POST /api/todo
Content-Type: application/json
{
"title": "Buy groceries",
"description": "Milk, eggs, bread"
}
PUT /api/todo/{id}
Content-Type: application/json
{
"title": "Buy groceries",
"description": "Milk, eggs, bread, butter",
"isCompleted": false
}
DELETE /api/todo/{id}
POST /api/todo/{id}/complete
curl -H "X-Api-Key: your-secret-api-key-here" https://localhost:7001/api/todo- Navigate to
https://localhost:7001/swagger - Click the "Authorize" button
- Enter your API key in the value field
- Click "Authorize"
- All requests will now include the API key automatically
- Create a new request
- In the Headers tab, add:
- Key:
X-Api-Key - Value:
your-secret-api-key-here
- Key:
- The API key is stored in
appsettings.secrets.jsonwhich is excluded from version control - For production, consider using:
- Azure Key Vault
- Environment variables
- User Secrets (for development)
- More sophisticated authentication (JWT, OAuth2, etc.)
- HTTPS is enforced in production environments
- Swagger endpoints bypass authentication for documentation access
CopilotDemo/
??? CopilotDemo.Core/
? ??? Entities/
? ? ??? TodoItem.cs
? ??? Interfaces/
? ? ??? ITodoRepository.cs
? ? ??? ITodoService.cs
? ??? Services/
? ??? TodoService.cs
??? CopilotDemo.Repository/
? ??? Data/
? ? ??? ApplicationDbContext.cs
? ??? Repositories/
? ??? TodoRepository.cs
??? CopilotDemo.Web/
??? Configuration/
? ??? ApiKeyOptions.cs
??? Controllers/
? ??? TodoController.cs
??? Middleware/
? ??? ApiKeyAuthenticationMiddleware.cs
??? Properties/
? ??? launchSettings.json
??? appsettings.json
??? appsettings.secrets.json (not in git)
??? Program.cs
- Define domain models in Core/Entities
- Define interfaces in Core/Interfaces
- Implement business logic in Core/Services
- Implement data access in Repository/Repositories
- Add controllers in Web/Controllers
- Register services in Web/Program.cs
dotnet testThis is a demo project for educational purposes.