Skip to content

A modern ASP.NET Core Web API demonstrating two-tier architecture with CQRS, MediatR, Dapper ORM, and SQL Server for comprehensive user management.

License

Notifications You must be signed in to change notification settings

a0s21en5/two-tier-user-management-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

7 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Two-Tier Web Application

A modern ASP.NET Core Web API application demonstrating a two-tier architecture with comprehensive user management functionality using CQRS pattern, MediatR, Dapper ORM, and SQL Server.

πŸ—οΈ Architecture

This application follows a two-tier architecture:

  • Presentation Tier: ASP.NET Core Web API with RESTful endpoints
  • Data Tier: SQL Server database with optimized data access using Dapper

Design Patterns & Technologies

  • CQRS (Command Query Responsibility Segregation) with MediatR
  • Repository Pattern with Dapper ORM
  • Validation using FluentValidation
  • Dependency Injection with built-in ASP.NET Core DI container
  • OpenAPI/Swagger documentation
  • Docker containerization support

πŸš€ Features

User Management

  • βœ… Create new users
  • βœ… Retrieve all active users
  • βœ… Get user by ID
  • βœ… Search users by email
  • βœ… Update existing users
  • βœ… Soft delete users
  • βœ… Input validation with detailed error messages

Technical Features

  • πŸ”„ Automatic database initialization
  • πŸ“Š Comprehensive API documentation with Swagger UI
  • 🐳 Docker containerization
  • πŸ›‘οΈ Input validation and error handling
  • πŸ“ˆ Performance optimized with database indexing
  • πŸ” Search functionality
  • πŸ“ Structured logging

πŸ› οΈ Technology Stack

Core Framework

  • 🎯 .NET 9.0 - Latest Microsoft development platform
  • 🌐 ASP.NET Core - Cross-platform web framework

Data & Persistence

  • πŸ—οΈ Dapper 2.1.35 - Lightweight, high-performance ORM
  • πŸ—„οΈ SQL Server 2022 - Enterprise-grade relational database
  • πŸ“Š Microsoft.Data.SqlClient 5.2.2 - Modern SQL Server connectivity

Architecture & Patterns

  • πŸ“‘ MediatR 12.4.1 - CQRS and Mediator pattern implementation
  • βœ… FluentValidation 11.10.0 - Fluent interface for validation rules

API & Documentation

  • πŸ“– Swashbuckle.AspNetCore 7.2.0 - OpenAPI/Swagger documentation
  • πŸ”§ Microsoft.AspNetCore.OpenApi 9.0.8 - OpenAPI specification support

Development & Deployment

  • 🐳 Docker - Containerization platform
  • πŸ”¨ Visual Studio Code - Recommended IDE with REST Client extension
  • βš™οΈ PowerShell - Windows development environment

πŸ“‹ Prerequisites

πŸš€ Getting Started

1. Clone the Repository

git clone https://github.com/a0s21en5/two-tier-user-management-api.git
cd two-tier-web-app

2. Choose Your Setup Method

You can run this application using either .NET CLI or Docker. Choose the method that best fits your environment:

Option A: Local Development (.NET CLI)

  1. Database Setup: Ensure SQL Server is running locally and update the connection string in appsettings.json:

    {
      "ConnectionStrings": {
        "DefaultConnection": "Server=localhost;Database=TwoTierWebAppDB;User Id=sa;Password=your-password;TrustServerCertificate=True;MultipleActiveResultSets=true;"
      }
    }
  2. Run the Application:

    dotnet restore
    dotnet build
    dotnet run

Option B: Full Docker Setup (Recommended)

  1. Create Docker Network:

    docker network create -d bridge two-tier
  2. Start SQL Server Container:

    docker run -d --name sqlserver2022 --network two-tier \
      -e "ACCEPT_EULA=Y" \
      -e "MSSQL_SA_PASSWORD=Obito#9775" \
      mcr.microsoft.com/mssql/server:2022-latest
  3. Build and Run Application:

    docker build -t two-tier-backend:v1 .
    docker run -d -p 5000:5000 --network two-tier two-tier-backend:v1

