You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C# WebAPI控制器方法中获取已缓存的数据

如何在WebAPI控制器中获取已缓存的数据

基于你已经实现的OutputCacheFilter,要在控制器方法中获取缓存数据,核心是复用Filter中一致的缓存键生成逻辑,并直接访问缓存容器。下面是具体的实现步骤:

1. 重构缓存键生成逻辑(避免重复代码)

首先把Filter中生成缓存键的逻辑抽成公共静态方法,这样控制器和Filter可以共用,保证键的一致性。修改你的OutputCacheFilter类:

public class OutputCacheFilter : ActionFilterAttribute 
{ 
    // 把原来的private静态缓存改成public,或者添加公共访问方法
    public static readonly ObjectCache WebApiCache = MemoryCache.Default;

    // 其他原有字段和构造函数...

    // 添加公共静态方法生成缓存键
    public static string GenerateCacheKey(HttpRequestMessage request, bool dependsOnIdentity = true)
    {
        // 处理Accept头为空的情况,避免NullReferenceException
        var acceptHeader = request.Headers.Accept.FirstOrDefault()?.ToString() ?? string.Empty;
        var baseKey = string.Join(":", request.RequestUri.OriginalString, acceptHeader);

        // 如果启用用户身份依赖,拼接用户标识(根据你的原有逻辑补充)
        if (dependsOnIdentity)
        {
            // var user = new SecurityHelper().GetUser(); // 取消注释并使用你的用户获取逻辑
            // return $"{user}:{baseKey}";
            return baseKey; // 暂时保留,根据实际需求调整
        }

        return baseKey;
    }

    // 其他原有方法...
}

2. 在控制器中获取缓存数据

以你的MessageController为例,假设要在GetMessage方法中复用GetMessages的缓存结果,可以这样实现:

public class MessageController : ApiController 
{ 
    [OutputCacheFilter()] 
    public IHttpActionResult GetMessages() 
    { 
        // 原有逻辑...
    } 

    public IHttpActionResult GetMessage(string messageCode) 
    { 
        if(string.IsNullOrEmpty(messageCode)) 
        { 
            return BadRequest("Please pass the messageCode in order to get the message."); 
        } 

        // 步骤1:生成和Filter一致的缓存键
        var cacheKey = OutputCacheFilter.GenerateCacheKey(Request);
        // 步骤2:检查缓存是否存在
        if(OutputCacheFilter.WebApiCache.Contains(cacheKey))
        {
            // 步骤3:获取缓存的内容和ContentType
            var cachedContent = OutputCacheFilter.WebApiCache.Get(cacheKey) as string;
            var contentType = OutputCacheFilter.WebApiCache.Get(cacheKey + ":response-ct") as MediaTypeHeaderValue;

            if(cachedContent != null)
            {
                // 步骤4:反序列化缓存的JSON字符串为DTO对象
                var cachedMessages = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Message>>(cachedContent);
                var targetMsg = cachedMessages.FirstOrDefault(o => 
                    o.Code.Equals(messageCode, StringComparison.InvariantCultureIgnoreCase));
                
                if(targetMsg != null)
                {
                    return Ok(targetMsg);
                }
            }
        }

        // 如果缓存未命中,走原有数据库查询逻辑
        MesssageManager msgManager = null;
        try 
        { 
            msgManager = new MesssageManager(); 
            List<Message> messages = msgManager.GetMessages(); 
            var msg = messages.FirstOrDefault(o => 
                o.Code.Equals(messageCode, StringComparison.InvariantCultureIgnoreCase)); 
            return Ok(msg); 
        } 
        catch (Exception ex) 
        { 
            return InternalServerError(ex); 
        } 
        finally 
        { 
            msgManager = null; 
        } 
    } 
}

关键注意事项

  • 依赖用户身份的缓存:如果你的OutputCacheFilter启用了_dependsOnIdentity,一定要在生成缓存键时拼接用户标识,否则会获取到其他用户的缓存数据。
  • 反序列化处理:因为Filter中缓存的是响应的字符串内容(通常是JSON),所以需要用JSON序列化库(比如Newtonsoft.Json)反序列化为对应的DTO类型。
  • 空值处理:要处理Accept头为空、缓存内容为空的情况,避免抛出空引用异常。
  • 代码小修正:你的DTO类Message最后一行publi是拼写错误,应该改为public;MesssageManager多了一个s,建议统一修正。

内容的提问来源于stack exchange,提问作者Neeraj Kumar Gupta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:22:13