2010-11-24 7 views
1

Je tente de mettre en cache un appel à une méthode d'action dans ASP.NET MVC3 RC1.Mise en cache d'un appel à Html.Action

La mise en cache fonctionne, mais la variation par paramètre ne semble pas s'améliorer. Y at-il quelque chose que je peux faire pour que les 3 appels à HotOffers retournent des résultats différents en fonction de productID?

La sortie est en ce moment

offres Hot 4

Offres Hot 4

offres Hot 4

Je veux que la sortie soit

offres Hot 4

Offres Chaudes 6

Hot 8 offres

Action

[OutputCache(Duration = 100, VaryByParam = "productId")] 
public PartialViewResult HotOffers(int productId) 
{ 
    ProductModel model = new ProductModel { ProductID = productId }; 
    model.Name = "Meatball"; 

    return PartialView(model); 
} 

page (Index.cshtml)

@{ 
    View.Title = "Home Page"; 
} 
<p> 
<div> 
    @Html.Action("HotOffers", new { productid=4}) 
</div> 
<div> 
@Html.Action("HotOffers", new { productid=6}) 
</div> 
<div> 
@Html.Action("HotOffers", new { productid = 8 }) 
</div> 
</p> 

partielle (HotOffers.cshtml)

Hot offers 
@Model.ProductID 
+1

Cela est dû à une mauvaise conception de la fonctionnalité dans MVC 3 RC. Un correctif a déjà été vérifié dans le produit et devrait être disponible à la prochaine version. – Levi

Répondre

1

Le système de cache utilisé par asp.net existe en dehors de MVC et ne s'applique donc qu'à Urls, puis VaryByParam ne s'applique qu'aux paramètres QueryString.

J'ai posté du code OutputCache behavior in ASP.NET MVC 3 et cela devrait vous permettre de démarrer avec des actions de mise en cache basées sur des paramètres. Dans cet exemple particulier, j'ai ajouté un paramètre "ignorer" qui ignore réellement l'un des champs de l'itinéraire, mais vous pouvez simplement le supprimer et vous devriez être ok.

Je crois que je peux poster ici sans ignorer

public class ActionOutputCacheAttribute : ActionFilterAttribute { 
    public ActionOutputCacheAttribute(int cacheDuration) { 
     this.cacheDuration = cacheDuration; 
    } 

    private int cacheDuration; 
    private string cacheKey; 

    public override void OnActionExecuting(ActionExecutingContext filterContext) { 
     string url = filterContext.HttpContext.Request.Url.PathAndQuery; 
     this.cacheKey = ComputeCacheKey(filterContext); 

     if (filterContext.HttpContext.Cache[this.cacheKey] != null) { 
      //Setting the result prevents the action itself to be executed 
      filterContext.Result = 
      (ActionResult)filterContext.HttpContext.Cache[this.cacheKey]; 
     } 

     base.OnActionExecuting(filterContext); 
    } 

    public override void OnActionExecuted(ActionExecutedContext filterContext) { 
     //Add the ActionResult to cache 
     filterContext.HttpContext.Cache.Add(this.cacheKey, filterContext.Result,null, DateTime.Now.AddSeconds(cacheDuration), 
      System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Normal, null); 

     //Add a value in order to know the last time it was cached. 
     filterContext.Controller.ViewData["CachedStamp"] = DateTime.Now; 

     base.OnActionExecuted(filterContext); 
    } 

    private string ComputeCacheKey(ActionExecutingContext filterContext) { 
     var keyBuilder = new StringBuilder(); 
     keyBuilder.Append(filterContext.ActionDescriptor.ControllerDescriptor.ControllerName); 
     keyBuilder.Append(filterContext.ActionDescriptor.ActionName); 

     foreach (var pair in filterContext.RouteData.Values) { 
      if(pair.Value != null) 
       keyBuilder.AppendFormat("rd{0}_{1}_", pair.Key.GetHashCode(), pair.Value.GetHashCode()); 
     } 
     return keyBuilder.ToString(); 
    } 
} 

Le code ci-dessus était une modification de http://blog.stevensanderson.com/2008/10/15/partial-output-caching-in-aspnet-mvc/