A robust RESTful API for managing IT devices built with ASP.NET Core 10.0, Entity Framework Core, and PostgreSQL. This API provides comprehensive device management capabilities including tracking device information, status, and user assignments.
- Device Management: Create, update, and track IT devices (laptops, desktops)
- RESTful API: Clean, versioned API endpoints following REST principles
- CQRS Pattern: Implements Command Query Responsibility Segregation using MediatR
- Repository Pattern: Abstracted data access layer for maintainability
- Exception Handling: Global exception filter with proper HTTP status codes
- API Versioning: Built-in versioning support via URL segments and headers
- Swagger/OpenAPI: Interactive API documentation and testing
- Docker Support: Containerized PostgreSQL database setup
- Entity Framework Core: Code-first approach with migrations support
- Architecture
- Prerequisites
- Getting Started
- Configuration
- Database Setup
- API Endpoints
- Project Structure
- Development
- Testing
- Deployment
- Contributing
The application follows a clean architecture pattern with clear separation of concerns:
- Controllers: Handle HTTP requests and responses
- Commands: Implement CQRS command pattern using MediatR
- Repositories: Abstract data access operations
- Domain Models: Core business entities
- DTOs: Data transfer objects for API contracts
- Exceptions: Custom exception types with global handling
- Database: Entity Framework Core context and migrations
- Framework: ASP.NET Core 10.0
- ORM: Entity Framework Core 10.0.1
- Database: PostgreSQL (via Npgsql)
- Mediator: MediatR 14.0.0
- API Versioning: Asp.Versioning 8.1.0
- Documentation: Swashbuckle.AspNetCore 10.0.1
- Containerization: Docker & Docker Compose
Before you begin, ensure you have the following installed:
- .NET 10.0 SDK
- Docker (for PostgreSQL)
- PostgreSQL (optional, if not using Docker)
- Git
- A code editor (JetBrains Rider, Visual Studio, or VS Code)
git clone <repository-url>
cd DeviceManagament
Using Docker Compose:
# Create a .env file with database credentials
cat > .env << EOF
POSTGRES_USER=devuser
POSTGRES_PASSWORD=devpassword
POSTGRES_DB=DeviceManagementDB
POSTGRES_PORT=5432
EOF
# Start the database
docker-compose up -d
Create appsettings.local.json in the DeviceManagament folder:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"ConnectionStrings": {
"DeviceManagerDB": "Host=localhost;Database=DeviceManagementDB;Username=devuser;Password=devpassword;Port=5432"
}
}
cd DeviceManagament
dotnet restore
# Install EF Core tools (if not already installed)
dotnet tool install --global dotnet-ef
# Apply migrations
dotnet ef database update
dotnet run
The API will be available at:
- HTTPS:
https://localhost:5001 - HTTP:
http://localhost:5000 - Swagger UI:
https://localhost:5001/swagger
The application supports different configuration files based on the environment:
appsettings.json- Base configurationappsettings.Development.json- Development environmentappsettings.local.json- Local development (gitignored)
Configure your PostgreSQL connection in the appropriate appsettings file:
{
"ConnectionStrings": {
"DeviceManagerDB": "Host=<host>;Database=<database>;Username=<username>;Password=<password>;Port=<port>"
}
}
For Docker deployment, configure these environment variables:
POSTGRES_USER- Database userPOSTGRES_PASSWORD- Database passwordPOSTGRES_DB- Database namePOSTGRES_PORT- Database port (default: 5432)
dotnet ef migrations add <MigrationName> --project DeviceManagament
dotnet ef database update --project DeviceManagament
dotnet ef migrations remove --project DeviceManagament
dotnet ef migrations script --project DeviceManagament
For detailed migration instructions, see docs/DATABASE_MIGRATIONS.md.
| Column | Type | Description |
|---|---|---|
| SerialNumber | GUID (PK) | Unique device identifier |
| ModelId | String | Device model identifier |
| ModelName | String | Device model name |
| Manufacturer | String | Device manufacturer |
| PrimaryUser | String (Email) | Email of primary user |
| OperatingSystem | String | Operating system name |
| DeviceType | Enum | Laptop or Desktop |
| DeviceStatus | Enum | Active, Inactive, or Retired |
https://localhost:5001/api/v1/Device
POST /api/v1/Device
Content-Type: application/json
{
"serialNumber": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"modelId": "XPS-15-9500",
"modelName": "XPS 15",
"manufacturer": "Dell",
"primaryUser": "user@example.com",
"operatingSystem": "Windows 11",
"deviceType": "Laptop",
"deviceStatus": "Active"
}
Response: 201 Created
{
"serialNumber": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"modelId": "XPS-15-9500",
"modelName": "XPS 15",
"manufacturer": "Dell",
"primaryUser": "user@example.com",
"operatingSystem": "Windows 11",
"deviceType": "Laptop",
"deviceStatus": "Active"
}
Error Responses:
400 Bad Request- Invalid device data409 Conflict- Device already exists500 Internal Server Error- Server error
PATCH /api/v1/Device/{serialNumber}
Content-Type: application/json
{
"serialNumber": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"modelId": "XPS-15-9500",
"modelName": "XPS 15",
"manufacturer": "Dell",
"primaryUser": "newuser@example.com",
"operatingSystem": "Windows 11 Pro",
"deviceType": "Laptop",
"deviceStatus": "Inactive"
}
Response: 200 OK
{
"serialNumber": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"modelId": "XPS-15-9500",
"modelName": "XPS 15",
"manufacturer": "Dell",
"primaryUser": "newuser@example.com",
"operatingSystem": "Windows 11 Pro",
"deviceType": "Laptop",
"deviceStatus": "Inactive"
}
Error Responses:
400 Bad Request- Serial number mismatch or invalid data404 Not Found- Device not found500 Internal Server Error- Server error
LaptopDesktop
ActiveInactiveRetired
The API supports versioning through:
-
URL Segment (Recommended):
https://localhost:5001/api/v1/Device -
Header:
X-Api-Version: 1.0
DeviceManagament/
├── DeviceManagament/ # Main API project
│ ├── Commands/ # MediatR command handlers
│ │ ├── InsertDeviceCommand.cs
│ │ └── UpdateDeviceCommand.cs
│ ├── Controllers/ # API controllers
│ │ └── DeviceController.cs
│ ├── Database/ # EF Core context
│ │ ├── DeviceManagerDbContext.cs
│ │ └── DeviceManagerDbContextFactory.cs
│ ├── Domain/ # Domain layer
│ │ ├── DTOs/
│ │ │ └── DeviceDto.cs
│ │ └── Models/
│ │ └── Device.cs
│ ├── Exceptions/ # Custom exceptions
│ │ ├── DeviceAlreadyExistsException.cs
│ │ ├── ExceptionFilter.cs
│ │ └── InvalidDeviceDataException.cs
│ ├── Migrations/ # EF Core migrations
│ ├── Repositories/ # Data access layer
│ │ └── DeviceRepository.cs
│ ├── Properties/
│ │ └── launchSettings.json
│ ├── appsettings.json
│ ├── appsettings.Development.json
│ ├── DeviceManagament.csproj
│ ├── Dockerfile
│ └── Program.cs
├── DeviceManagementTests/ # Unit and integration tests
│ └── ControllerTests/
│ ├── DeviceControllerInsertTests.cs
│ └── DeviceControllerUpdateTests.cs
├── docs/ # Documentation
│ ├── DATABASE_MIGRATIONS.md
│ └── QUICKSTART_MIGRATIONS.md
├── docker-compose.yml # Docker configuration
└── DeviceManagament.sln # Solution file
This project follows standard C# coding conventions:
- Use PascalCase for public members
- Use camelCase for private fields
- Use meaningful variable names
- Keep methods focused and small
- Write XML documentation for public APIs
- Create Domain Models in
Domain/Models/ - Create DTOs in
Domain/DTOs/ - Create Commands in
Commands/using MediatR - Create Repository Interface & Implementation in
Repositories/ - Create Controller Endpoints in
Controllers/ - Add Migrations using
dotnet ef migrations add - Write Tests in
DeviceManagementTests/
# Set environment to Development
export ASPNETCORE_ENVIRONMENT=Development # Linux/macOS
$env:ASPNETCORE_ENVIRONMENT="Development" # Windows PowerShell
# Run with hot reload
dotnet watch run
# Debug build
dotnet build
# Release build
dotnet build -c Release
# Publish
dotnet publish -c Release -o ./publish
# Run all tests
dotnet test
# Run with detailed output
dotnet test --verbosity detailed
# Run with code coverage
dotnet test /p:CollectCoverage=true
Tests are organized in the DeviceManagementTests project:
DeviceManagementTests/
└── ControllerTests/
├── DeviceControllerInsertTests.cs
└── DeviceControllerUpdateTests.cs
Example test structure:
[Fact]
public async Task InsertDevice_ValidDevice_ReturnsCreated()
{
// Arrange
var deviceDto = new DeviceDto { /* ... */ };
// Act
var result = await _controller.InsertDevice(deviceDto);
// Assert
Assert.IsType<CreatedResult>(result);
}
# Start all services
docker-compose up -d
# View logs
docker-compose logs -f
# Stop services
docker-compose down
# Remove volumes
docker-compose down -v
# Build the API image
docker build -t device-management-api:latest -f DeviceManagament/Dockerfile .
# Run the container
docker run -p 5000:8080 -e ConnectionStrings__DeviceManagerDB="<connection-string>" device-management-api:latest
When running in Development or Local environment, Swagger UI is available at:
https://localhost:5001/swagger
Swagger provides:
- Interactive API documentation
- Request/response schemas
- Try-it-out functionality
- API versioning support
Problem: Cannot connect to PostgreSQL database
Solution:
- Verify PostgreSQL is running:
docker-compose ps - Check connection string in
appsettings.local.json - Ensure database exists:
docker exec -it devicemanagement-db psql -U devuser -d DeviceManagementDB
Problem: EF Core migration fails
Solution:
# Remove last migration
dotnet ef migrations remove
# Clear database and reapply
dotnet ef database drop
dotnet ef database update
Problem: Port 5000/5001 already occupied
Solution:
- Change ports in
Properties/launchSettings.json - Or kill the process using the port:
# macOS/Linux lsof -ti:5000 | xargs kill -9 # Windows netstat -ano | findstr :5000 taskkill /PID <PID> /F
Problem: Swagger UI not accessible
Solution:
- Ensure environment is Development or Local
- Check
Program.csSwagger configuration - Verify running on correct URL
Enable detailed logging in appsettings.Development.json:
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"Microsoft.AspNetCore": "Debug",
"Microsoft.EntityFrameworkCore": "Information"
}
}
}
- Database Migrations Guide - Comprehensive EF Core migrations documentation
- Quick Start Migrations - Fast migration setup guide
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit your changes:
git commit -m 'Add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request
- Follow existing code style and conventions
- Write unit tests for new features
- Update documentation as needed
- Ensure all tests pass before submitting PR
- Keep commits atomic and well-described
This project is licensed under the MIT License - see the LICENSE file for details.
- Your Name - Initial work
- ASP.NET Core team for the excellent framework
- Entity Framework Core team
- MediatR library contributors
- PostgreSQL community
For issues and questions:
- Create an issue in the repository
- Check existing documentation in
/docs - Review troubleshooting section above
Future enhancements:
- Add GET endpoints for retrieving devices
- Implement pagination for device lists
- Add filtering and search capabilities
- Implement authentication and authorization
- Add device history tracking
- Create admin dashboard
- Add bulk operations support
- Implement caching layer
- Add health check endpoints
- Implement rate limiting
Built with ❤️ using ASP.NET Core