2015-09-11 6 views
0

Nous utilisons un ActionFilterAttribute pour injecter certains paramètres dans des actions et cela fonctionne très bien. Mais quand nous ajoutons OutputCache, il varie exclusivement sur "MyID" quand Html.RenderAction() est utilisé et pas en surfant directement sur l'action.OutputCache et ActionParameters injectés

Des idées comment obtenir OutputCache pour toujours reconnaître "MyID"?

Contrôleur

[SiteIDs, OutputCache] 
public ActionResult SiteContent(string myID) 
{ 
    return Content(myID); 
} 

ActionFilter

public class SiteIDs : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     if (filterContext.ActionParameters.ContainsKey("MyID")) 
     { 
      filterContext.ActionParameters["MyID"] = GetMyIDByHostname(); 
     } 

     base.OnActionExecuting(filterContext); 
    } 
} 

Répondre

0

Avec le OutputCacheAttribute, les filtres d'action ne seront pas exécutés lorsqu'une page est récupérée à partir du cache. Vous devez probablement utiliser mvcdonutcaching pour que les filtres d'action soient exécutés même lors de la récupération du cache. Je vous recommande de lire this.

+0

J'ai essayé MvcDonutCaching maintenant et mon ActionFilter s'exécute à chaque fois mais cela ne fonctionne pas (ni via Html.RenderAction() ni directement). J'ai également regardé la source pour les deux et il semble que [OutputCache] utilise ActionParameters et [DonutOutputCache] RouteData lors de la génération d'une clé. –

0

Option 1

Selon this answer, il vous suffit d'utiliser VaryByParam = "*" et il variera automatiquement par les paramètres que vous passez la méthode d'action.

[SiteIDs, OutputCache(VaryByParam = "*")] 
public ActionResult SiteContent(string myID) 
{ 
    return Content(myID); 
} 

Cependant, cela ne peut pas fonctionner en utilisant un IActionFilter (n'ont pas essayé). Vous pouvez essayer d'utiliser un IValueProvider à la place (ce qui est une façon plus simple de faire ce que vous faites avec le filtre d'action, de toute façon).

Option 2

Vous pouvez utiliser VaryByCustom et GetVaryByCustomString pour faire varier le cache par nom d'hôte.

[SiteIDs, OutputCache(VaryByParam = "none", VaryByCustom = "hostname")] 
public ActionResult SiteContent(string myID) 
{ 
    return Content(myID); 
} 

Et dans votre fichier Global.asax:

public class MvcApplication : System.Web.HttpApplication 
{ 
    protected void Application_Start() 
    { 
     AreaRegistration.RegisterAllAreas(); 

     WebApiConfig.Register(GlobalConfiguration.Configuration); 
     FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
     RouteConfig.RegisterRoutes(RouteTable.Routes); 
     BundleConfig.RegisterBundles(BundleTable.Bundles); 
     AuthConfig.RegisterAuth(); 
    } 

    public override string GetVaryByCustomString(HttpContext context, string custom) 
    { 
     if (custom == "hostname") 
     { 
      return "HostName=" + context.Request.Url.Host; 
     } 

     return base.GetVaryByCustomString(context, custom); 
    } 
} 

Gardez à l'esprit que votre filtre d'action ne sera touché si le OutputCache n'a pas été définie. Vous devez donc faire varier le cache sur la même valeur (ou les mêmes valeurs) que celle dont vous modifiez votre ID. La solution la plus simple consiste à utiliser quelque chose qui est déjà dans HttpContext, tel que le nom d'hôte.

+0

Option 1: Oui, VaryByParam = "*" est la valeur par défaut et fonctionne avec IActionFilter lorsque Html.RenderAction ("MyAction", "MyController", new {notIncludingMyIDInRouteValueDictinary = "foo"}) est utilisé mais pas lors de l'accès direct à l'action . J'ai essayé avec un IValueProvider aujourd'hui, pas de différence. Option 2: N'avez pas encore essayé. –