我可以在ASP.NET MVC使用[通信pressFilter]不破甜甜圈缓存 [英] Can I use [CompressFilter] in ASP.NET MVC without breaking donut caching

查看:127
本文介绍了我可以在ASP.NET MVC使用[通信pressFilter]不破甜甜圈缓存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想获得[的COM pressFilter ]与甜甜圈缓存工作,并运行到的问题。

什么情况是,整个页面被缓存,而不仅仅是甜甜圈。为的COM pressFilter 我使用的源如下。我改变了这种从原始出处使用 OnResultExecuted 代替 OnActionExecuting(),因为我需要访问的结果,以避免某些缓存子类的ActionResult的类型。

综观实际MVC V1源$ C ​​$ C为 OutputCacheAttribute 看起来它也使用 OnResultExecuted(),但我不认为这一事实直接导致冲突。

我不知道有足够的了解替代缓存是如何工作的理解相当,为什么它的行为方式是这样。我认为这是值得注意的说,虽然,这并不与任何一种破坏显示器的结束。它只是行为就像没有甜甜圈!

它看起来像我将不得不使用某种非法入境插件来处理缓存,这我真的想避免这样做,但它看起来像我需要甜甜圈缓存了。

我其实更感兴趣,现在知道为什么它有这样的效果,但如果可能的解决方案将是巨大的。

 公共类的COM pressFilter:ActionFilterAttribute
{
    公共覆盖无效OnResultExecuted(ResultExecutedContext filterContext)
    {
        HTT prequestBase请求= filterContext.HttpContext.Request;        // EN不code图像!
        如果(filterContext.Result是ImageResult)
        {
            返回;
        }        字符串acceptEncoding = request.Headers [的Accept-Encoding];        如果(string.IsNullOrEmpty(acceptEncoding))回报;        acceptEncoding = acceptEncoding.ToUpperInvariant();        HTT presponseBase响应= filterContext.HttpContext.Response;        如果(acceptEncoding.Contains(GZIP))
        {
            response.AppendHeader(内容编码,gzip的);
            response.Filter =新GZipStream(response.Filter,COM pressionMode.Com preSS);
        }
        否则如果(acceptEncoding.Contains(DEFLATE))
        {
            (内容编码,放气)response.AppendHeader;
            response.Filter =新DeflateStream(response.Filter,COM pressionMode.Com preSS);
        }
    }
}


解决方案

这是一个糟糕的执行在COM pressFilter类的。

请阅读本:<一href=\"http://www.singular.co.nz/blog/archive/2008/07/06/finding-$p$pferred-accept-encoding-header-in-csharp.aspx\">Finding preferred接受在C#编码

