2012-06-12 5 views
11

簡単なパフォーマンス向上のために、私のアプリケーションでいくつかのアクションに出力キャッシュを追加しました。ただし、これらのアクションでは、Redis dbを押すことによって、各リクエスト(ビューカウンタ)ごとにカウンタを増やす必要があります。まず出力キャッシュとその他のアクションフィルタの操作

、私はちょうどフィルタが視界を確保するために実行するアクションがカウントされる順序調整することができます考え出し:

public class CountersAttribute : ActionFilterAttribute 
{ 
    public override void OnResultExecuted(ResultExecutedContext filterContext) 
    { 
     //increment my counter all clever like 
     base.OnResultExecuted(filterContext); 
    } 
} 

をしかし、それは動作しませんでした。明らかに、OutputCacheAttributeは通常のアクションフィルターのように振る舞いません。次に、カスタム出力キャッシュを実装しようとしました。

public class OutputCacheWithCountersAttribute : OutputCacheAttribute 
{ 
    public override void OnResultExecuted(ResultExecutedContext filterContext) 
    { 
     //straight to the source to get my headcount! 
     base.OnResultExecuted(filterContext); 
    } 
} 

いいえ、どちらも機能しませんでした。アクションフィルタは、アクションがキャッシュされると完全に無視されるように見えます。バマー。

私の見解がきれいで賢明であることを確実にするために、(カスタム出力キャッシングプロバイダを実装することなく)何らかの方法がありますか?

答えて

13

OutputCacheAttributeには制限があり、制限を克服するためにPaul Hilesによって開発されたDonutOutputCacheというカスタム属性があります。

重要な機能の1つは、アクションにキャッシュ属性でマークされていても常に呼び出すことができるアクションフィルタを持つことができることです。

例: 、あなたは、期間5秒のアクションをキャッシュすると同時に、あなたは単に以下でそれを達成することができLogThisフィルタを使用して、アクションが要求を受信するたびに記録したい

[LogThis] 
[DonutOutputCache(Duration=5, Order=100)] 
public ActionResult Index() 

Paulから

はい、組み込みのOutputCacheAttributeとは異なり、アクションフィルタは、ページがキャッシュから取得されても実行されます( )。 を追加する唯一の警告は、フィルタの順序に注意する必要があるということです。 アクションフィルタがOnResultExecutingまたはOnResultExecutedを実装する場合 これらのメソッドはすべてOnActionExecutingおよびOnActionExecutedの場合は実行されますが、 フィルタがDonutOutputCacheAttributeより前に実行された場合にのみ実行されます。これは 出力キャッシングのために行う必要があるfilterContext.Resultプロパティを に設定したときにMVCが後続のフィルタの実行を妨げるためです。

アクションフィルタ がアクションまたはコントローラで定義されている順序に頼ることはできません。 1つのフィルタが別のフィルタの前に を確実に実行するようにするには、すべてのActionFilterAttribute実装で現在のOrderプロパティである を使用できます。 オーダープロパティが設定されていないアクションは、デフォルトで値-1になります。つまり、明示的なOrder値を持つフィルタの前に が実行されます。

DonutOutputCache属性にOrder = 100を追加するだけで、他のすべてのフィルタはキャッシングフィルタ より前に実行されます。

+0

これはすごくうまくいきますが、私のVaryByCustomパラメータは機能しません。 GetVaryByCustomString()はグローバルで呼び出されますが、DonutはResponse.Cacheの変更を尊重していないようです(つまり、認証されたユーザーのキャッシュを無効にします)。 – Dusda

+0

context.Response.Cache.SetCacheability(HttpCacheability.NoCache); context.Response.Cache.SetExpires(DateTime.Now.AddMinutes(-1)); context.Response.Cache.SetNoStore(); context.Response.Cache.SetNoServerCaching(); これは私のレスポンスです。キャッシュの変更。とにかくドーナツはそれを無視して、それをすべてキャッシュしているようだ。 – Dusda

+0

VaryByCustomを使いこなすのではなく、ページビューをajax呼び出しに移動しました。しかし、この答えは、この問題の大きな解決策です。ありがとう:D。 – Dusda

0

理由は、.NETソースで実際に行われず、DonutOutputCacheとは何の関係:つまり

public void SetCacheability(HttpCacheability cacheability) 
{ 
    if (cacheability < HttpCacheability.NoCache || HttpCacheability.ServerAndPrivate < cacheability) 
    throw new ArgumentOutOfRangeException("cacheability"); 
    if (HttpCachePolicy.s_cacheabilityValues[(int) cacheability] >= HttpCachePolicy.s_cacheabilityValues[(int) this._cacheability]) 
    return; 
    this.Dirtied(); 
    this._cacheability = cacheability; 
} 

あなたが最初に(1の値)をNoCache命令を設定した場合、それは常にます4(public)などのより高い値を設定しようとすると戻ります。

唯一の解決策は、プロジェクトをフォークし、あなたが必要とどのようにそれを拡張し、または多分あなたはレイアウトビューからAJAX呼び出しを行うとも、あなたの訪問者を追跡することができprotected ICacheHeadersHelper CacheHeadersHelper

1

DonutOutputCacheAttributeにマークするために、プルリクエストを送信することですページがキャッシュされている場合これがGoogleアナリティクスの役割です。そのレイアウトを使用するすべてのビューで実行されるため、レイアウトビューから行うことをお勧めします。 コメントがもう1つあります。サイトの公開部分用とバックエンド用(従業員のみ)の2つのレイアウトビューがあるとします。従業員ではなくユーザーの追跡に興味があるので、これはレイアウトビューで追跡するもう1つの利点です。将来従業員の行動を追跡したい場合は、バックエンドのレイアウトビューに別のトラッカーを追加することができます。 私はそれが助けてくれることを願っています。

関連する問題