[ASP.NET MVC] 讓 API 允許/不允許瀏覽器快取

為 api 加上 attribute, 設定快取類型

快取,並且指定有效時間

加上OutputCacheAttribute

並設定Duration, 則可以在 response 的 header 上加上 Cache-Control: public, max-age=120, 指定快取有效期限為120秒.

則在120秒內, 每次請求都會拿到相同的回應 2021-04-12 09:42:11Z

[OutputCache(Duration = 120)]
[HttpGet]
public DateTime Test()
{
    return Json(DateTime.Now.ToString("u"), JsonRequestBehavior.AllowGet);
}

Http Response

GET /api/1.0/home/index HTTP/1.1
Cache-Control: public, max-age=120

Content-Length: 22
Response Body
"2021-04-12 09:42:11Z"

不允許快取

調整 OutputCache, 加上 NoStore = true, response 的 header 會加上 Cache-Control: public, no-store, max-age=0

no-store表示不允許快取, 所有請求都必須跟Server取得回應.

[Route("index")]
[OutputCache(Duration = 0, NoStore = true)]
[HttpGet]
public JsonResult Index()
{
    return Json(DateTime.Now.ToString("u"), JsonRequestBehavior.AllowGet);
}
GET /api/1.0/home/index HTTP/1.1
Cache-Control: public, no-store, max-age=0

Content-Length: 22
Response Body
"2021-04-12 10:18:44Z"

允許快取,但cookie異動時要重新請求

我希望把使用的語系存在cookie, 當切換語系時, 也必須讓API返回對應的語系內容. 在OutputCache加上VaryByCustom = "language".

[Route("index")]
[OutputCache(Duration = 120, VaryByCustom = "language")]
[HttpGet]
public JsonResult Index()
{
    return Json(DateTime.Now.ToString("u"), JsonRequestBehavior.AllowGet);
}

Global.asax.csMvcApplication覆寫方法GetVaryByCustomString來指定language應該怎麼取得.

public override string GetVaryByCustomString(HttpContext context, string custom)
{
    var languageKey = "language";
    if (custom == languageKey)
    {
        var value = context.Request.Cookies[languageKey];
        if (value != null)
        {
            return value.Value;
        }
    }
    return base.GetVaryByCustomString(context, custom);
}
GET http://localhost:41546/api/1.0/home/index
Cookie: language=tw
Cache-Control: public, max-age=110

Content-Length: 22
Response Body
"2021-04-12 10:47:52Z"

接著只要cookie有異動, 每次的response都會更新.


以上只提及部份快取的使用, 沒有提到no-storeno-cache的差異, 有興趣的可以在深入瞭解.


HTTP caching