MVC 3 compression filter causing garbled output

前端 未结 4 1687
囚心锁ツ
囚心锁ツ 2020-12-28 08:24

So, I have a custom attribute called CompressAttribute which is set up as a global filter in global.asax. It uses reflection to examine the return type of the current action

相关标签:
4条回答
  • 2020-12-28 09:04

    I had this same problem in asp.net mvc 1.0 browsing for a page that had a RenderAction inside (from the futures assembly). Apparently the problem was that the response was being encoded twice. I had to create an action filter for this child actions so that a flag is set in the DataTokens collection of the RouteData. Then I had to modify the compress filter so that it returned in case the flag was set. I also had to deal with the execution order of the filters. Maybe this can help, verify if the compress filter is being called more than one time when an error page is raised.

    0 讨论(0)
  • 2020-12-28 09:10

    You can also solve this by attaching to OnResultExecuting instead of OnActionExecuting. This gives a few advantages

    1. You can discover the action result without resorting to reflection.
    2. OnResultExecuting won't execute in exceptional cases (MVC will invoke OnException but not OnResultExecuting)

    Something like this:

    public sealed class MyAttribute  : ActionFilterAttribute
    {
        /// <summary>
        /// Called by MVC just before the result (typically a view) is executing.
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            var result = filterContext.Result;
            if (result is ViewResultBase)
            {
                var response = filterContext.HttpContext.Response;
    
                // Check your request parameters and attach filter.
            }
        }
    
    0 讨论(0)
  • 2020-12-28 09:18

    Ok so I was able to resolve this by clearing the Response.Filter property in the Application_Error event:

    public void Application_Error(object sender, EventArgs e)
    {
        Response.Filter.Dispose();
    }
    

    Wondering if there's a more correct way to do it though...

    0 讨论(0)
  • 2020-12-28 09:25

    The accepted answer won't work if anything has been already written to the output.

    Instead of disposing the filter you can make sure the headers are being persisted in place:

     protected void Application_PreSendRequestHeaders()
    {
        // ensure that if GZip/Deflate Encoding is applied that headers are set
        // also works when error occurs if filters are still active
        HttpResponse response = HttpContext.Current.Response;
        if (response.Filter is GZipStream && response.Headers["Content-encoding"] != "gzip")
            response.AppendHeader("Content-encoding", "gzip");
        else if (response.Filter is DeflateStream && response.Headers["Content-encoding"] != "deflate")
            response.AppendHeader("Content-encoding", "deflate");
    }
    
    0 讨论(0)
提交回复
热议问题