Output Caching Middleware

ABP.IO
abp-community
Published in
3 min readDec 30, 2022

Output caching is a new middleware component included with .NET 7. Instead of calling each request, it saves HTTP responses. In this post, we will show its capabilities, how to use it with an ABP-based solution, and compare it to its alternatives.

Let`s create an ABP app(default) solution template and show its implementation

abp new OutputCachingMiddleware -t app

Let`s start by configuring caching on the module file.

public class OutputCachingMiddlewareWebModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
//The other configurations
context.Services.AddOutputCache();
//The other configurations
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
//The other configurations
app.UseOutputCache();
//The other configurations
}
}

Note: Please kNote: Please keep in mind that UseOutputCache must be called after UseCors and UseRouting but before UseEndpoints.

Now, we can create a controller under the OutputCachingMiddleware.HttpApi named OutputCachingContoller

r

[Route("api/[controller]")]
public class OutputCachingContoller : OutputCachingMiddlewareController
{
[OutputCache(Duration = 10)]
[HttpGet("default")]
public async Task<string> Default()
{
await Task.Delay(1000);
return DateTime.UtcNow.ToString();
}
}

Note: After .NET 6, you can see the above code in minimal API but it`s used as the above for apps with controllers.

Specify the cache key

You can store by default as described above, but you can also store based on sending parameters. This feature is available as an attribute with VaryByQueryKeys. There are also VaryByHeaderNames and VaryByRouteValueNames for various purposes.

Let`s continue under the same controller and create a new action to demonstrate it.

.

[OutputCache(Duration = 30, VaryByQueryKeys = new[] { "letter" })]
[HttpGet("changecolon")]
public async Task<string> ChangeColon(string letter)
{
await Task.Delay(1000);
return DateTime.UtcNow.ToString().Replace(":", letter);
}

Disable cache

To disable caching, you can remove the attribute on the action, however, if you use [OutputCache] for the whole controller, you must use the way below.

Let`s see the code

[OutputCache] //enables the whole controller
public class OutputCachingContoller : OutputCachingMiddlewareController
{
[OutputCache(NoStore = true)]//only disable this action
[HttpGet("nostore")]
public async Task<string> NoStore()
{
await Task.Delay(1000);
return DateTime.UtcNow.ToString();
}
}

Some default policies

  • HTTP 200 responses (the successful responses) are cached and the others aren`t.
  • HTTP GET or HEAD requests are cached and the other HTTP methods aren`t.
  • Responses that set cookies aren`t cached.
  • Responses to authenticated requests aren`t cached.

Even so, you can override the following policies.

public override void ConfigureServices(ServiceConfigurationContext context)
{
builder.Services.AddOutputCache(options =>
{
options.AddBasePolicy(builder => builder.Cache());
});

context.Services.AddOutputCache(); // or you can make default
}

The Differences with response caching

It differs from response caching with the following features

  • The output cache behaviour is configurable on the server, the response cache uses the browser’s cache.
  • The output cache entries can be programmatically invalidated, the response cache doesn`t support that.
  • The output cache gets just the successful responses but the response cache stores even if the response is bad.
  • The output cache storage medium is extensible.

Source Code

  • You can find the full source code of the example application here.

See Also

--

--

ABP.IO
abp-community

Open Source ABP Framework is a complete infrastructure to create modern web applications by following the best practices & conventions of software development.