PharmaVault is structured as a clean N-Tier application split across three .NET 10 projects. Each layer has a single, well-defined responsibility, and dependencies only flow in one direction — from the outer layers inward toward the domain core. This means business rules never depend on infrastructure details, and swapping a data access implementation requires no changes to the Core or Web layers.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/JReyna217/PharmaVault/llms.txt
Use this file to discover all available pages before exploring further.
The Three Layers
PharmaVault.Core
Domain layer. Contains all domain models (
User, Inventory, MedicineCatalog, ErrorLog, SystemResponse), DTOs, and every interface that defines the contracts for data access and services. Has zero external project dependencies — it does not reference Data or Web.Key dependency: BCrypt.Net-Next 4.1.0 for password hashing.PharmaVault.Data
Infrastructure layer. Implements the DAO interfaces from Core using raw ADO.NET with the
Npgsql driver. Houses NpgsqlExtensions for lightweight reflection-based object mapping and all SQL queries. References Core only.Key dependencies: Npgsql 10.0.2, Microsoft.Extensions.Configuration.Abstractions 10.0.5.PharmaVault.Web
Presentation layer. ASP.NET Core Blazor Server application. Hosts Razor components, middleware (
ExceptionHandlingMiddleware), cookie authentication, and service registration in Program.cs. References both Core and Data.Key dependencies: BCrypt.Net-Next 4.1.0, Blazor-ApexCharts 6.1.0.Dependency Direction
The dependency graph is strictly unidirectional:- Core has no references to Data or Web. It is independently compilable and testable.
- Data references Core to implement its interfaces and use domain models as return types.
- Web references both Core (for interfaces and models in Blazor components) and Data (to register concrete implementations in the DI container).
All three projects target net10.0, as declared in each
.csproj file. .NET 10 is required to build and run PharmaVault.Interface-Based Design
All data access operations are expressed as interfaces declared inPharmaVault.Core.Interfaces. The Web layer consumes only these interfaces — never a concrete DAO class — making the data access layer fully replaceable without touching component code.
IUserDao
IUserDao
IMedicineCatalogDao
IMedicineCatalogDao
IInventoryDao
IInventoryDao
IErrorLogDao
IErrorLogDao
IAuthService
IAuthService
Dependency Injection
All services and DAOs are registered with a scoped lifetime inProgram.cs. Scoped means one instance per HTTP request, which is the correct lifetime for database connections in Blazor Server.
Program.cs
Service registration table
| Interface | Implementation | Layer |
|---|---|---|
IUserDao | UserDao | Data |
IMedicineCatalogDao | MedicineCatalogDao | Data |
IInventoryDao | InventoryDao | Data |
IErrorLogDao | ErrorLogDao | Data |
IAuthService | AuthService | Core/Services |
Data Access Pattern
PharmaVault uses a custom ADO.NET approach rather than Entity Framework Core. All queries are written as raw SQL executed throughNpgsqlCommand, and result sets are mapped to domain model objects via the NpgsqlExtensions helper class in PharmaVault.Data.Extensions.
NpgsqlExtensions provides two primary methods:
NpgsqlExtensions.cs
DBNull safely, and performs type coercion for booleans, DateTime, and enums. This gives DAO authors the same convenience as a micro-ORM like Dapper while keeping the full SQL query visible and editable.
The raw-SQL / ADO.NET approach was chosen to keep query logic fully explicit and to avoid the migration overhead that comes with EF Core when working directly against a PostgreSQL schema managed by hand-authored SQL scripts.
Middleware Pipeline
The HTTP middleware pipeline is assembled inProgram.cs in the following order:
Exception handler / HSTS (production only)
In non-Development environments, unhandled exceptions are routed to
/Error and HSTS headers are added.Status code pages
UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true) serves a custom 404 page for all unmatched routes.ExceptionHandlingMiddleware
Custom middleware that catches unhandled exceptions, logs them to the
error_logs table via IErrorLogDao, and returns a structured error response.Authentication and Authorization
Cookie authentication (
PharmaVaultSession) is validated on every request.