Кэширование не работает правильно на моем сайте ASP.NET MVC?
Я пытаюсь использовать OutputCaching на моем веб-сайте ASP.NET MVC. Проблема в том, что когда я пытаюсь изменить значение одного из моих параметров строки запроса, он возвращает данные для первого запрошенного элемента!
Вот мой код (с измененными именами параметров) ...
[ApiAuthorize]
[HandleErrorAsJson]
public class SearchController : Controller
{
[AcceptVerbs(HttpVerbs.Get)]
[OutputCache(Duration = 60, VaryByParam = "*")]
public ActionResult ScoreCard(string foo, byte? bar, byte? pewpew)
{
..
}
}
- ПРИМЕЧАНИЕ 1. ApiAuthorize - пользовательский атрибут, который проверяет параметр строки запроса под названием "Ключ" и проверяет словарь в памяти, чтобы увидеть, существует ли он.
- ПРИМЕЧАНИЕ 2: HandleErrorAsJson - пользовательский атрибут, который возвращает сообщение об ошибке как json, если было / выброшено исключение.
и вот два примера звонков, которые я делаю для этого действия: -
- / GET http://api.mysite.com/search/scorecard?foo=hello+world,+PewPew&key=abcd1234&bar=2
- / GET http://api.mysite.com/search/scorecard?foo=invalid+search+stuff&key=abcd1234&bar=2
поэтому данные из первого вызова (foo = hello world, Pew Pew) возвращаются как 200 OK. Затем второй вызов API возвращает 200 OK, но с данными из предыдущего вызова.
Кроме того, я не использую прокси-сервер. Если я закомментирую атрибут OutputCache, все будет хорошо.
Я также попробовал следующее (вручную перечисляя каждый раз, когда мне нужно кешировать) .....
[OutputCache(Duration = 60, VaryByParam = "foo,key,bar,pewpew")]
Неудачно:(
Обратите внимание, как мне нужно убедиться, что я включил параметр API "Ключ" как часть уникального ключа кэша. Я не хочу, чтобы люди искали одну и ту же вещь, но если у второго человека нет правильного ключа, он должен получить не кешированный результат, а сообщение об ошибке (технически это 401 не авторизован, но в любом случае) ...
Мысли?
2 ответа
Список параметров в VaryByParam должен быть разделен точкой с запятой, а не запятой. Дайте это попробовать. Тем не менее, * должен был работать.
Я использую фильтр для кэширования вывода, который дает программный контроль для отладки, а также устанавливает, когда это необходимо. Не стесняйтесь использовать это и посмотрите, будет ли настройка здесь иметь значение, которое, я думаю, могло бы быть (также убедитесь, что любое предыдущее кэширование очищено)
public class CacheFilterAttribute : ActionFilterAttribute
{
private const int Second = 1;
private const int Minute = 60 * Second;
private const int Hour = 60 * Minute;
public const int SecondsInDay = Hour * 24;
/// <summary>
/// Gets or sets the cache duration in seconds. The default is 10 seconds.
/// </summary>
/// <value>The cache duration in seconds.</value>
public int Duration
{
get;
set;
}
public int DurationInDays
{
get { return Duration / SecondsInDay; }
set { Duration = value * SecondsInDay; }
}
public CacheFilterAttribute()
{
Duration = 10;
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (Duration <= 0) return;
HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
TimeSpan cacheDuration = TimeSpan.FromSeconds(Duration);
cache.SetCacheability(HttpCacheability.Public);
cache.SetExpires(DateTime.Now.Add(cacheDuration));
cache.SetMaxAge(cacheDuration);
cache.AppendCacheExtension("must-revalidate, proxy-revalidate");
}
}
Пока я просто использую это для очень статичной части сайта, так что позвоните вот так
[CacheFilter(DurationInDays = 1)]
Очевидно, что вы просто хотели бы расширить это, чтобы VaryByParams отображался как свойство, но могло показаться, что вы знаете, что делать.