Reputation: 3220
I have a problem with my custom RouteBase
implementation and [OutputCache]
.
We have a CMS in which urls are mapped to certain content pages. Each type of content page is handled by a different controller (and different views). The urls are completely free and we want different controllers, so a "catchall" route is not usable. So we build a custom RouteBase implementation that calls the database to find all the urls. The database knows which Controller and Action to use (based on the content page type).
This works just great.
However, combining this with the [OutputCache] attribute, output caching doesn't work (the page still works). We made sure [OutputCache] works on our "normal" routes.
It is very difficult to debug outputcaching, the attribute is there we us it, it doesn't work... Ideas how to approach this would be very welcome, as would the right answer!
The controller looks like this:
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);
}
}
The custom route looks like this:
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();
}
}
Thank you for reading until the end!
Upvotes: 10
Views: 2494
Reputation: 13536
In the end we tracked it down to a call to
... data-role="@this.FirstVisit" ...
in our _Layout.cshtml
This called a property on our custom view page that in turn called a service which always set a cookie. (Yikes setting cookies in services!, we know!)
Had it not been Friday and at the end of the sprint we might have noticed the cache busting
Cache-Control: no-cache="Set-Cookie":
Http Header.
I still don't understand why this only busted the cache for our custom RouteBase
implementation and not all pages. All pages use the same _Layout.cshtml
.
Upvotes: 1
Reputation: 13138
You might look here to customize caching :
Also, check the cache location.
Upvotes: 0
Reputation: 1774
You can try the following code if it helps
[OutputCache(Duration = 300, VaryByParam="*")]
public ActionResult TextPage(string pageid)
{
var model = textPageController.GetPage(pageid);
return View(model);
}
Upvotes: 0