A full-stack, multi-project ASP.NET Core application for building and managing a personal portfolio website. The system is split into multiple APIs and web interfaces, all built following Clean Architecture and SOLID principles.
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Client Browser β
βββββββββββββββββ¬βββββββββββββββββββββββββββββ¬ββββββββββββββββββββ
β β
βΌ βΌ
βββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββββ
β WebMvc (Public Site) β β WebAdmin (Admin Panel) β
β ASP.NET Core MVC β β ASP.NET Core MVC β
ββββββββββββββ¬βββββββββββββ ββββββββββββββββ¬ββββββββββββββββ
β β
β βββββββββββββββββββββββ
βΌ βΌ
ββββββββββββββββββββββββββββββ ββββββββββββββββ ββββββββββββββββββββ
β DataAPI β β AuthAPI β β FileAPI β
β ASP.NET Core Web API β β JWT Auth β β Image / CV Mgmt β
ββββββββββββββββββββββββββββββ ββββββββββββββββ ββββββββββββββββββββ
β β
βΌ βΌ
PostgreSQL (Portfolio) PostgreSQL (Auth)
| Project | Type | Description |
|---|---|---|
PersonalPortfolio.WebMvc |
ASP.NET Core MVC | Public-facing portfolio website |
PersonalPortfolio.WebAdmin |
ASP.NET Core MVC | Admin panel to manage all portfolio content |
PersonalPortfolio.DataAPI |
ASP.NET Core Web API | RESTful API for all portfolio data (CRUD) |
PersonalPortfolio.AuthAPI |
ASP.NET Core Web API | JWT-based authentication and user management |
PersonalPortfolio.FileAPI |
ASP.NET Core Web API | Image and CV file upload/download/delete |
PersonalPortfolio.Application |
Class Library | DTOs, service interfaces, validators (FluentValidation) |
PersonalPortfolio.Domain |
Class Library | Domain entities (pure C# models) |
PersonalPortfolio.Infrastructure |
Class Library | Service implementations, JWT authorization handler, Serilog logging |
PersonalPortfolio.Persistence |
Class Library | EF Core contexts, repositories, DB configurations, seeders |
- Single-page portfolio with all sections loaded dynamically from the DataAPI
- Sections: About Me, Education, Experience, Projects, Skills, Blog, Contact
- Blog listing page and individual blog post detail pages with comments
- Visitors can post comments on blog posts
- Contact form for sending messages to the portfolio owner
- CV download button served directly from the FileAPI
- JWT authentication with cookie-based session management (HttpOnly cookies)
- Role-based access:
AdminandVisitorroles - Full CRUD management for all portfolio sections: About Me, Education, Experience, Projects, Skills, Blog Posts, Comments, Contact Messages, Users
- Dashboard with summary stats: pending comments count, unread contact messages, recent blog posts, entity counts
- CV management: upload, download, and delete CV (PDF) via the FileAPI
- Image upload support for blog posts and projects via the FileAPI
- User registration and login (
/api/accounts/register,/api/accounts/authenticate) - JWT tokens signed with HMAC-SHA256 with configurable expiry
- ASP.NET Core Identity integration for user and role management
- New users are automatically assigned the
Visitorrole on registration - Role claims embedded in JWT for fine-grained access control
- Image upload/download/delete β supports
.jpg,.jpeg,.png(max 10 MB) - CV upload/download/delete β supports
.pdfonly (max 10 MB) - Files stored on the server's local filesystem
- Unique
GUID-based filenames to prevent collisions
- Full RESTful CRUD for all entities
- Separate Read/Write repositories per entity for clean separation
- FluentValidation on all DTOs for input validation
- AutoMapper for clean DTO β domain model mapping
- Swagger UI available in development mode
- Database seeder runs on startup in development to populate initial data
| Technology | Usage |
|---|---|
| .NET 8 | Core framework |
| ASP.NET Core MVC | WebMvc (public site) & WebAdmin (admin panel) |
| ASP.NET Core Web API | DataAPI, AuthAPI, FileAPI |
| Entity Framework Core | ORM for database access |
| PostgreSQL | Two separate databases (portfolio data + auth/identity) |
| ASP.NET Core Identity | User management and role-based authorization |
| JWT Bearer Authentication | Stateless authentication across APIs |
| FluentValidation | DTO validation with rich rule sets |
| AutoMapper | DTO β domain model mapping |
| Serilog | Structured logging |
| Clean Architecture | Project structure and dependency direction |
| Repository Pattern | Separate IReadRepository / IWriteRepository per entity |
| Bootstrap + SCSS | Frontend styling for public site |
| Entity | Key Fields |
|---|---|
BlogPost |
Title, Content, Description, ImageUrl, AuthorId, PublishDate, Comments |
Comment |
Content, AuthorName, BlogPostId, IsApproved |
Project |
Title, Description, ImageUrl, GithubLink |
Skill |
Name |
Education |
School, Department, StartDate, EndDate |
Experience |
Company, Position, StartDate, EndDate |
PersonalInfos |
Name, Surname, Email, Phone, LinkedIn, GitHub, Twitter, Website, BirthDate |
AboutMe |
Content |
ContactMessage |
FullName, Email, Subject, Message, IsRead |
User |
FirstName, LastName, Email (extends IdentityUser) |
Role |
(extends IdentityRole) |
- Register β
POST /api/accounts/registerβ user created, assignedVisitorrole - Login β
POST /api/accounts/authenticateβ returns JWT token + user info - Admin Panel β JWT stored as an HttpOnly cookie (
JWToken); injected into API requests via cookie - Authorization β
[Authorize]and[Authorize(Roles = "Admin")]attributes control access
| Resource | GET (all) | GET (by id) | POST | PUT | DELETE |
|---|---|---|---|---|---|
| Blog Posts | β | β | β | β | β (single & bulk) |
| Comments | β | β | β | β | β |
| Projects | β | β | β | β | β |
| Skills | β | β | β | β | β |
| Educations | β | β | β | β | β |
| Experiences | β | β | β | β | β |
| Personal Infos | β | β | β | β | β |
| About Me | β | β | β | β | β |
| Contact Messages | β | β | β | β | β |
| Users | β | β | β | β | β |
Each project that connects to a database or external service reads from its own appsettings.json.
DataAPI β Presentation/PersonalPortfolio.DataAPI/appsettings.json:
{
"ConnectionStrings": {
"PostgreSQL": "Host=localhost;Database=portfolio_db;Username=postgres;Password=yourpassword",
"AuthDb": "Host=localhost;Database=portfolio_auth_db;Username=postgres;Password=yourpassword"
},
"Jwt": {
"Issuer": "PersonalPortfolioAPI",
"Audience": "PersonalPortfolioClient",
"SigningKey": "your-secret-signing-key"
}
}AuthAPI β Presentation/PersonalPortfolio.AuthAPI/appsettings.json:
{
"ConnectionStrings": {
"AuthDb": "Host=localhost;Database=portfolio_auth_db;Username=postgres;Password=yourpassword"
},
"Jwt": {
"Issuer": "PersonalPortfolioAPI",
"Audience": "PersonalPortfolioClient",
"SigningKey": "your-secret-signing-key",
"ExpireTimeInMinute": "60"
}
}WebAdmin / WebMvc β configure API base URLs:
{
"APIs": {
"DataApi": "https://localhost:7001/api/",
"AuthApi": "https://localhost:7002/api/",
"FileApi": "https://localhost:7003/"
},
"MVCs": {
"WebAdmin": "https://localhost:7004"
}
}Start all services (each in its own terminal):
# 1. Authentication API
cd Presentation/PersonalPortfolio.AuthAPI && dotnet run
# 2. Data API
cd Presentation/PersonalPortfolio.DataAPI && dotnet run
# 3. File API
cd Presentation/PersonalPortfolio.FileAPI && dotnet run
# 4. Admin Panel
cd Presentation/PersonalPortfolio.WebAdmin && dotnet run
# 5. Public Portfolio Site
cd Presentation/PersonalPortfolio.WebMvc && dotnet run# Portfolio data database
cd Infrastructure/PersonalPortfolio.Persistence
dotnet ef database update --context PortfolioDbContext
# Auth / Identity database
dotnet ef database update --context AuthDbContextThe DataAPI seeds initial data (AboutMe, PersonalInfos) automatically on the first run in development mode.
PersonalPortfolioProject/
βββ Core/
β βββ PersonalPortfolio.Application/ # DTOs, interfaces, validators (FluentValidation)
β βββ PersonalPortfolio.Domain/ # Domain entities (pure C# models)
βββ Infrastructure/
β βββ PersonalPortfolio.Infrastructure/ # Service implementations, JWT handler, Serilog
β βββ PersonalPortfolio.Persistence/ # EF Core, repositories, DB contexts, seeders
βββ Presentation/
βββ PersonalPortfolio.AuthAPI/ # JWT authentication API
βββ PersonalPortfolio.DataAPI/ # Portfolio data CRUD API (Swagger enabled)
βββ PersonalPortfolio.FileAPI/ # File and CV management API
βββ PersonalPortfolio.WebAdmin/ # Admin panel (MVC)
βββ PersonalPortfolio.WebMvc/ # Public portfolio website (MVC)