これは、キャッシングとOutputCache
.
最初に 2 番目の質問にお答えします。
それを含めることの利点は何ですか?
ブラウザは、サーバーから返された応答をキャッシュします。キャッシングは主に 3 つのヘッダーによって制御Cache-Control
さLast-Modified
れExpires
ますETag
。
Last-Modified
ヘッダーは、リソースが最後にいつ変更されたかをブラウザーに通知します。リソースは、静的ファイルまたは動的に作成されたビューのいずれかです。ブラウザがそのリソースのリクエストを行うときはいつでも、サーバーをチェックしますLast-Modified
。私のキャッシュからの応答を喜んで使用します。それ以外の場合は、新しい応答をすぐに送信してください。" . (ブラウザは、Last-Modified
以前にサーバーから返された値を、 という新しいヘッダーで渡すことに注意してくださいIf-Modified-Since
)
理想的には、サーバーはIf-Modified-Since
ヘッダーから値を読み取り、現在の変更日を確認する必要があり、それらが同じ場合は304 (NOT MODIFIED)を返すか、現在の変更日を渡してリソースの新しいコピーを再度返す必要があります。Last-Modified
ヘッダー。
利点はブラウザのキャッシングです。ブラウザーのキャッシュを利用することで、サーバーは重複した応答の作成を回避できます。また、ブラウザーにキャッシュされた応答が古いように見える場合は、新しい応答を返すこともできます。最終的な目標は時間を節約することです。
MVC にどのように、どこに含めることができますか?
画像、html ファイルなどの静的リソースの場合、 IIS がそのジョブを処理するため、HowとWhereの設定について心配する必要はありません。IIS は、ファイルの最終変更日をヘッダー値として使用します。Last-Modified
MVC アクションによって返される HTML コンテンツのような動的ページの場合、どのようにLast-Modified
ヘッダー値を決定できますか? 動的に駆動されるページはほとんどがデータ駆動型であり、以前に返された応答が古いかどうかを判断するのは私たちの責任です。
ブログがあり、記事の詳細を表示するページがあるとします (他の詳細は表示されません)。ページのバージョンは、最終更新日または作成日 (記事がまだ変更されていない場合) によって決定されます。論文。したがって、ビューを配信する対応するアクションで@jgauffin が回答したのと同じ作業を行う必要があります。
コントローラーのアクションごとに含める必要がありますか?というコメントで質問しました。
アクションからデータベースから最終変更日を読み取るロジックを抽象化できる場合は、アクション全体でコードが重複するのを回避しながら、アクション フィルターを使用してジョブを実行できます。問題は、アクションから詳細をどのように抽象化するかです。テーブル/列名を属性に渡すのが好きですか? あなたはそれを理解しなければなりません!
例として..
[LastModifiedCacheFilter(Table = "tblArticles", Column = "last_modified")]
public ViewResult Post(int postId)
{
var post = ... get the post from database using the postId
return View(post);
}
以下に示す実装の疑似コード (これはテストしていないことを意味します:) は、LastModifiedCacheFilterAttribute
Table/Column を使用して最終更新日を読み取りますが、他の方法でもかまいません。アイデアはOnActionExecuting
、チェックを実行して 304 を返すメソッド (キャッシュがまだ新しい場合) とOnResultExecuted
、最新の変更日を読み取り/設定するメソッドにあります。
public class LastModifiedCacheFilterAttribute : ActionFilterAttribute
{
// Could be some other things instead of Table/Column
public string Table { get; set; }
public string Column { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// var lastModified = read the value from the passed Column/Table and set it here
var ifModifiedSinceHeader = filterContext.RequestContext.HttpContext.Request.Headers["If-Modified-Since"];
if (!String.IsNullOrEmpty(ifModifiedSinceHeader))
{
var modifiedSince = DateTime.Parse(ifModifiedSinceHeader).ToLocalTime();
if (modifiedSince >= lastModified)
{
filterContext.Result = new EmptyResult();
filterContext.RequestContext.HttpContext.Response.Cache.SetLastModified(lastModified.ToUniversalTime());
filterContext.RequestContext.HttpContext.Response.StatusCode = 304;
}
}
base.OnActionExecuting(filterContext);
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
// var lastModified = read the value from the passed Column/Table and set it herefilterContext.RequestContext.HttpContext.Response.Cache.SetLastModified(lastModified.ToUniversalTime());
base.OnResultExecuted(filterContext);
}
}
OutputCache 属性を使用できないのはなぜですか?
私の分析によると、OutputCache
属性はLast-Modified
キャッシュメカニズムを使用していません。もう 1 つは、古いページ キャッシング メカニズムを使用しているため、カスタマイズや拡張が困難なことです。
すべてのアクションに最終変更メカニズムを実装する必要は本当にありますか?
本当に必要ありません。そのような応答を作成するのに時間がかかり、応答がネットワークを下ってブラウザに到達するのに時間がかかる、最終変更メカニズムをアクションに実装できます。他のケースでは、すべてのアクションを実装するのは単なるオーバーヘッドであり、実装する前に利点を測定する必要があると感じています. もう 1 つの主なポイントは、多くの場合、ページのバージョンは1 つのテーブル列だけで決まるわけではなく、他の多くの要素によって決まる可能性があり、そのような場合、これを実装するのはより複雑になる可能性があるということです!
についてのポイントETag
質問はヘッダーに関するものですが、[回答を投稿] ボタンをクリックする前にLast-Modified
何かを伝えておく必要があります。ヘッダー (日時に依存)と比較して、ヘッダー (ハッシュ値に依存) は、ブラウザーにキャッシュされた応答が最新かどうかを判断する際により正確ですが、実装が少し複雑になる可能性があります。IIS には、静的リソースのヘッダーと共にヘッダーも含まれています。このメカニズムを実装する前に、グーグルで検索して、役立つライブラリがあるかどうかを確認してください。ETag
Last-Modified
ETag
ETag
Last-Modified