ASP.NET MVC 3 Пользовательский RouteBase и OutputCache
У меня есть проблема с моей пользовательской реализацией RouteBase
и [OutputCache]
.
У нас есть CMS, в которой URL-адреса отображаются на определенные страницы контента. Каждый тип страницы контента обрабатывается другим контроллером (и разными видами). URL-адреса абсолютно бесплатны, и нам нужны разные контроллеры, поэтому "полный" маршрут не используется. Поэтому мы создаем пользовательскую реализацию RouteBase, которая вызывает базу данных для поиска всех URL-адресов. База данных знает, какой контроллер и действие использовать (на основе типа страницы содержимого).
Это отлично работает.
Однако, комбинируя это с атрибутом [OutputCache], выходное кэширование не работает (страница все еще работает). Мы убедились, что [OutputCache] работает на наших "обычных" маршрутах.
Очень сложно отлаживать выходное кэширование, атрибут есть у нас, он не работает... Идеи, как подойти к этому, были бы очень желанными, как и правильный ответ!
Контроллер выглядит следующим образом:
public class TextPageController : BaseController
{
private readonly ITextPageController textPageController;
public TextPageController(ITextPageController textPageController)
{
this.textPageController = textPageController;
}
[OutputCache(Duration = 300)]
public ActionResult TextPage(string pageid)
{
var model = textPageController.GetPage(pageid);
return View(model);
}
}
Пользовательский маршрут выглядит следующим образом:
public class CmsPageRoute : RouteBase
{
private IRouteService _routeService;
private Dictionary<string, RouteData> _urlsToRouteData;
public CmsPageRoute(IRouteService routeService)
{
this._routeService = routeService;
this.SetCmsRoutes();
}
public void SetCmsRoutes()
{
var urlsToRouteData = new Dictionary<string, RouteData>();
foreach (var route in this._routeService.GetRoutes()) // gets RouteData for CMS pages from database
{
urlsToRouteData.Add(route.Url, PrepareRouteData(route));
}
Interlocked.Exchange(ref _urlsToRouteData, urlsToRouteData);
}
public override RouteData GetRouteData(System.Web.HttpContextBase httpContext)
{
RouteData routeData;
if (_urlsToRouteData.TryGetValue(httpContext.Request.Path, out routeData))
return routeData;
else
return null;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
return null;
}
private RouteData PrepareRouteData(ContentRouteData contentRoute)
{
var routeData = new RouteData(this, new MvcRouteHandler());
routeData.Values.Add("controller", contentRoute.Controller);
routeData.Values.Add("action", contentRoute.Action);
routeData.Values.Add("area", contentRoute.Area);
routeData.Values.Add("pageid", contentRoute.Constraints["pageid"]); // variable for identifying page id in controller method
routeData.DataTokens.Add("Namespaces", new[] { contentRoute.Namespace });
routeData.DataTokens.Add("area", contentRoute.Area);
return routeData;
}
// routes get periodically updated
public void UpdateRoutes()
{
SetCmsRoutes();
}
}
Спасибо за чтение до конца!
Ответы
Ответ 1
В итоге мы отследили его до вызова
... data-role="@this.FirstVisit" ...
в нашем _Layout.cshtml
Это называется свойством на нашей странице пользовательского представления, которое, в свою очередь, называется службой, которая всегда устанавливает cookie. ( Yikes устанавливает файлы cookie в сервисах!, мы знаем!)
Если бы не пятница, а в конце спринта мы могли заметить, что перехват кеша
Cache-Control: no-cache="Set-Cookie":
Заголовок Http.
Я до сих пор не понимаю, почему это только разоряло кеш для нашей пользовательской RouteBase
реализации, а не всех страниц. Все страницы используют те же _Layout.cshtml
.
Ответ 2
Вы можете попробовать следующий код, если он помогает
[OutputCache(Duration = 300, VaryByParam="*")]
public ActionResult TextPage(string pageid)
{
var model = textPageController.GetPage(pageid);
return View(model);
}
Ответ 3
Вы можете посмотреть здесь, чтобы настроить кеширование:
Кроме того, проверьте расположение кэша.