【问题标题】:WebApi Output CacheWebApi 输出缓存
【发布时间】:2013-06-24 14:49:13
【问题描述】:

我正在尝试在 WebApi 中实现一个输出缓存,它可以缓存过滤器已处理的响应并生成格式化程序未处理的响应。

据我所知,ActionFilterAttribute 的 OnActionExecuting 和 OnActionExecuted 在序列化格式化程序之前执行,因此如果您缓存响应,在缓存命中时您将响应完全相同的内容,并且该内容将再次序列化以进行传输。

作为 MVC 中的一种可能解决方案,我认为您可以通过实现 IResultFilter 来做到这一点,该 IResultFilter 通过缓存序列化响应来覆盖 OnResultExecuted。使用这种方法,我不知道如何拦截请求处理以避免序列化格式化程序,我认为拦截的可能解决方案是创建一个自定义 ActionResult 以由 IResultFilter 直接处理。请注意,此解决方案不适合我,因为我正在 WebApi 应用程序中实现 OutputCache。

【问题讨论】:

    标签: asp.net-web-api outputcache


    【解决方案1】:

    在编写响应时,Web API 中的格式化程序仅对 ObjectContent 类型的 HttpContents 起作用。

    在您的 OnActionExecuted 方法中,您可以通过执行以下操作强制序列化发生,然后将响应内容设置为 StreamContent(这样格式化程序就不会出现):

    以下示例:

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        HttpResponseMessage response = actionExecutedContext.Response;
    
        if (response != null && response.IsSuccessStatusCode)
        {
            ObjectContent originalContent = response.Content as ObjectContent;
    
            if (originalContent != null)
            {
                MemoryStream ms = new MemoryStream();
    
                // NOTE:
                // 1. We are forcing serialization to occur into a buffered stream here
                // 2. This can cause exception. You can leave it as it is and Web API's exception handling mechanism should
                //    do the right thing.
                originalContent.CopyToAsync(ms).Wait();
    
                // reset the position
                ms.Position = 0;
    
                StreamContent newContent = new StreamContent(ms);
    
                // Copy the headers
                foreach (KeyValuePair<string, IEnumerable<string>> header in originalContent.Headers)
                {
                    newContent.Headers.TryAddWithoutValidation(header.Key, header.Value);
                }
    
                //dispose the original content
                originalContent.Dispose();
    
                //TODO: cache this new httpcontent 'newContent' (so we are caching both serialized body + headers too)
    
                //Set the response
                //NOTE: This newContent will not hit the formatters
                actionExecutedContext.ActionContext.Response.Content = newContent;
            }
        }
    }
    

    【讨论】:

    • 您好,非常感谢您的回复,但是如果您使用 ReadAsByteArrayAsync 生成 ByteArrayContent 而不是 StreamContent,该怎么办?
    • 是的,即使您将响应设置为 ByteArrayContent,格式化程序也不会参与其中...您能否详细说明 ReadAsByteArrayAsync 的含义?这里讨论的是resposne的编写,所以我不清楚你所说的“使用ReadAsByteArrayAsync”是什么意思?
    • 我的意思是代替使用 CopyToAsync 到内存流,您可以获得已经格式化的响应的字节 [] 并存储它们。当您有缓存命中时,您可以检索缓存的格式化响应字节并创建一个 ByteArrayContent 作为缓存命中响应的内容。使用此策略而不是您的策略是否有任何缺点,我的意思是 WebApi 使用 StreamContent 而不是 ByteArrayContent 有什么优势?再次非常感谢您的帮助
    猜你喜欢
    • 2014-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-18
    相关资源
    最近更新 更多