3. Access the Application

Once running, you can access the application at:

  • 🌐 API Base URL: http://localhost:5000
  • πŸ“– Swagger UI: http://localhost:5000/swagger
  • πŸ“‹ OpenAPI Spec: http://localhost:5000/swagger/v1/swagger.json

Note: The application runs on HTTP port 5000 when using Docker. For local development with .NET CLI, both HTTP (5000) and HTTPS (5001) are available.

πŸ“š API Documentation

πŸ”— API Endpoints

The application provides a RESTful API for user management operations:

Method Endpoint Description Status Codes
🟒 GET /api/users Retrieve all active users 200
🟒 GET /api/users/{id} Get user by ID 200, 400, 404
πŸ” GET /api/users/search?email={email} Search users by email 200, 400
βœ… POST /api/users Create a new user 201, 400, 500
πŸ”„ PUT /api/users/{id} Update existing user 204, 400, 404, 500
❌ DELETE /api/users/{id} Soft delete user 204, 400, 404, 500

πŸ“ Example API Calls

Create User

POST /api/users
Content-Type: application/json

{
  "firstName": "John",
  "lastName": "Doe",
  "email": "john.doe@example.com",
  "phone": "+1234567890"
}

Response (201 Created):

3

Get All Users

GET /api/users

Response (200 OK):

[
  {
    "id": 1,
    "firstName": "John",
    "lastName": "Doe",
    "email": "john.doe@example.com",
    "phone": "+1234567890",
    "createdDate": "2025-09-04T10:30:00Z",
    "updatedDate": null,
    "isActive": true
  },
  {
    "id": 2,
    "firstName": "Jane",
    "lastName": "Smith",
    "email": "jane.smith@example.com",
    "phone": "+1987654321",
    "createdDate": "2025-09-04T11:15:00Z",
    "updatedDate": "2025-09-04T12:00:00Z",
    "isActive": true
  }
]

Get User by ID

GET /api/users/1

Response (200 OK):

{
  "id": 1,
  "firstName": "John",
  "lastName": "Doe",
  "email": "john.doe@example.com",
  "phone": "+1234567890",
  "createdDate": "2025-09-04T10:30:00Z",
  "updatedDate": null,
  "isActive": true
}

Search Users by Email

GET /api/users/search?email=john

Update User

PUT /api/users/1
Content-Type: application/json

{
  "id": 1,
  "firstName": "John",
  "lastName": "Smith",
  "email": "john.smith@example.com",
  "phone": "+1234567890"
}

Response (204 No Content)

Delete User

DELETE /api/users/1

Response (204 No Content)

πŸ”§ Testing the API

  1. Swagger UI: Navigate to http://localhost:5000/swagger for interactive testing
  2. HTTP Files: Use the provided .http files in VS Code with REST Client extension
  3. Postman: Import the API endpoints using the OpenAPI specification
  4. cURL: Use command-line tools for testing

πŸ›‘οΈ Error Responses

The API returns consistent error responses:

{
  "errors": [
    "FirstName is required",
    "Email must be a valid email address"
  ]
}

Common HTTP status codes:

  • 200: Success
  • 201: Created
  • 204: No Content (successful update/delete)
  • 400: Bad Request (validation errors)
  • 404: Not Found
  • 500: Internal Server Error

πŸ—‚οΈ Project Structure

