Nonaktifkan cache browser untuk seluruh situs web ASP.NET

199

Saya mencari metode untuk menonaktifkan cache browser untuk seluruh situs web ASP.NET MVC

Saya menemukan metode berikut:

Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
Response.Cache.SetNoStore();

Dan juga metode meta tag (tidak akan bekerja untuk saya, karena beberapa tindakan MVC mengirim sebagian HTML / JSON melalui Ajax, tanpa kepala, meta tag).

<meta http-equiv="PRAGMA" content="NO-CACHE">

Tetapi saya mencari metode sederhana untuk menonaktifkan cache browser untuk seluruh situs web.

Palani
sumber

Jawaban:

92
HttpContext.Current.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
HttpContext.Current.Response.Cache.SetValidUntilExpires(false);
HttpContext.Current.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.Cache.SetNoStore();

Semua permintaan dialihkan melalui default.aspx terlebih dahulu - jadi anggap saja Anda bisa memunculkan kode di belakang sana.

Squiggs.
sumber
17
Saya akan memasukkannya ke Global.asax.cs di Application_BeginRequest (). Saya tidak mempercayai hal default.aspx ini ... Pertanyaan lain: apakah ini lebih diutamakan daripada atribut [OutputCache]?
chris166
5
Saya suka ide hanya membuat Filter Tindakan Global dan meletakkan barang-barang ini dengan cara itu. Meniadakan kebutuhan untuk khawatir tentang Default.aspx dan Global.asax.
Keith Adler
13
Menempatkan ini di Application_BeingRequest dapat menyebabkan beberapa masalah. Jika gambar Anda dialihkan melalui .net runtime (yang dapat terjadi jika Anda menggunakan pemetaan wildcard untuk url yang bagus) maka tidak ada gambar yang akan di-cache di browser. Ini BENAR-BENAR dapat memperlambat waktu pemuatan halaman Anda karena setiap permintaan halaman akan mengunduh ulang semua gambar.
herbrandson
4
Menggunakan apa pun secara terprogram akan selalu menimpa Atribut apa pun yang dinyatakan. Dengan kata lain, menggunakan kode OP akan menimpa atribut [OutputCache] yang dinyatakan.
Dave Black
Adakah pemikiran tentang cara menguji merokok dan memverifikasi bahwa penonaktifan cache sebenarnya berfungsi?
paaone
366

Buat kelas yang mewarisi dari IActionFilter.

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

Kemudian letakkan atribut di mana diperlukan ...

[NoCache]
[HandleError]
public class AccountController : Controller
{
    [NoCache]
    [Authorize]
    public ActionResult ChangePassword()
    {
        return View();
    }
}
JKG
sumber
19
Daripada HttpContext.Current.Response, Anda mungkin harus menggunakan filterContext.HttpContext.Response karena HttpContext.Current mengembalikan objek HttpContext pra-MVC dan filterContext.HttpContext mengembalikan post-MVC HttpContextBase. Ini meningkatkan testability dan konsistensi.
mkedobbs
5
IActionFilter sudah diterapkan pada ActionFilterAttribute, jadi Anda tidak perlu mengulanginya.
Andrew Davey
104
Dalam versi ASP.NET MVC saat ini, Anda cukup menggunakan OutputCacheAttribute untuk mencegah caching: [OutputCache (NoStore = true, Durasi = 0, VaryByParam = "Tidak Ada")]
Ashley Tate
9
Saya ingin menunjukkan bahwa saya hanya menghabiskan beberapa hari menggunakan setiap solusi "letakkan ini di kode Anda untuk menghentikan caching" di bawah matahari untuk ASP.NET MVC, termasuk jawaban yang diterima untuk pertanyaan ini, tidak berhasil. Jawaban ini - atribut - berfungsi. + 1M Wakil jika saya bisa ...
Tom Kidd
5
Anda mungkin ingin menambahkan if (filterContext.IsChildAction) return;di bagian atas - ini akan mencegah tindakan luar menjadi 'tidak di-cache' jika tindakan anak memanggil yang dihiasi dengan NoCacheatribut. Dengan kata lain NoCacheatribut tidak akan bocor ke tindakan lain jika mereka melakukan tindakan anak. Juga, nama kelas harus NoCacheAttributemematuhi konvensi penamaan atribut yang diterima secara umum.
Jakub Konecki
132

Alih-alih menggulung sendiri, cukup gunakan apa yang disediakan untuk Anda.

Seperti yang disebutkan sebelumnya, jangan nonaktifkan caching untuk semuanya. Misalnya, skrip jQuery yang banyak digunakan dalam ASP.NET MVC harus di-cache. Sebenarnya idealnya Anda harus menggunakan CDN untuk itu, tetapi poin saya adalah beberapa konten harus di-cache.

Apa yang saya temukan berfungsi paling baik di sini daripada menaburkan [OutputCache] di mana-mana adalah menggunakan kelas:

