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);
}