two-tier-web-app/
β”œβ”€β”€ πŸ“ Controllers/
β”‚   └── πŸ“„ UsersController.cs          # REST API endpoints and HTTP request handling
β”œβ”€β”€ πŸ“ Features/                       # CQRS implementation
β”‚   └── πŸ“ Users/
β”‚       β”œβ”€β”€ πŸ“ Commands/               # Write operations (Create, Update, Delete)
β”‚       β”œβ”€β”€ πŸ“ Queries/                # Read operations (Get, Search)
β”‚       └── πŸ“ Validators/             # FluentValidation rules for requests
β”œβ”€β”€ πŸ“ Infrastructure/                 # Core infrastructure services
β”‚   β”œβ”€β”€ πŸ“„ DatabaseInitializer.cs     # Automatic database setup and seeding
β”‚   └── πŸ“„ DbConnectionFactory.cs     # Database connection management
β”œβ”€β”€ πŸ“ Models/                         # Data models and DTOs
β”‚   └── πŸ“„ User.cs                     # User entity and request/response models
β”œβ”€β”€ πŸ“ Database/                       # Database scripts
β”‚   └── πŸ“„ CreateDatabase.sql          # Database schema and sample data
β”œβ”€β”€ πŸ“ Properties/                     # Application configuration
β”‚   └── πŸ“„ launchSettings.json         # Development server settings
β”œβ”€β”€ πŸ“„ Program.cs                      # Application entry point and service configuration
β”œβ”€β”€ πŸ“„ Dockerfile                      # Container configuration
β”œβ”€β”€ πŸ“„ appsettings.json               # Application configuration
β”œβ”€β”€ πŸ“„ appsettings.Development.json   # Development environment settings
β”œβ”€β”€ πŸ“„ appsettings.Production.json    # Production environment settings
└── πŸ“„ *.http                         # HTTP test files for API testing

πŸ›οΈ Architecture Layers

Presentation Layer

  • Controllers: Handle HTTP requests and responses
  • Validation: Input validation using FluentValidation

Application Layer

  • Commands: Handle write operations (CQRS)
  • Queries: Handle read operations (CQRS)
  • MediatR: Decouples request handling

Infrastructure Layer

  • Database: SQL Server with Dapper ORM
  • Connection Management: Factory pattern for database connections

Domain Layer

  • Models: Core business entities and DTOs

πŸ”§ Configuration

Environment-Specific Settings

The application supports multiple environments with specific configuration files:

  • appsettings.json - Base configuration
  • appsettings.Development.json - Development environment
  • appsettings.Production.json - Production environment

Key Configuration Options

{
  "ConnectionStrings": {
    "DefaultConnection": "Your SQL Server connection string"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  }
}

πŸ§ͺ Testing

Included Test Files

The project includes HTTP test files for comprehensive API testing:

  • πŸ“ two-tier-web-app.http - General API endpoint tests
  • πŸ“ two-tier-web-app-api.http - Specific user management scenarios

Testing Tools & Methods

1. VS Code REST Client (Recommended)

  • Install the "REST Client" extension in VS Code
  • Open any .http file and click "Send Request" above each HTTP call
  • View responses directly in VS Code

2. Swagger UI (Interactive)

  • Navigate to http://localhost:5000/swagger
  • Test all endpoints with an interactive interface
  • View request/response schemas and examples

3. Postman/Insomnia

  • Import the OpenAPI specification: http://localhost:5000/swagger/v1/swagger.json
  • Automatically generate a complete collection of API calls

4. cURL Command Line

# Test API health
curl -X GET "http://localhost:5000/api/users"

# Create a new user
curl -X POST "http://localhost:5000/api/users" \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "Test",
    "lastName": "User",
    "email": "test@example.com",
    "phone": "+1234567890"
  }'

Test Scenarios Covered

βœ… CRUD Operations

  • Create new users with valid data
  • Retrieve all users
  • Get specific users by ID
  • Update existing user information
  • Soft delete users

βœ… Validation Testing

  • Required field validation
  • Email format validation
  • Input length constraints
  • Invalid ID handling

βœ… Error Handling

  • Non-existent user lookup
  • Invalid request formats
  • Server error scenarios

Sample Test Data

The database initializes with sample users for immediate testing:

🐳 Docker Support

Network Architecture