[System.Web.Mvc.OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public class NoCacheController  : Controller
{
}

Semua pengontrol Anda, Anda ingin menonaktifkan caching untuk kemudian diwarisi dari pengontrol ini.

Jika Anda perlu mengganti default di kelas NoCacheController, cukup tentukan pengaturan cache pada metode tindakan Anda dan pengaturan pada metode Tindakan Anda akan diutamakan.

[HttpGet]
[OutputCache(NoStore = true, Duration = 60, VaryByParam = "*")]
public ViewResult Index()
{
  ...
}
Adam Tuliper - MSFT
sumber
4
@Ozziepeeps, komentar Anda tidak benar. Dokumentasi msdn yang membahas cache browser serta pengujian sederhana akan menunjukkan atribut ini mengubah header respons kontrol-cache menjadi "Kontrol-cache: publik, no-store, maks-age = 0" dari "Kontrol-cache: privat" tanpa menggunakan atribut.
Adam Tuliper - MSFT
2
juga fyi - Anda dapat mengontrol ketiga lokasi (server, proksi, klien) dengan atribut ini sehingga benar-benar dapat mengontrol di luar cache server. Lihat asp.net/mvc/tutorials/… untuk beberapa detail tambahan.
Adam Tuliper - MSFT
1
+1 "Jika Anda perlu mengganti default di kelas NoCacheController cukup tentukan pengaturan cache pada metode tindakan Anda dan pengaturan pada metode Tindakan Anda akan diutamakan."
Korayem
2
Harap dicatat bahwa jika Anda menggunakan [System.Web.Mvc.OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]di tingkat kelas, Anda tidak dapat memiliki PartialViews di kelas Anda.
Sungai Vivian
1
Metode OutputCache tidak mencegah caching IE ketika ada dua kondisi: 1) tindakan tidak mengambil parameter dan 2) tindakan hanya mengembalikan teks melalui Konten (someText). Ketika saya mengembalikan JSON dan mengambil parameter, caching IE dikalahkan dengan benar.
Kasey Speakman
10

Anda mungkin ingin menonaktifkan cache browser untuk semua halaman yang dibuat oleh pengontrol (yaitu halaman HTML), tetapi tetap menyimpan cache untuk sumber daya seperti skrip, style sheet, dan gambar . Jika Anda menggunakan MVC4 + bundling dan minification, Anda ingin mempertahankan durasi cache default untuk skrip dan stylesheet (durasi yang sangat lama, karena cache menjadi tidak valid berdasarkan perubahan URL unik, bukan berdasarkan waktu).

Di MVC4 +, untuk menonaktifkan cache browser di semua pengontrol, tapi simpan untuk apa pun yang tidak dilayani oleh pengontrol, tambahkan ini ke FilterConfig.RegisterGlobalFilters:

filters.Add(new DisableCache());

Tetapkan DisableCachesebagai berikut:

class DisableCache : ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    }
}
Edward Brey
sumber
Sayangnya ini tidak berfungsi, karena menekan tombol kembali setelah keluar menampilkan halaman.
ᴍᴀᴛᴛ ʙᴀᴋᴇʀ
6

Saya tahu jawaban ini tidak 100% terkait dengan pertanyaan, tetapi mungkin membantu seseorang.

Jika Anda ingin menonaktifkan cache browser untuk seluruh situs web ASP.NET MVC , tetapi Anda hanya ingin melakukan ini secara TEMPORARILY, maka lebih baik untuk menonaktifkan cache di browser Anda.

Berikut screenshot di Chrome

Carlos Martinez T
sumber
Ini adalah persis apa yang saya cari ... selama dev, jika saya mengubah file .js, itu sangat menyebalkan untuk mendapatkannya segera ketika saya kesulitan untuk melakukan sedikit masalah / siklus refresh / tes. Ini sempurna, terima kasih! Hanya membuat hidup debugging sisi klien saya jauh lebih mudah
jleach
2

Saya menerapkan semua jawaban sebelumnya dan masih memiliki satu pandangan yang tidak berfungsi dengan benar.

Ternyata nama tampilan saya mengalami masalah bernama 'Terbaru'. Rupanya ini membingungkan browser Internet Explorer.

Setelah saya mengubah nama tampilan (di controller) menjadi nama yang berbeda (saya memilih 'Recent5'), solusi di atas mulai berfungsi.

DrHooverCraft
sumber
0

Anda dapat mencoba kode di bawah ini dalam file Global.asax.

protected void Application_BeginRequest()
    {
        Response.Cache.SetCacheability(HttpCacheability.NoCache);
        Response.Cache.SetExpires(DateTime.UtcNow.AddHours(-1));
        Response.Cache.SetNoStore();
    }
NidhinSPradeep
sumber
-1

UI

<%@ OutPutCache Location="None"%>
<%
    Response.Buffer = true;
    Response.Expires = -1;
    Response.ExpiresAbsolute = System.DateTime.Now.AddSeconds(-1);
    Response.CacheControl = "no-cache";
%>

Latar Belakang

Context.Response.Cache.SetCacheability(HttpCacheability.NoCache); 
Response.Expires = -1;          
Response.Cache.SetNoStore();
Alfa
sumber
1
membutuhkan prosa penjelasan, meskipun secara teknis benar
rmalayter