接受的答案是正确的,但它在这种部分视图缓存的方式上不起作用。我将两种方法结合起来使用:使用
GetVaryByCustomString
并将
Duration
设置为最小值-用于局部视图,以及使用
AddValidationCallback
方法进行页面设置。实际上,只使用第一种方法也是可行的,但第二种方法看起来不那么昂贵-它不会每次都调用
OnResultExecuting
,而只调用注册的处理程序。
所以这是自定义缓存属性类。
public class CacheAttribute : OutputCacheAttribute
{
public CacheAttribute()
{
Duration = 300;
}
private bool _partialView;
public bool PartialView
{
get { return _partialView; }
set
{
_partialView = value;
if ( _partialView ) {
VaryByCustom = "Auth";
}
}
}
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
if ( PartialView ) OnCachePartialEnabled( filterContext );
else OnCacheEnabled(filterContext);
base.OnResultExecuting( filterContext );
}
private OutputCacheLocation? originalLocation;
private int? _prevDuration;
protected void OnCachePartialEnabled(ResultExecutingContext filterContext)
{
var httpContext = filterContext.HttpContext;
if ( !_prevDuration.HasValue) _prevDuration = Duration;
Duration = httpContext.User.Identity.IsAuthenticated ? 1 : _prevDuration.Value;
}
protected void OnCacheEnabled(ResultExecutingContext filterContext)
{
var httpContext = filterContext.HttpContext;
if ( httpContext.User.Identity.IsAuthenticated ) {
originalLocation = originalLocation ?? Location;
Location = OutputCacheLocation.None;
}
else {
Location = originalLocation ?? Location;
}
httpContext.Response.Cache.AddValidationCallback( IgnoreAuthenticated, null );
}
private void IgnoreAuthenticated(HttpContext context, object data, ref HttpValidationStatus validationStatus)
{
validationStatus = context.User.Identity.IsAuthenticated
? HttpValidationStatus.IgnoreThisRequest
: HttpValidationStatus.Valid;
}
}
在Global.asax.cs中重写GetVaryByCustomString方法。
public override string GetVaryByCustomString(HttpContext context, string custom)
{
if ( custom == "Auth" ) {
if ( context.User.Identity.IsAuthenticated ) {
return base.GetVaryByCustomString( context, custom );
}
return "NotAuth";
}
return base.GetVaryByCustomString( context, custom );
}
使用方法如下:
[Cache]
public virtual ActionResult Index()
{
return PartialView();
}
[ChildActionOnly, Cache(PartialView=true)]
public virtual ActionResult IndexPartial()
{
return PartialView();
}
更新:我在这里也添加了Fujiy的修复方法。