The Docker setup uses a custom bridge network to enable communication between containers:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚           two-tier network          β”‚
β”‚                                     β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚  sqlserver2022  β”‚ β”‚ web-app    β”‚ β”‚
β”‚  β”‚  (SQL Server)   β”‚ β”‚ (Backend)  β”‚ β”‚
β”‚  β”‚  Port: 1433     β”‚ β”‚ Port: 5000 β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Container Management

View Running Containers

docker ps

Check Application Logs

# Get container ID first
docker ps

# View logs
docker logs <container-id>

# Follow logs in real-time
docker logs -f <container-id>

Stop and Clean Up

# Stop containers
docker stop sqlserver2022 <web-app-container-id>

# Remove containers
docker rm sqlserver2022 <web-app-container-id>

# Remove network
docker network rm two-tier

# Remove image (optional)
docker rmi two-tier-backend:v1

Alternative: Docker Compose

For easier management, create a docker-compose.yml file:

version: '3.8'

networks:
  two-tier:
    driver: bridge

services:
  sqlserver:
    image: mcr.microsoft.com/mssql/server:2022-latest
    container_name: sqlserver2022
    environment:
      - ACCEPT_EULA=Y
      - MSSQL_SA_PASSWORD=Obito#9775
    networks:
      - two-tier
    volumes:
      - sqlserver_data:/var/opt/mssql
    healthcheck:
      test: ["CMD-SHELL", "/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P Obito#9775 -Q 'SELECT 1'"]
      interval: 30s
      timeout: 10s
      retries: 3

  web-app:
    build: .
    container_name: two-tier-backend
    ports:
      - "5000:5000"
    depends_on:
      sqlserver:
        condition: service_healthy
    networks:
      - two-tier
    environment:
      - ASPNETCORE_ENVIRONMENT=Production
      - ConnectionStrings__DefaultConnection=Server=sqlserver2022,1433;Database=TwoTierWebAppDB;User Id=sa;Password=Obito#9775;TrustServerCertificate=True;MultipleActiveResultSets=true;

volumes:
  sqlserver_data:

Using Docker Compose

# Start all services
docker-compose up -d

# View logs
docker-compose logs -f

# Stop all services
docker-compose down

# Stop and remove volumes
docker-compose down -v

πŸ“Š Database Schema

Users Table

Column Type Description
Id INT IDENTITY Primary key
FirstName NVARCHAR(50) User's first name
LastName NVARCHAR(50) User's last name
Email NVARCHAR(100) User's email address
Phone NVARCHAR(20) User's phone number
CreatedDate DATETIME2 Record creation timestamp
UpdatedDate DATETIME2 Last update timestamp
IsActive BIT Soft delete flag

Indexes

  • IX_Users_Email - Email lookup optimization
  • IX_Users_IsActive - Active users filtering
  • IX_Users_CreatedDate - Date-based queries

πŸ” Validation Rules

Create User Request

  • FirstName: Required, max 50 characters
  • LastName: Required, max 50 characters
  • Email: Required, valid email format, max 100 characters
  • Phone: Required, max 20 characters

Update User Request

  • Id: Required, must be positive integer
  • All fields from Create User Request

πŸš€ Development

Adding New Features

  1. Commands/Queries: Add to Features/Users/Commands or Features/Users/Queries
  2. Validation: Add validators to Features/Users/Validators
  3. API Endpoints: Extend UsersController
  4. Database Changes: Update CreateDatabase.sql and DatabaseInitializer

Best Practices

  • Follow CQRS pattern for separation of concerns
  • Use FluentValidation for input validation
  • Implement proper error handling and logging
  • Write comprehensive API documentation
  • Use async/await for database operations

🀝 Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

πŸ“ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ“ž Support

For support and questions:

  • Create an issue in the repository
  • Contact the development team

Happy Coding! πŸŽ‰

About

A modern ASP.NET Core Web API demonstrating two-tier architecture with CQRS, MediatR, Dapper ORM, and SQL Server for comprehensive user management.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published