13

パフォーマンスを簡単に向上させるために、アプリのいくつかのアクションに出力キャッシュを追加しました。ただし、これらのアクションでは、Redisデータベースをヒットすることにより、各リクエストの後にカウンター(ビューカウンター)をインクリメントする必要もあります。

最初は、アクションフィルターが実行される順序を調整して、ビューが確実にカウントされるようにすることができると考えました。

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

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

それで、ええと、(カスタム出力キャッシュプロバイダーを実装せずに)ビューが適切にカウントされ、クリーンで賢明であることを確認する方法はありますか?

4

4 に答える 4

14

ちなみに、OutputCacheAttributeには制限があり、 PaulHilesによって開発されたDonutOutputCacheという名前のカスタム属性が制限を克服するのに役立ちます。

サポートされている重要な機能の1つは、アクションがキャッシュ属性でマークされているかどうかに関係なく、常に呼び出すことができるアクションフィルターを使用できることです。

例:アクションを5秒間キャッシュすると同時に、アクションがフィルターを使用してリクエストを受信するたびにログに記録するLogThis場合は、以下の方法でそれを実現できます。

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

ポールから、

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

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

したがって、あなたの場合、DonutOutputCache属性にOrder = 100を追加するだけで、他のすべてのフィルターがキャッシュフィルターの前に実行されます。

于 2012-06-12T04:46:25.540 に答える
1

ページがキャッシュされている場合でも、レイアウトビューからAJAX呼び出しを行い、訪問者を追跡できます。これは、GoogleAnalyticsが行うことです。レイアウトビューから実行することをお勧めします。これは、そのレイアウトを使用するすべてのビューで実行されるためです。もう1つのコメントとして、2つのレイアウトビューがあるとします。1つはサイトのパブリック部分用で、もう1つはバックエンド用です(従業員のみ)。おそらく、従業員ではなくユーザーの追跡に関心があるので、これはレイアウトビューで追跡するもう1つの利点です。将来、従業員の行動を追跡したい場合は、バックエンドのレイアウトビューに別のトラッカーを追加できます。お役に立てば幸いです。

于 2014-07-29T20:29:37.277 に答える
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;
}

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

唯一の解決策は、プロジェクトをフォークして必要な方法に拡張するか、プルリクエストを送信してマークprotected ICacheHeadersHelper CacheHeadersHelperインすることです。DonutOutputCacheAttribute

于 2013-03-25T21:59:22.820 に答える
0

キャッシュされたページを提供する必要がある場合でも、常に実行される「検証コールバック」を使用します

public class MyCacheAttribute : OutputCacheAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        SaveToLog();

        httpContext.Response.Cache.AddValidationCallback(MyCallback, null);

        base.OnResultExecuting(filterContext);
    }

    // This method is called each time when cached page is going to be served
    private void MyCallback(HttpContext context, object data, ref HttpValidationStatus validationStatus)
    {
        SaveToLog();
    }
}

注:はSaveToLog()2つの場所で呼び出されます。これは仕様によるものです(キャッシュがバイパスされた場合の最初の呼び出し、キャッシュされたバージョンが提供された場合の2番目の呼び出し)

于 2018-11-04T17:32:58.490 に答える