DEV Community

Sabin Sim
Sabin Sim

Posted on • Edited on

C#.NET - day 03

Day 03: In-Memory Data — Teaching the Service to Remember

Understanding state, lifetime, and responsibility in ASP.NET Core

Introduction

Up to this point, the program we built behaved like a very forgetful chef. If a customer said “Sabin,” the chef created a business card — but immediately forgot about it. When the next customer arrived, there was no memory of who had come before.

In this step, we introduce a simple but important idea: memory. Before using a real database, we simulate persistence by storing data in memory (RAM). Think of it as hanging a whiteboard on the kitchen wall.


🌊 Flow: What We Are Building

  1. Customer A visits: “I am Sabin.” → The chef writes it on the whiteboard.
  2. Customer B visits: “I am Tom.” → The chef writes it on the whiteboard.
  3. History request: “Who has visited?” → The chef shows the entire whiteboard.

1️⃣ Step 1: Hanging a Guestbook in the Kitchen (Service)

We start by modifying the service so it can remember past results. The service will now hold a list in memory.

Open Services/HelloService.cs and replace the contents.

using HelloFlow.Models;

namespace HelloFlow.Services;

public class HelloService
{
    // The guestbook: an in-memory list shared by the service
    private readonly List<HelloResponse> _history = new();

    public HelloResponse GetHello(string name)
    {
        var response = new HelloResponse
        {
            Message = $"Hello, {name}! Welcome to C#.",
            CreatedAt = DateTime.Now,
            Location = "Cazis, Switzerland"
        };

        // Record the visit before returning the response
        _history.Add(response);

        return response;
    }

    // Return all recorded entries
    public List<HelloResponse> GetHistory()
    {
        return _history;
    }
}
Enter fullscreen mode Exit fullscreen mode

At this point, the service has gained a new responsibility:

  • It creates responses
  • It remembers past responses

2️⃣ Step 2: Adding a History Counter (Controller)

Next, we add a new endpoint so clients can ask: “Who has visited so far?”

Open Controllers/HelloController.cs and add the following method below the existing SayHello method.

[HttpGet("history")]
public IActionResult GetHistory()
{
    var history = _service.GetHistory();
    return Ok(history);
}
Enter fullscreen mode Exit fullscreen mode

Now the controller has two endpoints:

  • GET /api/hello → create a new entry
  • GET /api/hello/history → return all stored entries

🚨 3️⃣ Step 3: Keeping the Chef on Duty (Program.cs)

This step is the core of Step 1.5.

If the service is registered as AddScoped, a new chef is hired and fired for every request. That means the guestbook is reset every time — no memory is kept.

To preserve memory, the chef must stay for the entire lifetime of the application.

Open Program.cs and change the service registration:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

// Change lifetime: Scoped → Singleton
builder.Services.AddSingleton<HelloFlow.Services.HelloService>();

var app = builder.Build();
Enter fullscreen mode Exit fullscreen mode

This single change means:

One service instance lives as long as the server is running.


🚀 4️⃣ Run and Test

  1. Run the application
  2. Call /api/hello multiple times with different names
  3. Then call /api/hello/history

If everything works, you should see a JSON array like this:

[
  {
    "message": "Hello, Sabin! ...",
    "createdAt": "...",
    "location": "..."
  },
  {
    "message": "Hello, Tom! ...",
    "createdAt": "...",
    "location": "..."
  },
  {
    "message": "Hello, Jane! ...",
    "createdAt": "...",
    "location": "..."
  }
]
Enter fullscreen mode Exit fullscreen mode

🧠 Key Clarification: Service vs Controller

At this stage, one subtle misunderstanding can easily appear — and it is important to clear it up.

✔ What Is Correct

The service is a single instance. It does not “clock out.” It keeps memory as long as the application is running.

❌ A Common Misunderstanding

It may feel like there are two controllers: one for creating cards and one for showing history.

This is not the case.

⭕ The Correct Model

There is:

  • One controller (HelloController)
  • Two endpoints (two counters at the same desk)

Both endpoints belong to the same context: Hello.


🧩 The Mental Model

In one sentence:

The service is one person with memory. The controller is one person with multiple counters.

This distinction becomes crucial later when the system grows and responsibilities are split further.


✍️ My Notes & Reflections

  • By allowing the service to keep memory, I was able to give the controller two different counters: one for creating a business card, and another for showing the guestbook.

Top comments (0)