2012-02-25 70 views
2

我有一个ASP.NET MVC应用程序,其中某些资源都是这样解决的:选择基于查询字符串的OutputCache政策

/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

你可以写一个自定义的方法选择:

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

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

0

事实证明,我已经解决了这个问题,而通过利用302个重定向意识到这一点:显然302响应不缓存即使你对你的控制器的方法有OutputCache属性!

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

虽然这现在乞讨的问题,如果你想要缓存302 ...