1

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

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

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

4

1 回答 1

0

在编写响应时,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;
        }
    }
}
于 2013-06-24T15:58:32.650 回答