AspNetRestKit
A secure ASP.NET Core Web API starter kit with JWT authentication, role-based authorization, multi-database support, audit logging, Serilog, API versioning, pagination, filtering, sorting, CI/CD, and Swagger documentation.
AspNetRestKit is a practical ASP.NET Core Web API starter kit for building and studying clean backend APIs. It keeps a single main Web API project while separating responsibilities through controllers, services, repositories, DTOs, mappers, middleware, settings, and data access folders.
## Table of Contents
- [Overview](#overview)
- [Features](#features)
- [Architecture](#architecture)
- [Technologies](#technologies)
- [Getting Started](#getting-started)
- [Running with Visual Studio](#running-with-visual-studio)
- [Running with .NET CLI](#running-with-net-cli)
- [Configuration](#configuration)
- [Database Providers](#database-providers)
- [Database Scripts](#database-scripts)
- [Authentication and Authorization](#authentication-and-authorization)
- [API Endpoints](#api-endpoints)
- [Example Requests](#example-requests)
- [CI/CD](#cicd)
- [Logging and Audit](#logging-and-audit)
- [Security Notes](#security-notes)
- [Useful Commands](#useful-commands)
- [Contributing](#contributing)
- [License](#license)
## Overview
AspNetRestKit demonstrates modern backend development patterns in a compact and approachable ASP.NET Core Web API codebase.
It includes authentication, authorization, multi-database configuration, API versioning, pagination, filtering, sorting, global exception handling, audit logging, structured logging, CI/CD, and Swagger documentation.
The project intentionally uses a single main project structure instead of a multi-project enterprise layout. This keeps the repository easy to inspect while still preserving clear boundaries between HTTP, business logic, data access, mapping, configuration, and middleware.
## Features
### API
- Product and Category CRUD operations
- JWT authentication
- Refresh token support
- Role-based authorization
- API versioning with `/api/v1`
- Pagination, filtering, and sorting
- Swagger/OpenAPI documentation
- Standard API response format
### Data
- Entity Framework Core
- SQLite support
- SQL Server support
- PostgreSQL support
- EF Core design-time DbContext factory
- Provider-based SQL scripts under `/database`
- Soft delete support
- Seed data
### Security
- Password hashing
- JWT Bearer authentication
- Admin/User role model
- Security headers
- Rate limiting
- Custom validation responses
- Global exception handling
- No stack trace exposure in API responses
### Quality
- Serilog console and file logging
- Audit logging
- GitHub Actions CI pipeline
- Visual Studio compatible launch profiles
- Hardened `.gitignore`
## Architecture
| Folder | Responsibility |
|---|---|
| `Controllers` | Handles HTTP requests and delegates business logic to services |
| `Services` | Contains business rules and application logic |
| `DAL` | Contains DbContext, repositories, configurations, and seed data |
| `Models` | Contains database entities |
| `DTOs` | Contains feature-specific request and response models |
| `Mapper` | Contains manual mapping logic |
| `Middleware` | Contains exception handling and security headers |
| `Settings` | Contains strongly typed configuration models |
| `database` | Contains provider-specific SQL scripts |
## Technologies
| Technology | Purpose |
|---|---|
| .NET 8 | Runtime and framework |
| ASP.NET Core Web API | REST API development |
| Entity Framework Core | ORM and database access |
| SQLite | Default local database |
| SQL Server | Supported relational database |
| PostgreSQL | Supported relational database |
| JWT Bearer | Authentication |
| Serilog | Structured logging |
| Swagger / OpenAPI | API documentation |
| GitHub Actions | CI pipeline |
## Getting Started
### Prerequisites
- .NET 8 SDK
- Git
- Visual Studio 2022, Visual Studio 2026, or the latest Visual Studio version
- SQL Server or PostgreSQL only if you want to use them instead of SQLite
### Clone the Repository
```bash
git clone https://github.com/hamzadenizyilmaz/AspNetRestKit.git
cd AspNetRestKit
```
### Restore Packages
```bash
dotnet restore
```
### Build
```bash
dotnet build
```
## Running with Visual Studio
1. Open Visual Studio 2026, Visual Studio 2022, or the latest Visual Studio version.
2. Select **Open a project or solution**.
3. Open `AspNetRestKit.sln`.
4. Wait for NuGet restore to complete.
5. Make sure `AspNetRestKit` is selected as the startup project.
6. Select the `https` launch profile.
7. Press `F5` or `Ctrl + F5`.
8. Swagger UI should open automatically.
Default Swagger URLs:
- `https://localhost:7025/swagger`
- `http://localhost:5025/swagger`
### Package Manager Console
Open:
```txt
Tools > NuGet Package Manager > Package Manager Console
```
Set the default project to:
```txt
AspNetRestKit
```
Run:
```powershell
Add-Migration InitialCreate
Update-Database
```
### Common Visual Studio Fixes
| Problem | Solution |
|---|---|
| Project does not load | Install .NET 8 SDK |
| NuGet packages are missing | Restore NuGet packages |
| HTTPS error | Run `dotnet dev-certs https --trust` |
| Swagger does not open | Visit `https://localhost:7025/swagger` manually |
| Migration fails | Check the default project and `ApplicationDbContextFactory` |
## Running with .NET CLI
```bash
dotnet restore
dotnet build
dotnet ef migrations add InitialCreate
dotnet ef database update
dotnet run
```
Open Swagger:
```txt
https://localhost:7025/swagger
```
## Configuration
Main configuration file:
```txt
appsettings.json
```
Important configuration sections:
| Section | Description |
|---|---|
| `DatabaseSettings` | Selects the active database provider |
| `ConnectionStrings` | Contains provider-specific connection strings |
| `JwtSettings` | Configures JWT issuer, audience, secret, and expiration |
| `Serilog` | Configures console and file logging |
| `SwaggerSettings` | Configures Swagger title, version, and description |
Do not use the default JWT secret in production. Use environment variables, user secrets, or a secret manager.
```bash
dotnet user-secrets init
dotnet user-secrets set "JwtSettings:Secret" "your-secure-development-secret"
```
## Database Providers
AspNetRestKit supports three database providers:
- SQLite
- SQL Server
- PostgreSQL
The default provider is SQLite.
Provider selection is controlled from `appsettings.json`:
```json
"DatabaseSettings": {
"Provider": "SQLite",
"ConnectionString": ""
}
```
Available connection strings:
```json
"ConnectionStrings": {
"SQLite": "Data Source=aspnetrestkit.db",
"SqlServer": "Server=localhost;Database=AspNetRestKitDb;Trusted_Connection=True;TrustServerCertificate=True;",
"PostgreSQL": "Host=localhost;Port=5432;Database=AspNetRestKitDb;Username=postgres;Password=your_password"
}
```
If `DatabaseSettings.ConnectionString` is empty, the application uses the connection string matching the selected provider.
### Switching Provider
1. Open `appsettings.json`.
2. Change `DatabaseSettings.Provider`.
3. Update the related connection string.
4. Create a migration for the selected provider.
5. Apply the database update.
Example:
```bash
dotnet ef migrations add InitialCreate_PostgreSQL
dotnet ef database update
```
## Database Scripts
The `/database` folder contains provider-specific SQL scripts.
```txt
database/
+-- sqlite/
| +-- schema.sql
| +-- seed.sql
+-- sqlserver/
| +-- schema.sql
| +-- seed.sql
+-- postgresql/
+-- schema.sql
+-- seed.sql
```
These scripts are optional and can be used for manual database setup or review. The recommended setup method is EF Core migrations:
```bash
dotnet ef migrations add InitialCreate
dotnet ef database update
```
Generate a SQL script from migrations:
```bash
dotnet ef migrations script -o database/generated-script.sql
```
SQL syntax differs between SQLite, SQL Server, and PostgreSQL, so scripts are separated by provider.
## Authentication and Authorization
AspNetRestKit uses JWT Bearer authentication with refresh token support.
### Roles
| Role | Description |
|---|---|
| `Admin` | Can create, update, delete, and manage protected resources |
| `User` | Can access authenticated user endpoints |
### Auth Flow
1. Register a user.
2. Login with credentials.
3. Copy the access token.
4. Click **Authorize** in Swagger.
5. Enter the token as `Bearer YOUR_TOKEN`.
6. Call protected endpoints.
### Authorization Rules
| Resource | Access |
|---|---|
| Auth register/login/refresh token | Public |
| Product and Category GET endpoints | Public |
| Product and Category write endpoints | Admin |
| Audit logs | Admin |
| Current user endpoint | Authenticated user |
| Refresh token revoke | Authenticated user |
## API Endpoints
### Auth
| Method | Endpoint | Access | Description |
|---|---|---|---|
| POST | `/api/v1/auth/register` | Public | Register user |
| POST | `/api/v1/auth/login` | Public | Login and receive token |
| POST | `/api/v1/auth/refresh-token` | Public | Refresh access token |
| POST | `/api/v1/auth/revoke-token` | Authenticated | Revoke refresh token |
| GET | `/api/v1/auth/me` | Authenticated | Get current user |
### Products
| Method | Endpoint | Access | Description |
|---|---|---|---|
| GET | `/api/v1/products` | Public | Get paged, filtered, and sorted products |
| GET | `/api/v1/products/{id}` | Public | Get product by ID |
| GET | `/api/v1/products/by-category/{categoryId}` | Public | Get products by category |
| POST | `/api/v1/products` | Admin | Create product |
| PUT | `/api/v1/products/{id}` | Admin | Update product |
| PATCH | `/api/v1/products/{id}/status` | Admin | Change product status |
| DELETE | `/api/v1/products/{id}` | Admin | Soft delete product |
Product query parameters:
`search`, `categoryId`, `minPrice`, `maxPrice`, `isActive`, `pageNumber`, `pageSize`, `sortBy`, `sortDirection`
### Categories
| Method | Endpoint | Access | Description |
|---|---|---|---|
| GET | `/api/v1/categories` | Public | Get paged, filtered, and sorted categories |
| GET | `/api/v1/categories/{id}` | Public | Get category by ID |
| POST | `/api/v1/categories` | Admin | Create category |
| PUT | `/api/v1/categories/{id}` | Admin | Update category |
| PATCH | `/api/v1/categories/{id}/status` | Admin | Change category status |
| DELETE | `/api/v1/categories/{id}` | Admin | Soft delete category |
Category query parameters:
`search`, `isActive`, `pageNumber`, `pageSize`, `sortBy`, `sortDirection`
### Audit Logs
| Method | Endpoint | Access | Description |
|---|---|---|---|
| GET | `/api/v1/audit-logs` | Admin | Get paged audit logs |
### System
| Method | Endpoint | Access | Description |
|---|---|---|---|
| GET | `/` | Public | API status |
| GET | `/health` | Public | Health check |
## Example Requests
### Login
```http
POST /api/v1/auth/login
Content-Type: application/json
```
```json
{
"email": "demo@example.local",
"password": "ChangeThisPassword123!"
}
```
### Get Products with Pagination, Filtering, and Sorting
```http
GET /api/v1/products?search=mouse&minPrice=10&maxPrice=100&pageNumber=1&pageSize=10&sortBy=price&sortDirection=asc
```
### Create Product
```http
POST /api/v1/products
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
```
```json
{
"name": "Wireless Mouse",
"description": "Ergonomic wireless mouse",
"price": 29.99,
"stockQuantity": 50,
"sku": "ELEC-MOUSE-001",
"categoryId": "REPLACE_WITH_CATEGORY_ID"
}
```
## CI/CD
This repository includes a GitHub Actions workflow:
```txt
.github/workflows/dotnet-ci.yml
```
The pipeline runs on push and pull requests to `main`.
It performs:
- Restore
- Build
- Vulnerable package check
## Logging and Audit
AspNetRestKit uses Serilog for structured logging.
Logs are written to:
```txt
logs/aspnetrestkit-.log
```
Log files are ignored by Git.
Audit logging records important operations such as:
- User registration
- User login
- Product create/update/delete/status changes
- Category create/update/delete/status changes
- Refresh token revoke
Audit logs are available for Admin users through:
```txt
GET /api/v1/audit-logs
```
## Security Notes
Before using this project in production:
- Replace the default JWT secret.
- Store secrets using environment variables, user secrets, or a secret manager.
- Restrict CORS origins.
- Protect or disable Swagger.
- Use HTTPS.
- Use a production database configuration.
- Review rate limiting settings.
- Do not commit real database passwords.
- Do not commit `.db`, `.mdf`, `.ldf`, `.env`, log, or secret files.
- Run dependency vulnerability checks regularly.
Check vulnerable packages:
```bash
dotnet list package --vulnerable
```
## Useful Commands
| Command | Description |
|---|---|
| `dotnet restore` | Restore NuGet packages |
| `dotnet build` | Build the solution |
| `dotnet run` | Run the API |
| `dotnet format` | Format the code |
| `dotnet ef migrations add InitialCreate` | Create EF Core migration |
| `dotnet ef database update` | Apply database migration |
| `dotnet ef migrations script -o database/generated-script.sql` | Generate SQL script |
| `dotnet list package --vulnerable` | Check vulnerable packages |
| `dotnet dev-certs https --trust` | Trust local HTTPS certificate |
## Contributing
Contributions are welcome.
To contribute:
1. Fork the repository.
2. Create a feature branch.
3. Make your changes.
4. Run `dotnet build`.
5. Open a pull request.
Please keep the code clean, documented where necessary, and consistent with the existing structure.
## License
This project is licensed under the GNU General Public License v3.0.
See the [LICENSE](LICENSE) file for details.