Ошибка gzip / deflate при возникновении исключения - PullRequest
4 голосов
/ 14 февраля 2012

У меня есть интересная проблема с gzip / deflate ActionFilterAttribute в ASP.NET MVC 3. Если в моем приложении возникает исключение, вместо получения YSOD я получаю полную страницу, как показано ниже.

��� I�%&/m�{J�J��t�� $ ؐ @ ������� iG #) � * ��eVe] f @ � 흼 �� {���� {����; �N'\ fdlJɞ ~ |?!? "Еу) = y6hZ2kjuU? � + _x-��: � ����T����W�v� <[���� ~ 2�g�2���? �ʋ�y�hY Ջ������� t� _N���M�l������� {��, ���Xn���Q�} �������� * g�������7�� ~� <code>�j'u>K�{_��IW4�>�U�w�|=-fYzR-�������|��<&�o�Z()*�S!U��k�g�������j��.����b}��ή�9X/��J�Iն��Q���z�i�n�-g٤���ݞ��Y^����H�8/��k�}]7�ǜ@�{|�g��wUd�O����죫y���o-�����ݏ��� �ZHv,�d]��١�>o3�=�3x�7MN�����������Ow���w�.o��φ�<؟M����;���vg���A>��䋟{YޟN�����Φ�$p>q����/�!�y��9�2��two������?������Ӈ���n�9�r�^����!������{���ag�?\1*c�?!�bي? ���xI����u�f? �� {'�����P $ �v & = # s�l�_0����΃�w�ss����廌 ⼽ г! {к \ 7М (o4 ߛ >> @ "|| vy5В ꆦ RJSK & ߛ р <Сt��1�hOI���y {j�] i���˷���� �D'p <� $ <code>,�'M��r{-�}��CF�؛�����A��9��[�½�� �! 2�� �:��!��{�t�;�߇'y��M��+�M^#x^\����Q��jM�l��?(�]� ��IZ�ݟ[����+4#"�:�X����m�������dv>������iL�̀I |�fL�TU��ho�� �{L��_t��5�o?���h�O�UY]#�u�[���G�ޞ�=���;��8���~����d�8k�w�����yw� ���� ֺ�� Nx��A��� [��xMo�� ۣ f��� / �Og�; y ~ ����!

Если я удаляю свой CompressAttribute, он работает как положено (я вижу YSOD). Так что кажетсячто моя обработка исключений (ElmahHandleErrorAttribute из Elmah.Contrib.Mvc) останавливает остальные фильтры, включая CompressAttribute, и ответ не дефлируется.

Соответствующий код:

public sealed class CompressAttribute : ActionFilterAttribute
{
    private const string _acceptEncodingHeader = "Accept-Encoding";
    private const string _contentEncodingHeader = "Content-Encoding";

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

        string acceptEncoding = request.Headers[_acceptEncodingHeader];

        if (String.IsNullOrEmpty(acceptEncoding))
        {
            return;
        }

        acceptEncoding = acceptEncoding.ToUpperInvariant();

        HttpResponseBase response = filterContext.HttpContext.Response;

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

Фильтррегистрация:

GlobalFilterCollection filters = GlobalFilters.Filters;
filters.Add(new ElmahHandleErrorAttribute(), 999); // Elmah.Contrib.Mvc
filters.Add(new CompressAttribute());

Как я могу убедиться, что ответ доступен для чтения даже при возникновении исключений?

Ответы [ 3 ]

8 голосов
/ 18 февраля 2012

Вот немного лучший ответ, вдохновленный ответом от iaimtomisbeve. Это позволяет хранить весь код в одном классе.

Добавьте следующее переопределение в ваш класс CompressAttribute:

public override void OnResultExecuted(ResultExecutedContext filterContext)
{
    if (filterContext.Exception != null)
    {
        filterContext.HttpContext.Response.Filter = null;
    }
}
6 голосов
/ 14 февраля 2012

Это связано с тем, что при возникновении ошибки в вашем приложении ASP.Net удаляет все ваши пользовательские заголовки, но фильтр все еще там. Вы можете сбросить фильтр при ошибке приложения, которая должна устранить проблему.

protected void Application_Error(object sender, EventArgs e)
{
        Response.Filter = null;
}
0 голосов
/ 31 марта 2014

Погуглил интернет для решения той же проблемы и оказался здесь.Довольно полезные ответы вдохновили меня на реализацию моей собственной версии, упомянутой ниже:

static public void EnableGzip()
{
    var c = HttpContext.Current;
    string a = c.Request.Headers["Accept-Encoding"];
    if (String.IsNullOrEmpty(a))
        return;
    if (!a.Contains("gzip"))
        return;
    c.Response.Filter = new GZipStream(
        c.Response.Filter, CompressionMode.Compress);
    c.Response.AppendHeader("Content-Encoding", "gzip");
    EventHandler errorHandler = null;
    errorHandler = delegate
    {
        c.Response.Filter = null;
        c.ApplicationInstance.Error -= errorHandler;
    };
    c.ApplicationInstance.Error += errorHandler;
}

Пожалуйста, не стесняйтесь критиковать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...