I am using a long-lived asynchronous HTTP connection to send progress updates to a client via AJAX. When compression is enabled, the updates are not received in discrete chunks (for obvious reasons). Disabling compression (by adding a <urlCompression>
element to <system.webServier>
) does solve the problem:
<urlCompression doStaticCompression="true" doDynamicCompression="false" />
However, this disables compression site-wide. I would like to preserve compression for every other controller and/or action except for this one. Is this possible? Or am I going to have to create a new site/area with its own web.config? Any suggestions welcome.
P.S. the code that does the writing to the HTTP response is:
var response = HttpContext.Response;
response.Write(s);
response.Flush();
I found a much easier way to do this. Instead of selectively doing your own compression, you can selectively disable the default IIS compression (assuming its enabled in your web.config).
Simply remove the accept-encoding encoding header on the request and IIS wont compress the page.
(global.asax.cs:)
protected void Application_BeginRequest(object sender, EventArgs e)
{
try
{
HttpContext.Current.Request.Headers["Accept-Encoding"] = "";
}
catch(Exception){}
}
@Aristos' answer will work for WebForms, but with his help, I've adapted a solution more inline with ASP.NET/MVC methodology.
Create a new filter to provide the gzipping functionality:
public class GzipFilter : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext);
var context = filterContext.HttpContext;
if (filterContext.Exception == null &&
context.Response.Filter != null &&
!filterContext.ActionDescriptor.IsDefined(typeof(NoGzipAttribute), true))
{
string acceptEncoding = context.Request.Headers["Accept-Encoding"].ToLower();;
if (acceptEncoding.Contains("gzip"))
{
context.Response.Filter = new GZipStream(context.Response.Filter, CompressionMode.Compress);
context.Response.AppendHeader("Content-Encoding", "gzip");
}
else if (acceptEncoding.Contains("deflate"))
{
context.Response.Filter = new DeflateStream(context.Response.Filter, CompressionMode.Compress);
context.Response.AppendHeader("Content-Encoding", "deflate");
}
}
}
}
Create the NoGzip
attribute:
public class NoGzipAttribute : Attribute {
}
Prevent IIS7 from gzipping using web.config:
<system.webServer>
...
<urlCompression doStaticCompression="true" doDynamicCompression="false" />
</system.webServer>
Register your global filter in Global.asax.cs:
protected void Application_Start()
{
...
GlobalFilters.Filters.Add(new GzipFilter());
}
Finally, consume the NoGzip
attribute:
public class MyController : AsyncController
{
[NoGzip]
[NoAsyncTimeout]
public void GetProgress(int id)
{
AsyncManager.OutstandingOperations.Increment();
...
}
public ActionResult GetProgressCompleted()
{
...
}
}
P.S. Once again, many thanks to @Aristos, for his helpful idea and solution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With