我写我自己会服从基于上述文章AcceptEncoding ::

 公共类的COM pressFilter:ActionFilterAttribute
{
    公共覆盖无效OnActionExecuting(ActionExecutingContext filterContext)
    {
        HTT prequestBase请求= filterContext.HttpContext.Request;        字符串[] =支持新的字符串[] {gzip的,放气};        IEnumerable的&LT;串GT; preferredOrder =新AcceptList(request.Headers [接受编码],支持);        字符串preferred = preferredOrder.FirstOrDefault();        HTT presponseBase响应= filterContext.HttpContext.Response;        开关(preferred)
        {
            案的gzip:
                response.AppendHeader(内容编码,gzip的);
                response.Filter =新GZipStream(response.Filter,COM pressionMode.Com preSS);
                打破;            案紧缩:
                response.AppendHeader(内容编码,放气);
                response.Filter =新DeflateStream(response.Filter,COM pressionMode.Com preSS);
                打破;            案身份:
            默认:
                打破;
        }
    }
}公共类AcceptList:IEnumerable的&LT;串GT;
{
    正则表达式解析器=新的正则表达式(@(小于名称&gt; [^;,\\ r \\ n] +)(?:; Q =(小于值&GT; +))?[\\ D]?,RegexOptions。编译);    IEnumerable的&LT;串GT;编码;    公共AcceptList(字符串acceptHeaderValue,IEnumerable的&LT;串GT; supportedEncodings)
    {
        清单&LT; KeyValuePair&LT;字符串,浮动&GT;&GT;接受=新名单&LT; KeyValuePair&LT;字符串,浮动&GT;&GT;();        如果(!string.IsNullOrEmpty(acceptHeaderValue))
        {
            MatchCollection匹配= parser.Matches(acceptHeaderValue);            从比赛比赛v VAR值=
                         其中,v.Success
                         新选择
                         {
                             名称= v.Groups [名。价值,
                             值= v.Groups [值。值
                         };            的foreach(中值VAR值)
            {
                如果(value.Name ==*)
                {
                    的foreach(在supportedEncodings字符串编码)
                    {
                        如果(accepts.Where(一个= GT;!a.Key.ToUpperInvariant()== encoding.ToUpperInvariant())任何())
                        {
                            accepts.Add(新KeyValuePair&LT;字符串,浮动&GT;(编码,1.0F));
                        }
                    }                    继续;
                }                浮所需= 1.0F;
                如果(!string.IsNullOrEmpty(value.Value))
                {
                    float.TryParse(value.Value,出需要);
                }                如果(期望== 0.0)
                {
                    继续;
                }                accepts.Add(新KeyValuePair&LT;字符串,浮动&GT;(value.Name,需要的话));
            }
        }        this.encodings =从在接受
                         其中,supportedEncodings.Where。(SE = GT; se.ToUpperInvariant()== a.Key.ToUpperInvariant())的任何()|| a.Key.ToUpperInvariant()==身份
                         排序依据a.value中降
                         选择a.Key;
    }    IEnumerator的&LT;串GT; IEnumerable的&LT;串GT; .GetEnumerator()
    {
        返回this.encodings.GetEnumerator();
    }    的IEnumerator IEnumerable.GetEnumerator()
    {
        返回((IEnumerable的)this.encodings).GetEnumerator();
    }
}

I am trying to get [CompressFilter] working with donut caching and running into issues.

What happens is that the whole page gets cached and not just the donut. The source for the CompressFilter I am using is below. I changed this from the original source to use OnResultExecuted instead of OnActionExecuting() because I needed access to the type of the result to avoid caching certain ActionResult subclasses.

Looking at the actual MVC v1 source code for OutputCacheAttribute it looks like it also is using OnResultExecuted(), but I dont think that fact directly is causing the conflict.

I don't know enough about how substitution caching works to understand quite why it behaves the way it does. I think it is notable to say though that this does not end up with any kind of corrupted display. It just behaves like there is no donut!

Its looking like I will have to use some kind of IIs 'plug-in' to handle caching, which I really wanted to avoid having to do, but its looking like I need donut caching too.

I'm actually more interested right now to know why it has this effect, but a solution if possible would be great too.

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

        // dont encode images!
        if (filterContext.Result is ImageResult)
        {
            return;
        }

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

解决方案

That is a bad implementation of the CompressFilter class.

Please read this: Finding Preferred Accept Encoding in C#

I have written my own that will obey the AcceptEncoding based on the above article::

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

        string[] supported = new string[] { "gzip", "deflate" };

        IEnumerable<string> preferredOrder = new AcceptList(request.Headers["Accept-Encoding"], supported);

        string preferred = preferredOrder.FirstOrDefault();

        HttpResponseBase response = filterContext.HttpContext.Response;

        switch (preferred)
        {
            case "gzip":
                response.AppendHeader("Content-Encoding", "gzip");
                response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
                break;

            case "deflate":
                response.AppendHeader("Content-Encoding", "deflate");
                response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
                break;

            case "identity":
            default:
                break;
        }
    }
}

public class AcceptList : IEnumerable<string>
{
    Regex parser = new Regex(@"(?<name>[^;,\r\n]+)(?:;q=(?<value>[\d.]+))?", RegexOptions.Compiled);

    IEnumerable<string> encodings;

    public AcceptList(string acceptHeaderValue, IEnumerable<string> supportedEncodings)
    {
        List<KeyValuePair<string, float>> accepts = new List<KeyValuePair<string, float>>();

        if (!string.IsNullOrEmpty(acceptHeaderValue))
        {
            MatchCollection matches = parser.Matches(acceptHeaderValue);

            var values = from Match v in matches
                         where v.Success
                         select new
                         {
                             Name = v.Groups["name"].Value,
                             Value = v.Groups["value"].Value
                         };

            foreach (var value in values)
            {
                if (value.Name == "*")
                {
                    foreach (string encoding in supportedEncodings)
                    {
                        if (!accepts.Where(a => a.Key.ToUpperInvariant() == encoding.ToUpperInvariant()).Any())
                        {
                            accepts.Add(new KeyValuePair<string, float>(encoding, 1.0f));
                        }
                    }

                    continue;
                }

                float desired = 1.0f;
                if (!string.IsNullOrEmpty(value.Value))
                {
                    float.TryParse(value.Value, out desired);
                }

                if (desired == 0.0f)
                {
                    continue;
                }

                accepts.Add(new KeyValuePair<string, float>(value.Name, desired));
            }
        }

        this.encodings = from a in accepts
                         where supportedEncodings.Where(se => se.ToUpperInvariant() == a.Key.ToUpperInvariant()).Any() || a.Key.ToUpperInvariant() == "IDENTITY"
                         orderby a.Value descending
                         select a.Key;
    }

    IEnumerator<string> IEnumerable<string>.GetEnumerator()
    {
        return this.encodings.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return ((IEnumerable)this.encodings).GetEnumerator();
    }
}

这篇关于我可以在ASP.NET MVC使用[通信pressFilter]不破甜甜圈缓存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