ASP.NET Core 的 ResponseCache 觸發伺服器端快取的條件尤為嚴格,限制很多
為了節省伺服器的運算成本,所以可以實作一個ResultFilter來快取頁面
這邊是採用本機MemoryCache,當然也可以改用Redis或者其他Cache Server
首先在Startup.cs加入services.AddMemoryCache();
public void ConfigureServices(IServiceCollection services) { services.AddMemoryCache(); services.AddControllers(); }
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Caching.Memory; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace WebApplication2 { public class CacheResultFilter : ResultFilterAttribute { private readonly int _expiration; public CacheResultFilter(int expirationMs) { _expiration = expirationMs; } public override void OnResultExecuting(ResultExecutingContext context) { var controller = context.RouteData.Values["Controller"].ToString(); var action = context.RouteData.Values["Action"].ToString(); var method = context.HttpContext.Request.Method; var queryStrings = new List<string>(); if (context.HttpContext.Request.Query.Count > 0) { context.HttpContext.Request.Query.ToList() .ForEach(kv => { queryStrings.Add(kv.Key); queryStrings.Add(kv.Value); }); } var key = generateCacheKey(action, method, queryStrings.ToArray()); var cache = context.HttpContext.RequestServices.GetService(typeof(IMemoryCache)); if (cache == null) { base.OnResultExecuting(context); return; } var cacheValue = (cache as IMemoryCache)?.Get(key); if (cacheValue != null) { context.Result = new ObjectResult(JsonConvert.DeserializeObject(cacheValue.ToString())); } else { var objResult = context.Result as ObjectResult; var json = JsonConvert.SerializeObject(objResult.Value); (cache as IMemoryCache)?.Set(key, json, TimeSpan.FromMilliseconds(_expiration)); } base.OnResultExecuting(context); } private string generateCacheKey(string action,string method,string[] queryStrings) { var key = string.Format("{0}_{1}_{2}", action, method, string.Join("_", queryStrings)); return key; } } }
這邊Get掛上了CacheResultFilter設定快取5秒using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace WebApplication2.Controllers { [ApiController] [Route("[controller]")] public class ExampleController : ControllerBase { [HttpGet] [CacheResultFilter(5000)] public DateTime Get() { return DateTime.Now; } } }