특성을 사용하여 특정 작업에 대해 ASP.NET MVC에서 캐싱 방지


197

ASP.NET MVC 3 응용 프로그램이 있습니다. 이 애플리케이션은 jQuery를 통해 레코드를 요청합니다. jQuery는 JSON 형식으로 결과를 반환하는 컨트롤러 작업을 다시 호출합니다. 나는 이것을 증명할 수 없었지만 내 데이터가 캐시 될지도 모른다.

캐싱을 특정 작업에만 적용하고 모든 작업에 적용하려는 것은 아닙니다.

데이터가 캐시되지 않도록 조치를 취할 수있는 속성이 있습니까? 그렇지 않은 경우 캐시 된 세트 대신 브라우저가 매번 새로운 레코드 세트를 받도록하려면 어떻게해야합니까?


1
당신이 캐시되는 뭔가를 추측하는 경우에, 여기 당신이 캐시 제어 메커니즘을 읽어 것이 좋습니다 w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9

답변:


304

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]. 또는 우리가 여기에있는 것처럼 컨트롤러를 상속받은 기본 클래스의 클래스에 속성을 넣을 수 있습니다.

[NoCache]
public class ControllerBase : Controller, IControllerBase

전체 컨트롤러를 장식하는 대신 캐시 할 수없는 경우이 속성을 사용하여 일부 작업을 장식 할 수도 있습니다.

클래스 또는 액션이 NoCache브라우저에서 렌더링 될 때 클래스가 없거나 작동하지 않는지 확인하려면 변경 사항을 컴파일 한 후 브라우저에서 "하드 리프레시"(Ctrl + F5)를 수행해야합니다. 그렇게 할 때까지 브라우저는 이전에 캐시 된 버전을 유지하며 "일반 새로 고침"(F5)으로 새로 고치지 않습니다.


1
위의 솔루션에서 모든 것을 시도했지만 작동하지 않습니다.
Obi Wan

9
cache : false는 jQuery를 쿼리 문자열에 고정시켜 브라우저가 요청을 다른 무언가에 대한 것이라고 생각하도록 브라우저를 "속이기"만한다는 것을 이해하고 있습니다 (jQuery 전문가가 아닙니다). 이론적으로 이것은 브라우저가 여전히 결과를 캐시하고 캐시 된 결과를 사용하지 않음을 의미합니다. 응답 헤더를 통한 캐싱을 비활성화하려면 클라이언트에서보다 효율적이어야합니다.
Josh

2
작업 수준이 아닌 컨트롤러 수준에서만 작동했습니다.
Ramesh

3
나는 공식적인 ASP.NET 패키지에 그러한 속성을 포함시켜
찬성 할 것이다

1
스펙의 섹션 인 @ Frédéric은 캐시가 비 저장 컨텐츠를 캐시 할 수 없다고 말합니다. "비 저장"응답 지시문은 캐시가 즉각적인 요청 또는 응답의 일부를 저장해서는 안됨을 나타냅니다.
kristianp

258

내장 캐시 속성을 사용하여 캐싱을 방지 할 수 있습니다.

.net Framework의 경우 : [OutputCache(NoStore = true, Duration = 0)]

.net Core의 경우 : [ResponseCache(NoStore = true, Duration = 0)]

브라우저가 강제로 캐싱을 사용하지 않도록 설정하는 것은 불가능합니다. 당신이 할 수있는 최선의 방법은 대부분의 브라우저가 일반적으로 헤더 나 메타 태그의 형태로 존중할 것을 제안하는 것입니다. 이 데코레이터 속성은 서버 캐싱을 비활성화하고이 헤더를 추가합니다 Cache-Control: public, no-store, max-age=0. 메타 태그를 추가하지 않습니다. 원하는 경우 뷰에서 수동으로 추가 할 수 있습니다.

또한 JQuery 및 기타 클라이언트 프레임 워크는 타임 스탬프 또는 GUID와 같이 URL에 항목을 추가하여 브라우저의 캐시 된 버전의 리소스를 사용하지 않도록 브라우저를 속이려고 시도합니다. 이것은 브라우저가 리소스를 다시 요청하도록하는 데 효과적이지만 실제로 캐싱을 막지는 않습니다.

마지막 메모. 서버와 클라이언트간에 리소스를 캐시 할 수도 있습니다. ISP, 프록시 및 기타 네트워크 장치도 리소스를 캐시하며 실제 리소스를 보지 않고 내부 규칙을 사용하는 경우가 많습니다. 이것에 대해 할 수있는 일은 많지 않습니다. 좋은 소식은 일반적으로 초 또는 분과 같은 짧은 시간 동안 캐시한다는 것입니다.


3
나는 이것이 문제를 완전히 해결하지 못한다고 생각합니다. 이렇게하면 ASP.NET 캐싱은 비활성화되지만 브라우저 캐싱은 비활성화되지 않습니다.
Rosdi Kasim

