EasyCaching in a ASP.NET Core Minimal API project
Tags: api, programming, minimalapi, cache
Published: 2022-08-12 07:43:27

When developing an API, it is very common to need a cache to improve performance and to load the server less.
ASP.NET Core has his own library to manage the cache out-of-the-box but in a real scenario, you need to write some code to have a clean solution.

EasyCaching is an open-source caching library that contains basic usages and some advanced usages of caching which can help us to handle caching more easily.

Let's see how we can use EasyCaching in a Minimal API project.

## Install the packages
The main package of EasyCaching is called EasyCaching.Core and contains the basic logic of caching.
It's not very common to use this package without any other packages from EasyCaching.
The reason is very simple: you need a provider where EasyCaching stores all the data.
There are a lot of caching providers developed directly by EasyCaching team:
- InMemory
- Redis
- SQLite
- LiteDB
and much more.

Choose your caching provider and install it via NuGet:

```
Install-Package EasyCaching.InMemory
Install-Package EasyCaching.Redis
Install-Package EasyCaching.SQLite
```
All the dependencies are installed with the caching provider package.

## Configure the project
Now we are ready to add EasyCaching in our ASP.NET Core Minimal API project.
Open the "Program.cs" file and add the service to the IServiceCollection at the beginning of the class.

```csharp
builder.Services.AddEasyCaching(options =>
{
    options.UseInMemory("inMemoryCache");
});
```
This is the simplest way to use the In Memory cache and it uses the default configuration.
You can also set a lot of parameters during this phase.

```csharp
builder.Services.AddEasyCaching(options =>
{
    // use memory cache with your own configuration
    options.UseInMemory(config =>
    {
        config.DBConfig = new InMemoryCachingOptions
        {
            // scan time, default value is 60s
            ExpirationScanFrequency = 60,
            // total count of cache items, default value is 10000
            SizeLimit = 100,

            // below two settings are added in v0.8.0
            // enable deep clone when reading object from cache or not, default value is true.
            EnableReadDeepClone = true,
            // enable deep clone when writing object to cache or not, default valuee is false.
            EnableWriteDeepClone = false,
        };
        // the max random second will be added to cache's expiration, default value is 120
        config.MaxRdSecond = 120;
        // whether enable logging, default is false
        config.EnableLogging = false;
        // mutex key's alive time(ms), default is 5000
        config.LockMs = 5000;
        // when mutex key alive, it will sleep some time, default is 300
        config.SleepMs = 300;
    }, "inMemoryCache");
});
```
You can read the official documentation to understand better all the parameters for the In Memory provider: https://easycaching.readthedocs.io/en/latest/In-Memory/

## Change the code to use EasyCaching
We can use the default WeatherForecast Get endpoint to understand how easy it is to use EasyCaching.
First of all, we can use the dependency injection engine to retrieve the instances of the providers (yes, you can configure more than one in the startup).
Then, we can check if a value is stored in the EasyCaching provider and in that case, we can return directly the cached value from the endpoint.
In the other case, we load the values of the weather, store them in the cache for the next call to the API.
It's easier if you see the code directly:

```csharp
app.MapGet("/weatherforecast", async (IEasyCachingProvider _provider) => 
{
    if (await _provider.ExistsAsync("forecast"))
    {
        var cachedForecast = await _provider.GetAsync<WeatherForecast[]>("forecast");
        return cachedForecast.Value;
    }

    var forecast = Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        (
            DateTime.Now.AddDays(index),
            Random.Shared.Next(-20, 55),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();

    await _provider.SetAsync("forecast", forecast, TimeSpan.FromMinutes(60));

    return forecast;
})
.WithName("GetWeatherForecast");
```

## Pro Tip
You can store all the settings directly in the appsettings.json file in a very easy way.

You can change the setup of the provider like in the code below.
```csharp
options.UseInMemory(Configuration, "default", "easycaching:inmemory");
```
Then, you can add this json section in the appsettings.json file.

```json
"easycaching": {
    "inmemory": {
        "MaxRdSecond": 120,
        "EnableLogging": false,
        "LockMs": 5000,
        "SleepMs": 300,
        "DBConfig":{
            "SizeLimit": 10000,
            "ExpirationScanFrequency": 60,
            "EnableReadDeepClone": true,
            "EnableWriteDeepClone": false
        }
    }
}
```
You can use the same approach for the other providers, not only for the In Memory one.
Here you can find the example for Redis: https://easycaching.readthedocs.io/en/latest/Redis/