2012-09-14 18 views
10

Tengo un problema con mi implementación personalizada RouteBase y [OutputCache]. Tenemos un CMS en el que las direcciones URL se asignan a determinadas páginas de contenido. Cada tipo de página de contenido es manejada por un controlador diferente (y diferentes vistas). Las direcciones URL son completamente gratuitas y queremos diferentes controladores, por lo que no se puede utilizar una ruta "atrapada". Entonces creamos una implementación personalizada de RouteBase que llama a la base de datos para encontrar todas las urls. La base de datos sabe qué Controlador y Acción usar (en función del tipo de página de contenido).ASP.NET MVC 3 Custom RouteBase y OutputCache

Esto funciona genial.

Sin embargo, al combinar esto con el atributo [OutputCache], el almacenamiento en caché de resultados no funciona (la página aún funciona). Nos aseguramos de que [OutputCache] funcione en nuestras rutas "normales".

Es muy difícil depurar el almacenamiento de salida, el atributo está ahí, lo usamos nosotros, no funciona ... Las ideas sobre cómo abordar esto serían muy bienvenidas, ¡y la respuesta correcta!

El controlador tiene el siguiente aspecto:

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

La costumbre es el siguiente:

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

Gracias por leer hasta el final!

+0

BTW Olvidé mencionar que miré el contador de rendimiento "Aplicaciones ASP.NET/Entradas de caché de resultados", que se genera cuando agrego correctamente una página a la caché, pero no cuando se llama al controlador anterior utilizando mi costumbre Implementación de RouteBase – Jaap

+0

Durante el fin de semana extraje la lógica detrás de esto al más pequeño ejemplo, y funciona. Sin embargo, en nuestro proyecto más grande no es así. Por lo tanto, mi esfuerzo debe ser comprender por qué no funciona. Depurar el almacenamiento en caché no es lo suficientemente fácil :( – Jaap

+0

¿dónde intentas almacenar en caché? ¿Quieres que IIS almacene en caché tus páginas o quieres que el cliente (navegador) lo guarde en caché? El almacenamiento en caché en IIS puede ser difícil ya que IIS puede funcionar con formas simples de URL pero el almacenamiento en caché en la computadora del cliente es fácil configurando Response.Expires –

Respuesta

1

Al final, lo rastreó a una llamada a

... data-role="@this.FirstVisit" ... 

en nuestra _Layout.cshtml

Esta llama una propiedad en nuestra página de vista personalizada que a su vez llamó a un servicio que siempre se establece una cookie. (Ajuste Huy las cookies en los servicios!, sabemos!)

Si no hubiera sido viernes y al final del sprint que se habrán dado cuenta que revienta la Cache-Control: no-cache="Set-Cookie": encabezado HTTP caché.

Todavía no entiendo por qué esto solo rompió el caché para nuestra implementación personalizada RouteBase y no todas las páginas. Todas las páginas usan el mismo _Layout.cshtml.

+0

Gracias Martijn :) – Jaap

0

Puede probar el siguiente código si ayuda

[OutputCache(Duration = 300, VaryByParam="*")] 
public ActionResult TextPage(string pageid) 
{ 
    var model = textPageController.GetPage(pageid); 
    return View(model); 
} 
+0

VaryByParam = "*" está predeterminado en MVC 3 – Jaap