Êýøèðîâàíèå è ñæàòèå äàííûõ (gzip) â ASP.NET MVC

Èñòî÷íèê: progblog

Êýøèðîâàíèÿ ÿâëÿåòñÿ íåîòúåìëèìîé ÷àñòüþ ëþáîãî êðóïíîãî ñàéòà. Ïîñìîòðèì êàê íà ïðàêòèêå ðåàëèçóåòñÿ êýøèðîâàíèå â ASP.NET MVC.

Ñîçäàäèì ñëåäóþùèé ActionFilter:

  1. using System;   
  2. using System.Web;   
  3. using System.Web.Mvc;   
  4.   
  5. public class CacheFilterAttribute : ActionFilterAttribute   
  6. {   
  7.     /// <summary>   
  8.     /// Gets or sets the cache duration in seconds. The default is 10 seconds.   
  9.     /// </summary>   
  10.     /// <value>The cache duration in seconds.</value>   
  11.     public int Duration   
  12.     {   
  13.         get;   
  14.         set;   
  15.     }   
  16.   
  17.     public CacheFilterAttribute()   
  18.     {   
  19.         Duration = 10;   
  20.     }   
  21.   
  22.     public override void OnActionExecuted(FilterExecutedContext filterContext)   
  23.     {   
  24.         if (Duration <= 0) return;   
  25.   
  26.         HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;   
  27.         TimeSpan cacheDuration = TimeSpan.FromSeconds(Duration);   
  28.   
  29.         cache.SetCacheability(HttpCacheability.Public);   
  30.         cache.SetExpires(DateTime.Now.Add(cacheDuration));   
  31.         cache.SetMaxAge(cacheDuration);   
  32.         cache.AppendCacheExtension("must-revalidate, proxy-revalidate");   
  33.     }   
  34. }  
using System;
using System.Web;
using System.Web.Mvc;

public class CacheFilterAttribute : ActionFilterAttribute
{
    /// <summary>
    /// Gets or sets the cache duration in seconds. The default is 10 seconds.
    /// </summary>
    /// <value>The cache duration in seconds.</value>
    public int Duration
    {
        get;
        set;
    }

    public CacheFilterAttribute()
    {
        Duration = 10;
    }

    public override void OnActionExecuted(FilterExecutedContext filterContext)
    {
        if (Duration <= 0) return;

        HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
        TimeSpan cacheDuration = TimeSpan.FromSeconds(Duration);

        cache.SetCacheability(HttpCacheability.Public);
        cache.SetExpires(DateTime.Now.Add(cacheDuration));
        cache.SetMaxAge(cacheDuration);
        cache.AppendCacheExtension("must-revalidate, proxy-revalidate");
    }
}

Ïðèìåíÿåòñÿ òàêîé ActionFilter î÷åíü ïðîñòî:

  1. [CacheFilter(Duration = 60, Order = 2)]   
  2. [OutputCache(Duration = 60, VaryByParam = "None", Order = 1)]   
  3. public ActionResult Index(string alias)  
[CacheFilter(Duration = 60, Order = 2)]
[OutputCache(Duration = 60, VaryByParam = "None", Order = 1)]
public ActionResult Index(string alias)

Òåïåðü ðåçóëüòàò Index áóäåò çàêýøèðîâàí íà 60 ñåêóíä. OutputCache îòâå÷àåò çà êýøèðîâàíèå ðåçóëüòàòà, à CacheFilter çà çàãîëîâêè âîçâðàùàåìûå ñåðâåðîì. Äëÿ ñæàòèÿ äàííûõ ìåòîäîì gzip, ïîäîéäåò ñëåäóþùèé ActionFilter:

  1. using System.Web;   
  2. using System.Web.Mvc;   
  3.   
  4. public class CompressFilter : ActionFilterAttribute   
  5. {   
  6.     public override void OnActionExecuting(FilterExecutingContext filterContext)   
  7.     {   
  8.         HttpRequestBase request = filterContext.HttpContext.Request;   
  9.   
  10.         string acceptEncoding = request.Headers["Accept-Encoding"];   
  11.   
  12.         if (string.IsNullOrEmpty(acceptEncoding)) return;   
  13.   
  14.         acceptEncoding = acceptEncoding.ToUpperInvariant();   
  15.   
  16.         HttpResponseBase response = filterContext.HttpContext.Response;   
  17.   
  18.         if (acceptEncoding.Contains("GZIP"))   
  19.         {   
  20.             response.AppendHeader("Content-encoding", "gzip");   
  21.             response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);   
  22.         }   
  23.         else if (acceptEncoding.Contains("DEFLATE"))   
  24.         {   
  25.             response.AppendHeader("Content-encoding", "deflate");   
  26.             response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);   
  27.         }   
  28.     }   
  29. }  
using System.Web;
using System.Web.Mvc;

public class CompressFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(FilterExecutingContext filterContext)
    {
        HttpRequestBase request = filterContext.HttpContext.Request;

        string acceptEncoding = request.Headers["Accept-Encoding"];

        if (string.IsNullOrEmpty(acceptEncoding)) return;

        acceptEncoding = acceptEncoding.ToUpperInvariant();

        HttpResponseBase response = filterContext.HttpContext.Response;

        if (acceptEncoding.Contains("GZIP"))
        {
            response.AppendHeader("Content-encoding", "gzip");
            response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
        }
        else if (acceptEncoding.Contains("DEFLATE"))
        {
            response.AppendHeader("Content-encoding", "deflate");
            response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
        }
    }
}

Ïðèìåíÿåòñÿ ñëåäóþùèì îáðàçîì:

  1. [CompressFilter(Order = 3)]   
  2. [CacheFilter(Duration = 60, Order = 2)]   
  3. [OutputCache(Duration = 60, VaryByParam = "None", Order = 1)]   
  4. public ActionResult Index(string alias)  
[CompressFilter(Order = 3)]
[CacheFilter(Duration = 60, Order = 2)]
[OutputCache(Duration = 60, VaryByParam = "None", Order = 1)]
public ActionResult Index(string alias)

Order - ïîðÿäîê ñëåäîâàíèÿ àòòðèáóòîâ. Â ðåçóëüòàòå - îòâåò ñåðâåðà, ñ êýøèðîâàíèåì ("Cache-control: public, must-relative, proxy-revalidate, max-age=30") è ñæàòèåì ("Content-Encoding: gzip"):

 


Ñòðàíèöà ñàéòà http://test.interface.ru
Îðèãèíàë íàõîäèòñÿ ïî àäðåñó http://test.interface.ru/home.asp?artId=22685