A modern, fully-featured blogging platform built with Clean Architecture, ASP.NET Core, and Entity Framework Core. DevPulse demonstrates enterprise-grade API design with authentication, authorization, comprehensive blog management, and structured logging capabilities.
DevPulse is a RESTful blogging platform that enables users to create, manage, and discover blog posts. The application leverages Clean Architecture principles to ensure separation of concerns, maintainability, and scalability. It showcases modern .NET development practices and design patterns with professional-grade logging and monitoring.
Key Highlights:
- 🏗️ Clean Architecture with clear separation of concerns
- 🔐 JWT-based authentication and role-based authorization
- 📝 Full blog lifecycle management (Create, Read, Update, Delete)
- 🏷️ Category-based blog organization and filtering
- 🔒 User ownership authorization for blog content
- 🛠️ Enterprise design patterns (Generic Repository, Unit of Work, Dependency Injection)
- 📊 Global exception handling with standardized responses
- 📋 Structured logging with Serilog and Seq integration
- 📁 File storage and image management for profiles and blogs
- 🔄 Automatic data seeding and database migrations
- User Registration & Login - Secure account creation with email verification
- JWT Authentication - Token-based authentication for protected endpoints
- Role-Based Authorization - Admin and User roles with granular access control
- User Ownership Validation - Users can only modify their own blogs
- Get User Profile - Authenticated users can view their profile information (FirstName, LastName, Email, ImageUrl)
- Update User Profile - Users can update their personal information and upload a profile image
- Image Handling - Automatic image upload to storage with old image cleanup
- Create Blogs - Authenticated users can publish blogs with title, content, category, and optional images
- Read Blogs - Public access to browse all blogs or filter by category
- Update Blogs - Users can edit only their own published blogs
- Delete Blogs - Users can delete only their own blogs
- User Blog Retrieval - Authenticated users can view their own blog collection
- Browse Categories - Public access to view all available categories
- Admin Management - Admin users can create, update, and delete categories and update, delete any blog for any user
- Input Validation - Data Annotations for comprehensive validation rules
- Global Exception Handling - Centralized error handling middleware
- Standardized API Responses - Consistent response format across all endpoints
DevPulse follows Clean Architecture principles with a layered approach:
┌─────────────────────────────────────────────────────┐
│ DevPulseApp (API Layer) │
│ Controllers | Middleware | WebConfig │
└────────────────────┬────────────────────────────────┘
│
┌────────────────────┴────────────────────────────────┐
│ Application (Business Logic) │
│ Services | DTOs | Interfaces | Dependency Setup │
└────────────────────┬────────────────────────────────┘
│
┌────────────────────┴────────────────────────────────┐
│ Infrastructure (Data Access) │
│ UnitOfWork | Repositories | DbContext | Services │
└────────────────────┬────────────────────────────────┘
│
┌────────────────────┴────────────────────────────────┐
│ Domain (Core Entities) │
│ ApplicationUser | Blog | Category │
└─────────────────────────────────────────────────────┘
| Pattern | Purpose |
|---|---|
| Generic Repository Pattern | Centralized data access logic with reusable CRUD operations |
| Unit of Work Pattern | Transaction management and coordinated repository operations |
| Dependency Injection | Loose coupling and easy testability |
| DTO Pattern | Clean separation between API contracts and domain models |
| Middleware Pattern | Cross-cutting concerns (exception handling, authentication, logging) |
| Factory Pattern | Service registration through extension methods |
DevPulse/
├── DevPulseApp/ # API Layer (ASP.NET Core Web API)
│ ├── Controllers/
│ │ ├── AccountController.cs # Authentication endpoints
│ │ ├── BlogController.cs # Blog CRUD and filtering
│ │ └── CategoryController.cs # Category management
│ ├── Middlewares/
│ │ └── GlobalExceptionMiddleware.cs # Centralized error handling & logging
│ ├── ExtensionMethods/
│ │ └── WebApplicationRegister.cs # App configuration extensions
│ ├── Program.cs # Application entry point with Serilog setup
│ ├── appsettings.json # Configuration (Serilog, JWT, Database)
│ ├── Properties/
│ │ └── launchSettings.json
│ └── wwwroot/ # Static files directory
│
├── Application/ # Business Logic Layer
│ ├── Services/
│ │ ├── BlogService.cs
│ │ └── CategoryService.cs
│ ├── Interfaces/
│ │ ├── Services/
│ │ │ ├── IAccountService.cs
│ │ │ ├── IBlogService.cs
│ │ │ ├── ICategoryService.cs
│ │ │ ├── IJwtService.cs
│ │ │ ├── IUserProfileService.cs
│ │ │ └── IFileStorageService.cs
│ │ ├── Repositories/
│ │ │ └── IGenericRepository.cs
│ │ ├── UnitOfWork/
│ │ │ └── IUnitOfWork.cs
│ │ └── DataSeeding/
│ │ └── IDataInitializer.cs
│ ├── DTOs/
│ │ ├── AccountDTOs/
│ │ │ ├── RegisterDto.cs
│ │ │ ├── LoginDto.cs
│ │ │ ├── UpdateUserDto.cs
│ │ │ └── GetProfileDto.cs
│ │ ├── BlogDTOs/
│ │ │ ├── CreateBlogDto.cs
│ │ │ ├── GetBlogDto.cs
│ │ │ └── UpdateBlogDto.cs
│ │ ├── CategoryDTOs/
│ │ │ ├── CreateCategoryDto.cs
│ │ │ ├── GetCategoryDto.cs
│ │ │ ├── GetCategoryWithoutBlogsDto.cs
│ │ │ └── UpdateCategoryDto.cs
│ │ └── JwtDTOs/
│ │ └── JwtDto.cs
│ ├── Mapper/
│ │ └── DomainProfile.cs # AutoMapper configuration
│ └── DependencyInjection/
│ └── ApplicationServiceRegistration.cs
│
├── Infrastructure/ # Data Access Layer
│ ├── Database/
│ │ ├── ApplicationDbContext.cs # Entity Framework Core context
│ │ └── Migrations/
│ ├── Configurations/
│ │ ├── ApplicationUserConfiguration.cs
│ │ ├── BlogConfiguration.cs
│ │ └── CategoryConfiguration.cs
│ ├── Repositories/
│ │ └── GenericRepository.cs
│ ├── Services/
│ │ ├── AccountService.cs
│ │ ├── JwtService.cs
│ │ └── UserProfileService.cs
│ ├── UnitOfWork/
│ │ └── UnitOfWork.cs
│ ├── DataSeeding/
│ │ └── DataInitializer.cs
│ └── DependencyInjection/
│ └── InfrastructureServiceRegistration.cs
│
└── Domain/ # Core Domain Layer
├── Entities/
│ ├── BaseEntity.cs # Base entity with generic Id
│ ├── ApplicationUser.cs # User with Identity
│ ├── Blog.cs # Blog entity
│ └── Category.cs # Category entity
└── Domain.csproj
Extends ASP.NET Core Identity User with profile information:
FirstName,LastName- User profileImageUrl- Profile picture URLBlogs- Collection of user's published blogs
Core blog entity with rich content:
Title- Blog title (3-200 characters)Content- Blog body (20-10,000 characters)ImageUrl- Optional featured image URLCategoryId- Foreign key to CategoryUserId- Foreign key to ApplicationUser (owner)CreatedAt- Publication timestamp
Content organization:
Name- Category nameBlogs- Collection of blogs in this category
- Token Generation - Issued upon successful login
- Token Validation - Custom claims and signature verification
- Configuration - Issuer, Audience, and expiration settings in
appsettings.json - Duration - Configurable token lifetime (default: 30 days)
- Admin Role - Category management, administrative operations
- User Role - Default role for registered users
- Public Access - Endpoints for anonymous users (blog browsing, category listing)
[AllowAnonymous] // Public endpoint
[Authorize] // Authenticated
[Authorize(Roles = "Admin")] // Admin users only
DevPulse uses Serilog for structured, richly-detailed logging. The logging pipeline captures:
- Application Events - Service operations, business logic execution
- HTTP Requests/Responses - Request details and outcomes
- Exceptions - Detailed error information with stack traces
- Authentication Events - Login attempts and token operations
The application is configured to write logs to multiple sinks via appsettings.json:
"Serilog": {
"MinimumLevel": "Information",
"WriteTo": [
{
"Name": "Console"
},
{
"Name": "Seq",
"Args": {
"serverUrl": "http://localhost:5341"
}
}
]
}- Console Sink - Real-time logs in the application console
- Seq Sink - Centralized log aggregation and analysis at
http://localhost:5341
Seq is a centralized structured log server that provides:
- Log Aggregation - Collect logs from all application instances
- Querying - Search and filter logs using powerful query language
- Dashboards - Visualize application health and metrics
- Alerts - Create alerts based on log patterns
# Run Seq in Docker
docker run -d -e ACCEPT_EULA=Y -p 5341:80 datalust/seq
# Access Seq UI
http://localhost:5341The GlobalExceptionMiddleware catches all unhandled exceptions and:
- Logs exception details using Serilog
- Returns standardized error responses
- Maintains request context for debugging
DevPulse supports image uploads for user profiles and blog posts with professional file handling:
- User Profile Images - Upload profile pictures when creating/updating user profile
- Blog Post Images - Add featured images to blog posts
- File Validation - Server-side validation for file type and size
- Organized Storage - Files stored in dedicated folders (Users, Blogs) in
wwwroot
- Automatic Cleanup - Old images automatically removed when replaced
- Path Management - Images accessible via relative URLs
- Error Handling - Graceful error responses for upload failures
- Storage Service -
IFileStorageServicehandles all file operations
- ASP.NET Core 9 - High-performance web framework
- .NET 9 - Latest .NET runtime with performance improvements
- Entity Framework Core 9.0.16 - Object-relational mapping
- SQL Server - Relational database
- LINQ - Data queries and operations
- ASP.NET Core Identity - User management and authentication
- JWT Bearer Authentication - Token-based security
- SymmetricSecurityKey - Token encryption/decryption
- Microsoft Dependency Injection - Service registration and resolution
- AutoMapper 16.1.1 - Object-to-object mapping for DTOs
- Serilog.AspNetCore 10.0.0 - Structured logging for ASP.NET Core
- Serilog.Settings.Configuration 10.0.0 - Configuration-based Serilog setup
- Serilog.Sinks.Seq 9.1.0 - Seq server sink for log aggregation
- Swagger/OpenAPI - Interactive API documentation
- Swagger UI - Web-based API testing interface
- Swashbuckle.AspNetCore 9.0.6 - Swagger tooling for ASP.NET Core
- System.ComponentModel.DataAnnotations - Declarative validation rules
- Custom Validation - Email, StringLength, Required attributes
- Global Exception Middleware - Centralized error handling with logging
- Custom Response Format - Standardized API responses
- Microsoft.AspNetCore.Authentication.JwtBearer 9.0.16
- Microsoft.AspNetCore.OpenApi 9.0.16
- Microsoft.EntityFrameworkCore.Tools 9.0.16
- Serilog.AspNetCore 10.0.0
- Serilog.Settings.Configuration 10.0.0
- Serilog.Sinks.Seq 9.1.0
- Swashbuckle.AspNetCore 9.0.6
- Microsoft.AspNetCore.Authentication.JwtBearer 9.0.16
- Microsoft.AspNetCore.Identity.EntityFrameworkCore 9.0.16
- Microsoft.EntityFrameworkCore 9.0.16
- Microsoft.EntityFrameworkCore.Design 9.0.16
- Microsoft.EntityFrameworkCore.SqlServer 9.0.16
- AutoMapper 16.1.1
- .NET 9 SDK - Download
- SQL Server - Any version (LocalDB, Developer Edition, or Express)
- Visual Studio 2022 or VS Code with C# extension
- Clone the Repository
git clone https://github.com/Gargera/DevPulse-WebAPI.git
cd "DevPulse (Web API)"- Configure Database Connection
- Open
DevPulseApp/appsettings.json - Update
ConnectionStrings:DefaultConnectionwith your SQL Server connection string:
- Open
"ConnectionStrings": {
"DefaultConnection": "Server=.;Database=DevPulseDb;Trusted_Connection=true;TrustServerCertificate=true;"
}- Configure JWT Settings
- Update JWT settings in
appsettings.json:
- Update JWT settings in
"JWT": {
"Key": "your-secret-key-here-minimum-64-characters",
"Issuer": "DevPulseAPI",
"Audience": "DevPulseClient",
"DurationInDays": 30
}- Security Note: Use
dotnet user-secretsfor sensitive configuration in production
- Setup Serilog Logging (Optional but Recommended)
- Option A: Console Logging Only - Default configuration logs to console
- Option B: With Seq Server - For advanced log analysis:
# Run Seq using Docker
docker run -d -e ACCEPT_EULA=Y -p 5341:80 datalust/seq
# Access Seq UI at http://localhost:5341- Ensure
appsettings.jsonhas Seq sink configured:"Serilog": { "MinimumLevel": "Information", "WriteTo": [ { "Name": "Console" }, { "Name": "Seq", "Args": { "serverUrl": "http://localhost:5341" } } ] }
- Restore Dependencies
dotnet restore- Apply Migrations
dotnet ef database update --project Infrastructure --startup-project DevPulseApp- Run the Application
dotnet run --project DevPulseApp- Access the Application
- API:
https://localhost:5001 - Swagger UI:
https://localhost:5001/swagger - Seq Dashboard:
http://localhost:5341(if Seq is running)
- API:
Instead of hardcoding sensitive data in appsettings.json, use User Secrets:
# Initialize user secrets
dotnet user-secrets init --project DevPulseApp
# Set connection string
dotnet user-secrets set "ConnectionStrings:DefaultConnection" "Your_Connection_String" --project DevPulseApp
# Set JWT key
dotnet user-secrets set "JWT:Key" "Your_JWT_Secret_Key" --project DevPulseApp
# Set Seq server URL (optional)
dotnet user-secrets set "Serilog:WriteTo:1:Args:serverUrl" "Your_Seq_Server_URL" --project DevPulseAppPOST /api/account/register- Create new user accountPOST /api/account/login- Authenticate and receive JWT tokenGET /api/account/UserProfile- Get current user profile (authenticated)PUT /api/account/update- Update user profile with FirstName, LastName, and Image (authenticated)
GET /api/blog- Get all blogs (public)GET /api/blog/{id}- Get blog by ID (public)GET /api/blog/category/{categoryId}- Filter blogs by category (public)GET /api/blog/my-blogs- Get current user's blogs (authenticated)POST /api/blog- Create new blog (authenticated)PUT /api/blog/{id}- Update blog (authenticated, owner and admins only)DELETE /api/blog/{id}- Delete blog (authenticated, owner and admins only)
GET /api/category- Get all categories (public)GET /api/category/{id}- Get category by ID (admin)POST /api/category- Create category (admin)PUT /api/category/{id}- Update category (admin)DELETE /api/category/{id}- Delete category (admin)
✅ User Profile Endpoints - Get and update user profile information
✅ Profile Image Upload - Support for user profile picture uploads
✅ File Storage Service - Professional image handling and storage
✅ Automatic Cleanup - Old files automatically removed when updated
✅ GetProfileDto & UpdateUserDto - Dedicated DTOs for profile operations
✅ IUserProfileService - Service layer for profile management
✅ Serilog Integration - Added structured logging with Serilog
✅ Seq Server Support - Integrated Seq for centralized log aggregation
✅ Multiple Sinks - Console and Seq sinks for flexible logging
✅ Exception Logging - Global exception middleware now logs all errors
✅ Configuration-Based Setup - Logging configuration in appsettings.json
✅ Clean Architecture Implementation
✅ JWT Authentication & Authorization
✅ Entity Framework Core Integration
✅ AutoMapper for DTOs
✅ Generic Repository Pattern
✅ Unit of Work Pattern
✅ Global Exception Handling
✅ Data Seeding
Gargera
- GitHub: @Gargera
- Repository: DevPulse-WebAPI
DevPulse © 2024-2026. Showcasing modern ASP.NET Core development practices, Clean Architecture principles, and enterprise-grade logging solutions.