2013-06-24 2 views
1

Я пытаюсь реализовать выходной кэш в WebApi, который может кэшировать ответы, уже обработанные фильтрами, и генерировать ответы, которые не обрабатываются formatters.WebApi Output Cache

Из того, что я видел, OnActionExecuting и OnActionExecuted ActionFilterAttribute выполняются перед формированием поля сериализации, поэтому, если вы кешируете ответ, при ударе кеша вы ответите на тот же самый контент и этот контент будет снова сериализован для передачи.

Как возможное решение в MVC, я думаю, что вы можете сделать это, реализовав IResultFilter, который переопределяет OnResultExecuted путем кэширования сериализованного ответа. При таком подходе я не знаю, как перехватить обработку запроса, чтобы избежать форматирования сериализации, я думаю, что возможным решением для перехвата является создание настраиваемого ActionResult, обрабатываемого непосредственно IResultFilter. Обратите внимание, что это решение не подходит для меня, потому что я реализую OutputCache в приложении WebApi.

ответ

0

При написании ответа, форматировщики в Web API вступают в действие только для HttpContents типа ObjectContent.

В вас 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; 
     } 
    } 
} 
+0

Здравствуйте, я очень благодарен за ваш ответ, но что, если вы создали ByteArrayContent вместо StreamContent, используя ReadAsByteArrayAsync? – IgrCndd

+0

Да, даже если вы зададите ответ как ByteArrayContent, форматирующие элементы не будут задействованы ... Можете ли вы подробнее рассказать о том, что вы подразумеваете под ReadAsByteArrayAsync? Здесь речь шла о написании resposne, поэтому я не понимаю, что вы подразумеваете под «использованием ReadAsByteArrayAsync»? –

+0

Что я имею в виду, вместо того, чтобы использовать CopyToAsync в потоке памяти, вы можете получить байт [] вашего ответа, уже отформатированный и сохраняющий их. Когда у вас есть кэш, вы можете получить свои кэшированные отформатированные байты ответа и создать ByteArrayContent, чтобы быть содержимым вашего ответа на ответ в кеш. Есть ли недостаток в использовании этой стратегии вместо вашей, я имею в виду, что WebApi имеет какое-либо преимущество с помощью StreamContent вместо ByteArrayContent? Снова очень благодарен за вашу помощь – IgrCndd