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
- Customer A visits: “I am Sabin.” → The chef writes it on the whiteboard.
- Customer B visits: “I am Tom.” → The chef writes it on the whiteboard.
- 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;
}
}
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);
}
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();
This single change means:
One service instance lives as long as the server is running.
🚀 4️⃣ Run and Test
- Run the application
- Call
/api/hellomultiple times with different names - 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": "..."
}
]
🧠 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)