2 votes

Choisir la politique de OutputCache en fonction de la chaîne de requête

J'ai une application ASP.NET MVC dans laquelle certaines ressources sont adressées comme suit :

/controller/action/id?revision=123

En révision est facultatif :

  • s'il est manquant, je fais une redirection 302 vers la dernière révision. Je souhaite que cette réponse de redirection ne soit mise en cache que pendant une courte période, voire pas du tout.
  • s'il est présent, je veux mettre la réponse en cache pendant longtemps, car toute révision de la ressource est immuable.

Ma première tentative a été de faire quelque chose comme ça :

[OutputCache(Duration=10,Location=OutputCacheLocation.Server)]
public Action(string id)
{
    long lastRevision = GetLastRevision(id);
    return RedirectToAction("Action", 
        new { Id = id, revision = lastRevision }); 
}

[OutputCache(Duration=int.MaxValue,Location=OutputCacheLocation.Server)]
public Action(string id, long revision)
{
   // ... 
}

Malheureusement, le routage ASP.NET MVC ne semble pas apprécier les surcharges de méthodes. Il s'attend à ce qu'il n'y ait qu'une seule méthode Action avec un paramètre optionnel à la place (c'est-à-dire long? revision ), mais je ne peux pas spécifier des politiques de mise en cache différentes pour les deux cas.

Comment puis-je choisir une politique de mise en cache différente en fonction de la présence de la chaîne de requête ici ?

2voto

Darin Dimitrov Points 528142

Vous pouvez écrire un sélecteur de méthode personnalisé :

public class RevisionMethodSelectorAttribute : ActionMethodSelectorAttribute
{
    public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
    {
        var revision = controllerContext.Controller.ValueProvider.GetValue("revision");
        var hasRevisionParam = methodInfo.GetParameters().Any(p => string.Equals("revision", p.Name, StringComparison.OrdinalIgnoreCase));
        if (revision != null && !string.IsNullOrEmpty(revision.AttemptedValue) && hasRevisionParam)
        {
            return true;
        }

        if ((revision == null || string.IsNullOrEmpty(revision.AttemptedValue)) && !hasRevisionParam)
        {
            return true;
        }

        return false;
    }
}

et décorer les 2 actions avec :

[RevisionMethodSelector]
public ActionResult MyAction(string id)
{
    long lastRevision = GetLastRevision(id);
    return RedirectToAction("MyAction", new { id = id, revision = lastRevision }); 
}

[RevisionMethodSelector]
[OutputCache(Duration = int.MaxValue, Location = OutputCacheLocation.Server, VaryByParam = "revision")]
public ActionResult MyAction(string id, long revision)
{
    ...
}

La première action n'est pas mise en cache. Elle sera récupérée s'il n'y a pas de paramètre de révision dans la requête et elle redirigera simplement vers la deuxième action. La seconde action est mise en cache pour une très longue période, ce cache est fait pour varier en fonction de la valeur du paramètre de révision (que vous n'aviez pas) et sera récupéré par le sélecteur de méthode personnalisé si un paramètre de révision est présent dans la requête.

0voto

Wim Coenen Points 41940

Il s'avère que j'avais déjà résolu ce problème sans m'en rendre compte en utilisant des redirections 302 : apparemment Les réponses 302 ne sont pas mises en cache même si vous avez un OutputCache sur la méthode de votre contrôleur !

Par conséquent, les deux cas peuvent être traités par une seule méthode de contrôleur avec l'option [OutputCache(...)] spécifiant ce qu'il faut faire pour les 200 réponses.

Mais cela soulève la question de savoir ce qu'il faut faire si l'on veut mettre en cache un 302...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X