Implementing in-memory Caching in .NET 6 Web API

Pasindu Prabhashitha
4 min readSep 2, 2023
Implementing in-memory Caching in .NET 6 Web API

If you have a dataset that infrequently changes and is also expensive to retrieve from the database you definitely have to consider implementing a caching mechanism to that to increase the performance of your application. Though in memory caching we can store these types of datasets temporarily in the server’s memory. In this article, I’m going to show you how we can implement in-memory caching in a .NET 6 WebAPI.

In order to get started, Create a new web API project using Visual Studio. In this article, I’m going to create a vehicle Api endpoint that returns a list of vehicles.

After you create the new project create a folder called models in the root of the project folder. Inside that create a new file called Vehicle.cs and add the following vehicle model.

namespace CachingInmemory.Models
{
public class Vehicle
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
}
}

After that create a new service class to retrieve vehicles. But before creating the service class create a new interface called IVehicleService.

using CachingInmemory.Models;

namespace CachingInmemory.Services
{
public interface IVehicleService
{
public List<Vehicle> GetVehicles();
}
}

After that create a new service class called VehicleService to implement this interface. After that, we should inject the IMemoryCache interface on that class in order to work with the memory cache. In addition to that create a variable called cache key which will be used to identify the items in the memory.

using CachingInmemory.Models;
using Microsoft.Extensions.Caching.Memory;

namespace CachingInmemory.Services
{
public class VehicleService : IVehicleService
{
private readonly IMemoryCache _memoryCache;
public string cacheKey = "vehicles";

public VehicleService(IMemoryCache memoryCache)
{
_memoryCache = memoryCache;
}

public List<Vehicle> GetVehicles()
{
throw new NotImplementedException();
}
}
}

After that, we should implement the GetVehicle method. On the below code snippet you can see the implemented code.

using CachingInmemory.Models;
using Microsoft.Extensions.Caching.Memory;

namespace CachingInmemory.Services
{
public class VehicleService : IVehicleService
{
private readonly IMemoryCache _memoryCache;
public string cacheKey = "vehicles";

public VehicleService(IMemoryCache memoryCache)
{
_memoryCache = memoryCache;
}

public List<Vehicle> GetVehicles()
{
List<Vehicle> vehicles;

if(!_memoryCache.TryGetValue(cacheKey, out vehicles))
{
vehicles = GetValuesFromDbAsync().Result;

_memoryCache.Set(cacheKey, vehicles,
new MemoryCacheEntryOptions()
.SetAbsoluteExpiration(TimeSpan.FromSeconds(5)));
}
return vehicles;
}

private Task<List<Vehicle>> GetValuesFromDbAsync ()
{

List<Vehicle> vehicles = new List<Vehicle>
{
new Vehicle { Id = 1, Name = "Car" },
new Vehicle { Id = 2, Name = "Truck" },
new Vehicle { Id = 3, Name = "Motorcycle" }
};

Task<List<Vehicle>> VehiclesTask = Task<List<Vehicle>>.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return vehicles;
});

return VehiclesTask;

}
}
}

The GetVehicles method retrieves a list of vehicles either from a cache or, if not present, fetches them from a database and stores them in the cache for 5 seconds.

The GetValuesFromDbAsync method mimics the database access by creating a task and inside that task returning the vehicle list after waiting 5 seconds (Since a database call takes some time to complete).

Finally, you should register the service class interface inside the Program.cs file.

builder.Services.AddScoped<IVehicleService, VehicleService>();
builder.Services.AddMemoryCache();

In addition to registering the IVehicleService interface, you should add the AddMemoryCachemethod to Program.cs file to register the IMemoryCache interface for dependency injection.

After that inside the controllers folder create a controller called VehicleController and add the following code to it.

using CachingInmemory.Models;
using CachingInmemory.Services;
using Microsoft.AspNetCore.Mvc;

namespace CachingInmemory.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class VehicleController : ControllerBase
{
private readonly IVehicleService _vehicleService;
public VehicleController(IVehicleService vehicleService)
{
_vehicleService = vehicleService;
}

[HttpGet]
public ActionResult<List<Vehicle>> GetVehicles()
{
return _vehicleService.GetVehicles();
}
}
}

As you can see this controller has a get endpoint which talks to the vehicle service and returns the list of vehicles as the response. That’s it for the implementation. Super simple :)

Now when you run your project and if you test this with an API tester like Postman, the first time you hit that endpoint you will see it takes 5 seconds to get the response.

Caching Initial Response.

But once you hit the endpoint a second time you will see that it will respond within 2 milliseconds and on that round instead of getting the data from GetValuesFromDbAsync method it has taken it from the cache.

Caching SecondResponse.

So that’s it. You are done! Thanks for reading the article. If you need the source code, click on the following link to view the full source in GitHub.

https://learn.microsoft.com/en-us/aspnet/core/performance/caching/memory?view=aspnetcore-7.0

--

--