【问题标题】:ASP.NET MVC - compression + cachingASP.NET MVC - 压缩 + 缓存
【发布时间】:2023-03-14 00:00:01
【问题描述】:

我已经看到了许多将 GZIP/DEFLATE 压缩添加到 ASP.Net MVC 输出的选项,但它们似乎都是即时应用压缩..因此不利用缓存压缩内容。

任何启用缓存压缩页面输出的解决方案?最好在代码中,以便 MVC 代码可以检查页面是否已更改,如果没有更改,则将预压缩的缓存内容发送出去。

这个问题确实也适用于常规的 asp.net。

【问题讨论】:

  • 你的意思是像在System.Web.Cache中缓存压缩响应?
  • 也许,或任何其他解决方案可以做到这一点。
  • 到目前为止,没有一个答案,虽然在其他方面提供了丰富的信息,但似乎解决了压缩内容 in 缓存与内容 服务于 缓存.回想关于 ASP.NET 缓存的 UG 演示,您是否考虑过编写自定义缓存提供程序?
  • 将此链接为可能的解决方案,但我尚未对其进行测试:weblogs.asp.net/rashid/archive/2008/03/28/…

标签: asp.net asp.net-mvc asp.net-mvc-2 compression http-compression


【解决方案1】:
[Compress]
[OutputCache(Duration = 600, VaryByParam = "*", VaryByContentEncoding="gzip;deflate")]
public ActionResult Index()
{
    return View();
}

【讨论】:

  • 有这方面的文档吗?看起来正是我所追求的。
  • 我很想看到这方面的更多信息,我无法使“压缩”属性工作
  • @BradyMoritz Compress 属性可能被引用到类似于以下stackoverflow.com/a/3802424/459102
【解决方案2】:

你可以创建一个缓存属性:

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

【讨论】:

  • 这是如何处理压缩的?
  • 对不起,误解了问题的那一部分。您可以查看weblogs.asp.net/rashid/archive/2008/03/28/…。它仍在进行动态压缩,但它基于属性为您提供了比服务器范围解决方案更多的选择选项。
【解决方案3】:

有关该主题的完整介绍,请参阅Improving performance with output caching。主要建议是使用the Action 上的[OutputCache] 属性,应该对其应用缓存。

【讨论】:

  • 没有提到压缩?
【解决方案4】:

使用属性(对于 MVC)使用缓存选项,并且不要考虑压缩,因为 IIS/IISExpress 如果您启用它会自动压缩您的输出。

它的工作方式是,mvc 不支持缓存单个片段或部分输出(部分内容缓存)。如果你想要这个,考虑使用像 CloudFlare 这样的服务(还有其他像 CF 的吗?)。它会自动缓存您的输出并缓存您的输出片段,并提供许多其他性能和安全改进,所有这些都无需更改您的代码。

如果这不适合您,那么您仍然可以使用 IISpeed(它是 Google 的 mod_pagespeed 的 IIS 端口)。它提供了一些有趣的设置,如空格删除、内联 css 和 js 压缩、js 文件合并等等。

CF 和 IISpeed 都不关心您的网站是如何构建的,它们在 http/html 级别上运行,因此它们都适用于 MVC、Classic ASP.NET、php 甚至原始 html 文件。

【讨论】:

  • 最后一个,使用Vary时要小心,因为它可能会破坏某些旧IE版本的缓存行为。
【解决方案5】:

你可以创建一个属性像

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

【讨论】:

  • 这支持缓存页面的压缩版本,而不是重新压缩每个请求?
  • 是的,该属性应用于控制器方法,因此“响应”是从服务器端压缩的。我不明白“重新压缩请求”是什么意思。
  • 压缩是否发生在每个请求上,因此效率低下:“请求接收->检索缓存页面->压缩缓存页面”,而不是“请求接收->检索缓存页面(即已压缩)”。
  • 我仍然没有得到实际需求或用例。如果请求被缓存,服务器会以 304 状态码响应并且不会将文档正文发送给客户端,这意味着服务器没有命中来获取缓存的资源,直到在发出请求时在服务器上更改它。压缩是根据响应而不是根据请求进行的。您想要解决的实际问题是什么???
  • 如果页面被缓存,它应该以压缩形式被缓存。在每个请求上重新压缩相同的内容是很浪费的。
【解决方案6】:

这个link 似乎非常接近您的要求。它缓存压缩的动态生成的页面。虽然示例使用了 Web 表单,但可以通过使用 OutputCache 属性来适应 MVC

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

【讨论】:

    【解决方案7】:

    使用命名空间

    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());
    

    【讨论】:

      猜你喜欢
      • 2011-06-24
      • 2021-07-28
      • 1970-01-01
      • 2010-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多