我正在尝试在WebApi中实现一个输出缓存,它可以缓存已经过滤器处理的响应并生成格式化程序未处理的响应。
从我所见,ActionFilterAttribute的OnActionExecuting和OnActionExecuted在序列化格式化程序之前执行,因此如果缓存响应,则在缓存命中时,您将响应完全相同的内容,并且该内容将再次序列化为传输。
作为MVC中可能的解决方案,我认为您可以通过实现IResultFilter来实现这一点,该IResultFilter通过缓存序列化响应来覆盖OnResultExecuted。使用这种方法我不知道如何拦截请求处理以避免序列化格式化程序,我认为拦截的可能解决方案是创建一个自定义ActionResult,由IResultFilter直接处理。请注意,此解决方案不适合我,因为我正在WebApi应用程序中实现OutputCache。
答案 0 :(得分: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;
}
}
}