根据查询字符串选择OutputCache策略

时间:2012-02-25 00:39:50

标签: asp.net-mvc

我有一个ASP.NET MVC应用程序,其中某些资源的处理如下:

/controller/action/id?revision=123

修订参数是可选的:

  • 如果缺少,我会将302重定向到最新版本。我希望这个重定向响应只能在一段时间内缓存,或者根本不缓存。
  • 如果它存在,我想长时间缓存响应,因为任何给定的资源修订都是不可变的。

我的第一次尝试是做这样的事情:

[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)
{
   // ... 
}

不幸的是,ASP.NET MVC路由似乎不喜欢方法重载。它希望有一个带有可选参数的Action方法(即long? revision),但是我不能为这两种情况指定不同的缓存策略。

如何根据查询字符串的存在选择不同的缓存策略?

2 个答案:

答案 0 :(得分:2)

您可以编写自定义方法选择器:

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

然后用它装饰2个动作:

[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)
{
    ...
}

第一个操作未缓存。如果请求中没有修订参数,它将被拾取,它将简单地重定向到第二个操作。第二个操作缓存很长一段时间,此缓存根据修订参数值(您没有)而变化,如果请求中存在修订参数,则自定义方法选择器将选择该缓存。

答案 1 :(得分:0)

事实证明,我已经解决了这个问题而没有通过使用302重定向来实现它:显然 302响应没有缓存,即使您的控制器上有OutputCache属性方法!

因此,这两种情况都可以通过单个控制器方法处理,[OutputCache(...)]属性指定如何处理200个响应。

虽然这现在引出了如果你想要缓存302 ...

该怎么办的问题