{ZB}Ziyad Alboghdady

Case study

University Management System

One domain served two ways — Razor views for staff and a REST endpoint for other systems — without duplicating the data layer.

StackASP.NET Core MVC · Web API · EF Core · PostgreSQL · ASP.NET Identity · Repository pattern · DTOs
RoleSole engineer
When2026
SourceGitHub repository

The problem

The same university data (students, teachers, courses, rooms) needed a UI for staff and a JSON API for other systems. The naive answer is two codebases that drift apart within a month. The real question was how much could be shared before the sharing itself became the problem.

What I did & decided

  • Shared one repository layer between the MVC controllers and the API controller, so a query is written once and both surfaces use it.
  • Kept the shapes separate: ViewModels for Razor, DTOs for the API. Sharing data access is cheap; sharing the response shape is how an API ends up leaking form state.
  • Added pagination to the students API (?pageNumber=1&pageSize=5) with safe defaults for bad input.
  • Used ASP.NET Identity with roles: Admins and Managers can create and edit; only Admins can delete a student.
  • Stored student photos on disk under wwwroot/StudentPictures rather than as binaries in the database.

What came of it

  • Adding a field means one entity, one repository method and two small shape changes — not two features.
  • The API is usable by something that is not my own UI, which is the real test of whether it is an API.
  • What I would fix next: the repository still loads every student before the API pages the list. Paging inside the query (IQueryable with Skip/Take translated to SQL) would keep the endpoint fast as the table grows.

Next case: Live Data Visualisation with R on the JVM