22
브라우저가 캐싱을 사용하지 않도록 강제 할 수는 없습니다. 당신이 할 수있는 최선의 방법은 대부분의 브라우저가 일반적으로 헤더 나 메타 태그의 형태로 존중할 것을 제안하는 것입니다. 이 데코레이터 속성은 .NET 서버 캐싱을 비활성화하고 헤더도 추가합니다 Cache-Control:public, no-store, max-age=0. 메타 태그를 추가하지 않습니다. 원하는 경우 뷰에서 수동으로 추가 할 수 있습니다.
Jaguir

1
나는 왜 당신이 사용 NoStore = true하고 Duration = 0(내가 성공적으로 사용했는지) 이해할 수 있지만 VaryByParam = "None"다른 두 옵션이 매개 변수에 관계없이 모든 요청에 ​​영향을 미치면 어떤 추가 효과가 있습니까?
사라 코딩

나는 그것이 MVC에서 필요하다고 생각하지 않으며, 단지 명시 적이었습니다. ASP.NET 웹 양식 및 사용자 컨트롤에서이 특성 또는 VaryByControl 특성이 필요하다는 것을 기억합니다.
Jaguir

1
ASP.NET Core 사용 : '[ResponseCache (NoStore = true, Duration = 0)]'
Jeff

48

필요한 것은 다음과 같습니다.

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

또는 전체 컨트롤러에 대해 비활성화하려면 :

[OutputCache(Duration=0)]
public class MyController

여기 주석에 대한 토론에도 불구하고 브라우저 캐싱을 비활성화하기에 충분합니다. 그러면 ASP.Net이 브라우저에 문서가 즉시 만료되었음을 알리는 응답 헤더를 생성합니다.

OutputCache Duration = 0 응답 헤더 : max-age = 0, s-maxage = 0


6
컨트롤러 작업에서 기간 = 0 만 사용하여 뒤로 버튼을 클릭하면 IE8은 여전히 ​​페이지의 캐시 된 버전을 렌더링합니다. Duration = 0과 함께 NoStore = true를 사용하면 (Jared의 답변 참조) 내 경우의 동작이 수정되었습니다.
Keith Ketterer

3
이 설정의 다소 호기심 행동이 Cache-Controlpublic
ta.speot.is

max-age=0'캐시 비활성화'를 의미하지 않았습니다. 이것은 응답 내용이 즉시 오래된 것으로 간주된다는 것을 의미 하지만 캐시는이를 캐시 할 수 있습니다. 브라우저는 사용하기 전에 캐시 된 오래된 컨텐츠의 최신 성을 검증해야하지만 추가 지시문 must-revalidate을 지정 하지 않으면 필수가 아닙니다 .
프레데릭

14

컨트롤러 조치에서 헤더에 다음 행을 추가하십시오.

    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.

5

다음 NoCache은 Chris Moschini의 답변 정보를 사용하여 단순화 한 mattytommo가 제안한 속성입니다.

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

어떤 이유로 MVC 3에서는 지속 시간을 0으로 설정할 수 없습니다. 이러한 주석을 추가해야합니다. 해결 방법에 감사드립니다!
micahhoover

max-age=0'캐시 비활성화'를 의미하지 않았습니다. 이것은 응답 내용이 즉시 오래된 것으로 간주된다는 것을 의미 하지만 캐시는이를 캐시 할 수 있습니다. 브라우저는 사용하기 전에 캐시 된 오래된 컨텐츠의 최신 성을 검증해야하지만 추가 지시문 must-revalidate을 지정 하지 않으면 필수가 아닙니다 .
프레데릭

완전성을 위해 최소한의 적절한 지시문은입니다 no-cache. 캐싱은 허용하지만 사용 전에 원본 서버에서 다시 확인해야합니다. 재확인 된 캐싱을 피하려면와 no-store함께 추가해야합니다 no-cache. ( no-store휘발성 캐시가로 표시된 콘텐츠를 캐시 할 수 있기 때문에 단독으로는 잘못됩니다 no-store.)
Frédéric

4

MVC6 ( DNX )의 경우System.Web.OutputCacheAttribute

참고 : NoStore지속 시간 매개 변수 를 설정하면 고려되지 않습니다. 첫 등록의 초기 기간을 설정하고이를 사용자 정의 속성으로 대체 할 수 있습니다.

그러나 우리는 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());
    }

1

MVC의 출력 캐싱

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

또는
[OutputCache (NoStore = true, Duration = 0, VaryByParam = "없음")]


이미 이것을 사용하여 제안하는 수많은 답변에 대한 다른 의견 ( 1 , 2 , 3 )을 참조하십시오 . 두 번째 줄이 잘못되어 일부 브라우저에서 문제가 발생합니다.
Frédéric


0

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. 일단 당신이 그 자리에 있으면 당신은 내 또는 다른 수준 의 다른 OutputCache지시문을 적용하여 전역 필터를 재정의 할 수 있다는 것을 이해 합니다. 일반 컨트롤러의 경우ControllerView
[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 = "*")]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.