. Net Core WebApi custom resource filter (using cache)

Posted by javier on Sun, 05 Dec 2021 17:09:29 +0100

If you want to use caching in WebApi, cache some result sets, which can reduce the pressure on the database server. The cache can be used according to the situation. Generally, it caches the data that is often queried and generally will not be updated.

This article uses MemoryCache to cache data. Of course, there are many caching technologies, such as redis and memcache.

The following is an example to illustrate the usage of MemoryCache

1. Customize the class CustomResourceFilterAttribute, inherit the Attribute, and implement the interface IResourceFilter

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Caching.Memory;
using System;

namespace MyBlog.WebApi.Utility.FilterUtil
{
    /// <summary>
    ///Custom asset filters are used as properties
    /// </summary>
    public class CustomResourceFilterAttribute : Attribute, IResourceFilter
    {
        private IMemoryCache _memoryCache;
        public CustomResourceFilterAttribute(IMemoryCache memoryCache)
        {
            this._memoryCache = memoryCache;
        }

        /// <summary>
        ///This method is called after the action is executed
        /// </summary>
        /// <param name="context"></param>
        public void OnResourceExecuted(ResourceExecutedContext context)
        {
            string path = context.HttpContext.Request.Path;//api/test/GetCacheTest
            string route = context.HttpContext.Request.QueryString.Value;//?name='11'
            string key = path + route;

            //Put the path as the key and the result set as the value into the MemoryCache. The context.Result here refers to the return value of the action
            _memoryCache.Set(key, context.Result);
        }

        /// <summary>
        ///This method is called before the action is executed
        /// </summary>
        /// <param name="context"></param>
        public void OnResourceExecuting(ResourceExecutingContext context)
        {
            string path = context.HttpContext.Request.Path;//api/test/GetCacheTest
            string route = context.HttpContext.Request.QueryString.Value;//?name='11'
            string key = path + route;

            //Check whether the same key value exists in the MemoryCache. If it exists, return data directly from the cache; action is called if it does not exist
            if (_memoryCache.TryGetValue(key, out object value))
            {
                context.Result = value as IActionResult; //When this line is executed, the results in the cache will be returned directly, and neither action nor OnResourceExecuted will be executed
            }
        }


    }
}

Customize a resource filter class and inherit the Attribute class so that this class can be used as a feature in the method; The IResourceFilter interface is implemented to implement the method of resource filter and execute custom logic before and after action execution.

2. Inject MemoryCache in Startup.cs. There is no need to refer to the assembly, because when creating a WebApi project, the framework has introduced relevant methods, which can be called directly.

3. Use cache in the controller's action

        [TypeFilter(typeof(CustomResourceFilterAttribute))]
        [HttpGet("GetCacheTest")]
        public IActionResult GetCacheTest(string strName)
        {
            //Simulate querying data from a database
            return new JsonResult(new
            {
                name = strName,
                age = 18,
                sex = "male"
            });
        }

The following shows the code execution process:

For the first call, the data has not been cached:  

Code execution process:

① First execute the OnResourceExecuting method of the filter, try to read data from the cache according to the key value, and find that there is no data corresponding to the key value in the cache.

② Then execute the action method GetCacheTest in the controller.

③ After the action is executed, after obtaining the data, execute the OnResourceExecuted method of the filter to add the data returned by the action to the cache.

In the second call, the data has been cached. Query the data in the cache:  

Code execution process:

① First, execute the OnResourceExecuting method of the filter, try to read data from the cache according to the key value, find that there is data corresponding to the key value in the cache, and directly return the data in the cache to the caller. Neither the action method of the controller nor the OnResourceExecuted method of the filter is executed.

The cached key is a string composed of path + request parameters. Only when the path and request parameters change at the same time will the database be queried again, new data will be returned, and new data will be added to the cache.

You can also set the expiration time of data in the cache. When the data expires, you can't find it by querying in the cache. At this time, you will call action to query the latest records from the database.

Set expiration time for cached data:

  You can set milliseconds, seconds, minutes, hours and days.

Topics: Cache webapi