Skip to main content

Architecture Overview

The Medical Appointment Management API follows a service-oriented architecture (SOA) pattern with clear separation of concerns. This design promotes maintainability, testability, and scalability.

Architecture Layers

┌─────────────────────────────────────┐
│         HTTP Requests               │
└──────────────┬──────────────────────┘


┌─────────────────────────────────────┐
│         Controllers                 │
│  - CitaController                   │
│  - PacienteController               │
│  - MedicoController                 │
│  - EspecialidadController           │
└──────────────┬──────────────────────┘


┌─────────────────────────────────────┐
│         Service Interfaces          │
│  - ICitaService                     │
│  - IPacienteService                 │
│  - IMedicoService                   │
│  - IEspecialidadService             │
└──────────────┬──────────────────────┘


┌─────────────────────────────────────┐
│      Service Implementations        │
│  - CitaService                      │
│  - PacienteService                  │
│  - MedicoService                    │
│  - EspecialidadService              │
└──────────────┬──────────────────────┘


┌─────────────────────────────────────┐
│        In-Memory Storage            │
│  List<Paciente>                     │
│  List<Medico>                       │
│  List<Especialidad>                 │
│  List<Cita>                         │
└─────────────────────────────────────┘

Layer Responsibilities

Controllers Layer

Purpose: Handle HTTP requests and responses
  • Receive and validate incoming HTTP requests
  • Parse request bodies and route parameters
  • Call appropriate service methods
  • Return properly formatted HTTP responses
  • Handle HTTP status codes (200, 201, 404, 400, etc.)
Controllers are kept thin - they delegate all business logic to services. Location: Controllers/ directory
  • CitaController.cs
  • PacienteController.cs
  • MedicoController.cs
  • EspecialidadController.cs

Service Layer

Purpose: Implement business logic and data operations
  • Perform CRUD operations (Create, Read, Update, Delete)
  • Implement business rules and validation
  • Manage data consistency
  • Handle data transformations between DTOs and entities
  • Generate IDs for new records
Service Interfaces (Services/I*.cs):
public interface IPacienteService
{
    List<Paciente> ObtenerPacientes();
    Paciente AgregarPaciente(CreatePacienteDto paciente);
    Paciente ObtenerPaciente(int id);
    void EliminarPaciente(int id);
    Paciente ActualizarPaciente(int id, CreatePacienteDto paciente);
}
Service Implementations (Services/*Service.cs):
  • PacienteService.cs
  • MedicoService.cs
  • EspecialidadService.cs
  • CitaService.cs
Each service implementation maintains its own in-memory data store.

Models Layer

Purpose: Define data structures Entities (Models/Entities/):
  • Domain models representing core business objects
  • Include all properties and relationships
  • Example: Paciente, Medico, Especialidad, Cita
DTOs (Models/Dtos/):
  • Data Transfer Objects for API communication
  • Separate creation DTOs from response DTOs
  • Example: CreatePacienteDto, CitaDto
Enums (Models/Enums/):
  • Type-safe enumerations
  • Example: CitaEstado (Pendiente, Confirmada, Cancelada, Completada)

Dependency Injection

The API uses ASP.NET Core’s built-in dependency injection container to manage service lifetimes and dependencies.

Service Registration

Services are registered in Program.cs:
Program.cs
using preliminarServicios.Services;
using Scalar.AspNetCore;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddOpenApi();

// Register services as singletons
builder.Services.AddSingleton<IPacienteService, PacienteService>();
builder.Services.AddSingleton<IMedicoService, MedicoService>();
builder.Services.AddSingleton<IEspecialidadService, EspecialidadService>();
builder.Services.AddSingleton<ICitaService, CitaService>();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
    app.MapScalarApiReference(options => 
    {
        options.WithTitle("Mi Super API .NET 10")
               .WithTheme(ScalarTheme.DeepSpace)
               .WithDefaultHttpClient(ScalarTarget.CSharp, ScalarClient.HttpClient);
    });
}

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

Service Lifetimes

Singleton: Services are registered as singletons, meaning:
  • A single instance is created for the application lifetime
  • The same instance is shared across all requests
  • In-memory data persists for the lifetime of the application
In production, you would typically use Scoped services with a database context, creating a new instance per HTTP request.

Request Flow

A typical API request follows this flow:
1

HTTP Request

Client sends an HTTP request to an endpoint like POST /api/Paciente
2

Routing

ASP.NET Core routing directs the request to the appropriate controller action
3

Controller Action

Controller receives the request and validates input data
4

Service Call

Controller calls the appropriate service method via the interface
5

Business Logic

Service implementation executes business logic and data operations
6

Data Storage

Service updates the in-memory data store
7

Response

Service returns data to the controller
8

HTTP Response

Controller formats and returns the HTTP response to the client

Design Patterns

Repository Pattern (Implicit)

While not explicitly implemented as a separate repository layer, the service layer acts as a repository by:
  • Abstracting data access behind service interfaces
  • Encapsulating data storage implementation details
  • Providing a clean API for data operations

DTO Pattern

The API separates:
  • Create DTOs - For incoming data (e.g., CreatePacienteDto)
  • Entity Models - For internal representation (e.g., Paciente)
  • Response DTOs - For API responses (e.g., CitaDto with nested data)
This separation provides:
  • Control over what clients can send vs. receive
  • Validation at the API boundary
  • Flexibility to change internal models without breaking the API

Service Layer Pattern

The service layer provides:
  • Clear separation between HTTP concerns and business logic
  • Testability through interface-based design
  • Reusability of business logic across different controllers
  • Single Responsibility Principle compliance

OpenAPI Integration

The API includes full OpenAPI 3.0 specification support:
builder.Services.AddOpenApi();

if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
    app.MapScalarApiReference(options => 
    {
        options.WithTitle("Mi Super API .NET 10")
               .WithTheme(ScalarTheme.DeepSpace)
               .WithDefaultHttpClient(ScalarTarget.CSharp, ScalarClient.HttpClient);
    });
}
Benefits:
  • Automatic API documentation generation
  • Interactive testing with Scalar UI
  • Type-safe client code generation
  • API contract validation

Current Limitations

In-Memory Storage: The current implementation uses in-memory lists for data storage. This means:
  • Data is lost when the application restarts
  • Not suitable for production use
  • No persistence layer
For production, replace with a database (SQL Server, PostgreSQL, etc.) and Entity Framework Core.
No Authentication: The API currently has no authentication or authorization. All endpoints are publicly accessible.
No Validation: The service layer currently has placeholder implementations that throw NotImplementedException. Full validation and business logic need to be implemented.

Next Steps

Data Models

Explore the entity structures and relationships

Services

Learn about the service layer implementation

Development Guide

Learn how to extend the API

API Reference

Browse all available endpoints

Build docs developers (and LLMs) love