I have an interesting issue with a gzip/deflate ActionFilterAttribute in ASP.NET MVC 3. If an exception is thrown by my application, instead of getting a YSOD, I get a full page of gibberish as seen below.
���
I�%&/m�{J�J��t��$ؐ@�������iG#)�*��eVe]f@�흼��{����{����;�N’���?\fdl��J�ɞ!���?~|?”��Ey�’)=��y6�����h����Z��2k�j���uU?�+_x-��:�
�T����W�v�<[����~2�g�2���?�ʋ�y�hYՋ�������t�
_N���M�l�������{��,���Xn���Q�}��������*g�������7�� ~��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-�����ݏ���?���xI����u�f
�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ي
?��{‘�����P$�v&=#s�l�_0�����w�ss�����廌��⼽�r���!��{k\7M���(o������4�ߛ>�>�@”|�|v���y5�����QꆦR���JSK�&�����ߛ�p������v<�C��t��1�hOI���y{j�]i���˷����
�D’p<�$,�'M��r{-�}��CF�؛�����A��9��[�½�� �!����ֺ��Nx��A���[��xMo��ۣf���/�Og�;y~����!
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�
If I remove my CompressAttribute, it works as expected (I see the YSOD). So it seems that my exception handling (ElmahHandleErrorAttribute from Elmah.Contrib.Mvc) halts the remaining filters, including CompressAttribute and the response is not deflated.
Relevant code:
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);
}
}
}
Filter registration:
GlobalFilterCollection filters = GlobalFilters.Filters;
filters.Add(new ElmahHandleErrorAttribute(), 999); // Elmah.Contrib.Mvc
filters.Add(new CompressAttribute());
How can I make sure that the response is readable even when exceptions are thrown?
This is because when there is an error in your application ASP.Net removes all your custom headers but the filter is still there. You could reset the filter on application error that should make the problem go away.