簡體   English   中英

使用屬性防止在 ASP.NET MVC 中緩存特定操作

[英]Prevent Caching in ASP.NET MVC for specific actions using an attribute

我有一個 ASP.NET MVC 3 應用程序。 此應用程序通過 jQuery 請求記錄。jQuery 回調 controller 操作,以 JSON 格式返回結果。 我無法證明這一點,但我擔心我的數據可能會被緩存。

我只想將緩存應用於特定操作,而不是所有操作。

是否有一個屬性我可以放在一個動作上以確保數據不會被緩存? 如果沒有,我如何確保瀏覽器每次都獲得一組新記錄,而不是緩存的記錄集?

為確保 JQuery 不緩存結果,請在您的 ajax 方法中輸入以下內容:

$.ajax({
    cache: false
    //rest of your ajax setup
});

或者為了防止在 MVC 中緩存,我們創建了自己的屬性,您也可以這樣做。 這是我們的代碼:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class NoCacheAttribute : ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
        filterContext.HttpContext.Response.Cache.SetValidUntilExpires(false);
        filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
        filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        filterContext.HttpContext.Response.Cache.SetNoStore();

        base.OnResultExecuting(filterContext);
    }
}

然后用[NoCache]裝飾你的 controller 。 或者為所有人做這件事,你可以把屬性放在基 class 的 class 上,你從那里繼承你的控制器(如果你有一個)就像我們在這里:

[NoCache]
public class ControllerBase : Controller, IControllerBase

如果你需要它們是不可緩存的,你也可以用這個屬性裝飾一些動作,而不是裝飾整個 controller。

如果您的 class 或操作在您的瀏覽器中呈現時沒有NoCache ,並且您想檢查它是否正常工作,請記住在編譯更改后您需要在瀏覽器中執行“硬刷新”(Ctrl+F5)。 在您這樣做之前,您的瀏覽器將保留舊的緩存版本,並且不會使用“正常刷新”(F5) 對其進行刷新。

您可以使用內置的緩存屬性來防止緩存。

對於 .net 框架: [OutputCache(NoStore = true, Duration = 0)]

對於 .net 核心: [ResponseCache(NoStore = true, Duration = 0)]

請注意,無法強制瀏覽器禁用緩存。 您能做的最好的事情就是提供大多數瀏覽器都會接受的建議,通常以標題或元標記的形式。 此裝飾器屬性將禁用服務器緩存並添加此 header: Cache-Control: public, no-store, max-age=0 它不添加元標記。 如果需要,可以在視圖中手動添加這些。

此外,JQuery 和其他客戶端框架將嘗試通過向 url 添加內容(如時間戳或 GUID)來誘使瀏覽器不使用其緩存的資源版本。 這可以有效地讓瀏覽器再次請求資源,但並不能真正阻止緩存。

最后一點。 您應該知道資源也可以緩存在服務器和客戶端之間。 ISP、代理和其他網絡設備也緩存資源,它們通常使用內部規則而不查看實際資源。 您對此無能為力。 好消息是它們通常緩存較短的時間范圍,例如幾秒或幾分鍾。

所有你需要的是:

[OutputCache(Duration=0)]
public JsonResult MyAction(

或者,如果您想為整個 Controller 禁用它:

[OutputCache(Duration=0)]
public class MyController

盡管這里的評論存在爭議,但這足以禁用瀏覽器緩存——這會導致 ASP.Net 發出響應標頭,告訴瀏覽器文檔立即過期:

OutputCache Duration=0 響應頭:max-age=0, s-maxage=0

在controller動作append到header下面幾行

    public ActionResult Create(string PositionID)
    {
        Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
        Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0.
        Response.AppendHeader("Expires", "0"); // Proxies.

這是 mattytommo 提出的NoCache屬性,使用 Chris Moschini 的回答中的信息進行了簡化:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class NoCacheAttribute : OutputCacheAttribute
{
    public NoCacheAttribute()
    {
        this.Duration = 0;
    }
}

對於 MVC6 ( DNX ),沒有System.Web.OutputCacheAttribute

注意:當您設置NoStore Duration 參數時不考慮。 可以為首次注冊設置初始持續時間並使用自定義屬性覆蓋它。

但是我們有Microsoft.AspNet.Mvc.Filters.ResponseCacheFilter

 public void ConfigureServices(IServiceCollection services)
        ...
        services.AddMvc(config=>
        {
            config.Filters.Add(
                 new ResponseCacheFilter(
                    new CacheProfile() { 
                      NoStore=true
                     }));
        }
        ...
       )

可以使用自定義屬性覆蓋初始過濾器

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public sealed class NoCacheAttribute : ActionFilterAttribute
    {
        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            var filter=filterContext.Filters.Where(t => t.GetType() == typeof(ResponseCacheFilter)).FirstOrDefault();
            if (filter != null)
            {
                ResponseCacheFilter f = (ResponseCacheFilter)filter;
                f.NoStore = true;
                //f.Duration = 0;
            }

            base.OnResultExecuting(filterContext);
        }
    }

這是一個用例

    [NoCache]
    [HttpGet]
    public JsonResult Get()
    {            
        return Json(new DateTime());
    }

ASP.NET MVC 5 解決方案:

  1. 在中央位置緩存預防代碼: App_Start/FilterConfig.csRegisterGlobalFilters方法:
    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            // ...
            filters.Add(new OutputCacheAttribute
            {
                NoStore = true,
                Duration = 0,
                VaryByParam = "*",
                Location = System.Web.UI.OutputCacheLocation.None
            });
        }
    }
  1. 一旦你有了它,我的理解是你可以通過在ControllerView級別應用不同的OutputCache指令來覆蓋全局過濾器。 對於常規 Controller 它是
[OutputCache(NoStore = true, Duration = 0, Location=System.Web.UI.ResponseCacheLocation.None, VaryByParam = "*")]

或者如果它是一個ApiController它會是

[System.Web.Mvc.OutputCache(NoStore = true, Duration = 0, Location = System.Web.UI.OutputCacheLocation.None, VaryByParam = "*")]

Asp.Net MVC Core防止瀏覽器緩存(包括Inte.net Explorer 11 )的正確屬性值為:

[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]

如 Microsoft 文檔中所述:

ASP.NET Core 中的響應緩存 - NoStore 和 Location.None

Output MVC 中的緩存

[OutputCache(NoStore = true, Duration = 0, Location="None", VaryByParam = "*")]

OR
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM