ASP.NET MVC — сжатие + кэширование

Я видел несколько вариантов добавления сжатия GZIP/DEFLATE к выходным данным ASP.Net MVC, но все они, кажется, применяют сжатие на лету.. таким образом, не используют кэширование сжатого содержимого.

Любые решения для включения кэширования вывода сжатой страницы? Предпочтительно в коде, чтобы код MVC мог проверить, изменилась ли страница, и отправить предварительно сжатый кэшированный контент, если нет.

Этот вопрос действительно может относиться и к обычному asp.net.


person Brady Moritz    schedule 30.09.2010    source источник
comment
Вы имеете в виду кэширование сжатого ответа в System.Web.Cache?   -  person bzlm    schedule 01.10.2010
comment
Возможно, или любые другие решения, которые достигают этого.   -  person Brady Moritz    schedule 05.10.2010
comment
Ни один из ответов на данный момент, хотя и информативен в других отношениях, похоже, не касается сжатия содержимого в кеше по сравнению с содержимым, отправляемым из кеша. Вспоминая презентацию UG о кэшировании ASP.NET, не думали ли вы о написании собственного поставщика кэша?   -  person J0e3gan    schedule 08.05.2013
comment
Ссылка на это как на возможное решение, но я его не тестировал: weblogs.asp.net/rashid/archive/2008/03/28/   -  person AaronLS    schedule 08.05.2013


Ответы (7)


Используйте параметры кэширования с использованием атрибутов (для MVC) и не думайте о сжатии, поскольку IIS/IISExpress автоматически сжимает вывод, если вы его включаете.

как это работает, mvc не позволяет кэшировать отдельные фрагменты или части вывода (частичное кэширование контента). если вы хотите этого, рассмотрите возможность использования такого сервиса, как CloudFlare (есть ли другой, подобный CF?). он автоматически кэширует ваши выходные данные и фрагменты ваших выходных данных, а также обеспечивает множество других улучшений производительности и безопасности, и все это без изменения вашего кода.

Если это не вариант для вас, вы все равно можете использовать IISpeed ​​(это IIS-порт Google mod_pagespeed). Он предоставляет некоторые интересные настройки, такие как удаление пробелов, встроенное сжатие css и js, слияние файлов js и многие другие.

И CF, и IISpeed ​​не заботятся о том, как построен ваш сайт, они работают на уровне http/html, поэтому они оба работают с файлами MVC, Classic ASP.NET, php или даже с необработанными html.

person Erdogan Kurtur    schedule 07.05.2013
comment
и последнее, будьте осторожны при использовании Vary, так как это может нарушить поведение кэширования некоторых старых версий IE. - person Erdogan Kurtur; 07.05.2013

Вы можете создать атрибут, например

public class EnableCompressionAttribute : ActionFilterAttribute  
{  
    const CompressionMode Compress = CompressionMode.Compress;  

    public override void OnActionExecuting(ActionExecutingContext filterContext)  
    {  
        HttpRequestBase request = filterContext.HttpContext.Request;  
        HttpResponseBase response = filterContext.HttpContext.Response;  
        string acceptEncoding = request.Headers["Accept-Encoding"];  
        if (acceptEncoding == null)  
            return;  
        else if (acceptEncoding.ToLower().Contains("gzip"))  
        {  
            response.Filter = new GZipStream(response.Filter, Compress);  
            response.AppendHeader("Content-Encoding", "gzip");  
        }  
        else if (acceptEncoding.ToLower().Contains("deflate"))  
        {  
            response.Filter = new DeflateStream(response.Filter, Compress);  
            response.AppendHeader("Content-Encoding", "deflate");  
        }  
    }  
} 

Добавьте запись в Global.asax.cs.

        public static void RegisterGlobalFilters(GlobalFilterCollection filters)  
        {  
            filters.Add(new EnableCompressionAttribute());  
        }  

Затем вы можете использовать этот атрибут как:

    [EnableCompression]
    public ActionResult WithCompression()
    {
        ViewBag.Content = "Compressed";
        return View("Index");
    }

Вы можете скачать рабочий пример с Github: https://github.com/ctesene/TestCompressionActionFilter

person Pranav Singh    schedule 08.05.2013
comment
Это поддерживает кеширование сжатой версии страницы вместо повторного сжатия каждого запроса? - person AaronLS; 08.05.2013
comment
Да, атрибут применяется к методу контроллера, поэтому ответ сжимается со стороны сервера. Я не понял, что вы имеете в виду под повторным сжатием запроса. - person Pranav Singh; 12.05.2013
comment
Независимо от того, происходит ли сжатие при каждом запросе и, следовательно, неэффективно: Полученный запрос->Получить кэшированную страницу->Сжать кэшированную страницу, а не просто Полученный запрос->Получить кэшированную страницу (которая уже сжата). - person AaronLS; 12.05.2013
comment
Я до сих пор не понимаю реальной потребности или варианта использования. Если запрос кэшируется, сервер отвечает кодом состояния 304 и не отправляет тело документа клиенту, это означает, что сервер не обращается к кэшированному ресурсу, пока он не будет изменен на сервере при выполнении запроса. Сжатие выполняется по ответу, а не по запросу. какую актуальную проблему вы хотите решить??? - person Pranav Singh; 12.05.2013
comment
Если страница кэшируется, она должна кэшироваться в сжатом виде. Бесполезно повторно сжимать один и тот же контент при каждом запросе. - person AaronLS; 12.05.2013
comment
Я не говорю о кэшировании на стороне клиента, я говорю о кэшировании на стороне сервера. - person AaronLS; 12.05.2013

Этот ссылка кажется довольно близкой к тому, что вам нужно. Он кэширует сжатые динамически сгенерированные страницы. Хотя в примере используются веб-формы, его можно адаптировать к MVC с помощью атрибута OutputCache.

[OutputCache(Duration = 600, VaryByParam = "*", VaryByContentEncoding="gzip;deflate")]
person rivarolle    schedule 08.05.2013

Вы можете создать атрибут кэша:

public class CacheAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;

        if (Enabled)
        {
            cache.SetExpires(System.DateTime.Now.AddDays(30));
        }
        else
        {
            cache.SetCacheability(HttpCacheability.NoCache);
            cache.SetNoStore();
        }
    }

    public bool Enabled { get; set; }

    public CacheAttribute()
    {
        Enabled = true;
    }
}
person Jonathan Bates    schedule 16.10.2010
comment
Как это обрабатывает сжатие? - person Brady Moritz; 29.08.2012
comment
Извините, неправильно понял эту часть вопроса. Вы можете проверить это weblogs.asp.net/rashid/archive/2008/03/28/. Он по-прежнему выполняет сжатие «на лету», но основанный на атрибутах дает вам больше возможностей выбора, чем решение для всего сервера. - person Jonathan Bates; 29.08.2012

Подробнее см. в разделе Повышение производительности с помощью кэширования вывода. введение по теме. Основная рекомендация — использовать [OutputCache. ] в атрибуте Действия, для которого должно выполняться кэширование. применяться.

person Yaakov Ellis    schedule 17.10.2010
comment
Не видите упоминания о сжатии? - person Brady Moritz; 19.10.2010

использовать пространство имен

using System.Web.Mvc;

using System.IO.Compression;

создайте ClassName.cs в вашем основном проекте

public class CompressAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {

            var _encodingsAccepted = filterContext.HttpContext.Request.Headers["Accept-Encoding"];
            if (string.IsNullOrEmpty(_encodingsAccepted)) return;

            _encodingsAccepted = _encodingsAccepted.ToLowerInvariant();
            var _response = filterContext.HttpContext.Response;
if(_response.Filter == null) return;
            if (_encodingsAccepted.Contains("deflate"))
            {
                _response.AppendHeader("Content-encoding", "deflate");
                _response.Filter = new DeflateStream(_response.Filter, CompressionMode.Compress);
            }
            else if (_encodingsAccepted.Contains("gzip"))
            {
                _response.AppendHeader("Content-encoding", "gzip");
                _response.Filter = new GZipStream(_response.Filter, CompressionMode.Compress);
            }
        }
    }

--- и добавьте в global.asax.cs

GlobalFilters.Filters.Add(new CompressAttribute());
person Ganesh Kumar Pandey    schedule 09.06.2021

person    schedule
comment
Любая документация по этому поводу? выглядит именно то, что я после. - person Brady Moritz; 19.10.2010
comment
Я хотел бы увидеть больше информации об этом, я не смог заставить работать атрибут Compress - person Brady Moritz; 29.08.2012
comment
@BradyMoritz, возможно, атрибут Compress ссылается на что-то вроде следующего stackoverflow.com/a/3802424/459102 - person Aaron Hudon; 09.04.2019