2012年3月26日月曜日

ResponseFilter & Content-Encoding header, cleared by WriteExceptionJsonString

Hi There,

I have a ResponseFilter adding HTTP compression to my .aspx, ashx, and now .asmx requests, similar to http://blog.madskristensen.dk/post/HTTP-compression-in-ASPNET-20.aspx.

I've just starting using it to compress the web services in a project, which has worked great reducing the traffic immensely. To do this, I've added a response filter to the Response object, and set the "Content-Encoding" header to "gzip". Works great for normal pages and "MyService.asmx/js" requests as well.

Normally, when an exception is thrown inside a web service, the exception is serialised, passed along to the client, and handled by the error callback in javascript code. No worries there.

The error handling stopped working after added the compression as a response filter to the .asmx/js requests. It turns out that the method handles the error "WriteExceptionJsonString" found in "System.Web.Script.Services.RestHandler" clears the response headers before it serialises the exception. This isn't too bad in itself, but the response filter is still in place, so the gzip compression is still used, but now the client consuming the request doesn't know it needs decoding and a javascript error then occurs "result has no properties"

line 4860, result = new Sys.Net.WebServiceError(false, result.Message, result.StackTrace, result.ExceptionType);

Is there a way around this, while still allowing the compression? Or is this some kind behavioral bug in the underlying MS AJAX Rest handler? If theSystem.Web.Script.Services.RestHandler clears the headers... and the content... should it also remove any response filters?

I had a brain wave shortly after posting the previous message.

The HTTP Module I am using did all the Response.Filter setup in the PreRequestHandlerExecute event. That included the Response.AppendHeader("Content-Encoding", "gzip"). The header was subsequently cleared by the System.Web.Script.Services.RestHandler.WriteExceptionJsonString method, but the filter still compress the output stream.

So instead, I moved the Response.AppendHeader("Content-Encoding", "gzip") into the PreSendRequestHeaders event. Now the header gets set correctly for the Response.Filter GZipStream just before the headers are sent.

Hope that helps someone else.

0 件のコメント:

コメントを投稿