4

I have web application that in some pages I use Ms Ajax (Script Manager,Update Panel,...). In these pages I can't use compression because it conflicts with *.axd files.

How I can compress specific pages in my web application?

1
  • It looks like you have asked this same question before: stackoverflow.com/questions/8434881/… - That was the method I was going to suggest for you problem. Commented Dec 8, 2011 at 17:23

4 Answers 4

2
+50

I use a Http module to handle my compression. I am unable to use the new IIS compression for one of my sites since it is on shared hosting and they have not enabled IIS compression. I also have a custom web.config section in which i can exclude specific file paths as in:

If you want the code for module let me know. I can post it too. One class actually does the compression while i use 3 other classes to handle the custom web.config section.

  <RiderDesign>
    <HttpCompressionSettings compressionOn="true">
      <includedFileTypes>
        <add value="text/html"/>
        <add value="text/xhtml"/>
      </includedFileTypes>
      <excludedFilePaths>
        <add value="~/demos/partialpageupdates.aspx"/>
        <add value="~/demos/inlinetextedit.aspx"/>
      </excludedFilePaths>
    </HttpCompressionSettings
 </RiderDesign>

Just specify the pages to be excluded and they are not compressed.

My compression module is below:

Imports System.Web
Imports System.IO
Imports System.Net
Imports System.IO.Compression

Namespace RiderDesign.FrameworkV4.HttpModule

    Public NotInheritable Class HttpCompressionModule
        Implements IHttpModule
        Private Shared GZIP As String = "gzip"
        Private Shared DEFLATE As String = "deflate"

        Private Shared ENCODING_TYPE As String = "encodingType"
        Private Shared CONTENT_TYPE As String = "contentType"
        Private MARK As String = "passedModule"
        Dim HttpState As HttpCompressionConfigStateModule
        Sub Dispose() Implements IHttpModule.Dispose
        End Sub
        Sub Init(ByVal context As HttpApplication) Implements IHttpModule.Init

            If HttpCompressionConfigModule.GetConfig().CompressionOn = True Then
                ' Use for any other then WebResource
                AddHandler context.PostReleaseRequestState, AddressOf context_PostReleaseRequestState
            End If

            If HttpCompressionConfigModule.GetConfig().CompressionOn = True Then
                ' Use only for WebResource.axd files
                AddHandler context.BeginRequest, AddressOf context_BeginRequest
                AddHandler context.EndRequest, AddressOf context_EndRequest
            End If
        End Sub 'IHttpModule.Init

        Sub context_PostReleaseRequestState(ByVal sender As Object, ByVal e As EventArgs)
            Dim app As HttpApplication = CType(sender, HttpApplication) '

            If TypeOf app.Context.CurrentHandler Is System.Web.UI.Page And app.Request("HTTP_X_MICROSOFTAJAX") Is Nothing Then
                Dim FilePath As String
                Dim FilePaths As List(Of String) = New List(Of String)

                For Each Me.HttpState In HttpCompressionConfigModule.GetConfig().ExcludedFilePaths
                    FilePaths.Add(String.Format("{0}", HttpState.Value))
                Next HttpState
                FilePath = String.Join(", ", FilePaths.ToArray())

                Dim ContentTypes As String
                Dim FileTypes As List(Of String) = New List(Of String)
                Dim state As HttpCompressionConfigStateModule
                For Each state In HttpCompressionConfigModule.GetConfig().IncludedFileTypes
                    FileTypes.Add(String.Format("{0}", state.Value))
                Next state
                ContentTypes = String.Join(", ", FileTypes.ToArray())


                ' Check if the path is not excluded.
                If FilePath.Contains(app.Request.AppRelativeCurrentExecutionFilePath) Then
                    Return
                End If
                ' Check if the mime type is not excluded. (Use to exclude pages that generate specific mime type (such image or Excel...))
                If Not ContentTypes.Contains(app.Response.ContentType) Then
                    Return
                End If
                ' Check if GZIP is supported by the client
                If IsGzipEncodingSupported() Then
                    app.Response.Filter = New GZipStream(app.Response.Filter, CompressionMode.Compress)
                    SetEncodingType(GZIP)
                    ' Check if DEFLATE is supported by the client 

                Else
                    If IsDeflateEncodingSupported() Then
                        app.Response.Filter = New DeflateStream(app.Response.Filter, CompressionMode.Compress)
                        SetEncodingType(DEFLATE)
                    End If
                End If
            End If
        End Sub


        Sub context_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
            Dim app As HttpApplication = CType(sender, HttpApplication) '
            '
            ' Check if the current request is WebResource.axd
            If app.Request.Path.Contains("WebResource.axd") Then
                SetCachingHeaders(app)

                If app.Context.Request.QueryString(MARK) Is Nothing Then
                    app.CompleteRequest()
                End If
            End If
        End Sub 'context_BeginRequest



        Sub context_EndRequest(ByVal sender As Object, ByVal e As EventArgs)
            Dim app As HttpApplication = CType(sender, HttpApplication) '

            If app.Request.Path.Contains("WebResource.axd") And app.Context.Request.QueryString(MARK) Is Nothing Then
                Dim cacheKey As String = app.Request.QueryString.ToString()

                If app.Application(cacheKey) Is Nothing Then
                    CompressedIntoCache(app, cacheKey)
                End If

                SetEncodingType(CStr(app.Application((cacheKey + ENCODING_TYPE))))
                app.Context.Response.ContentType = CStr(app.Application((cacheKey + CONTENT_TYPE)))
                app.Context.Response.BinaryWrite(CType(app.Application(cacheKey), Byte()))
            End If
        End Sub 'context_EndRequest



        Private Sub CompressedIntoCache(ByVal app As HttpApplication, ByVal cacheKey As String)
            'Mark the current request by adding QueryString parameter.
            Dim request As HttpWebRequest = CType(WebRequest.Create((app.Context.Request.Url.OriginalString + "&" + MARK + "=1")), HttpWebRequest)
            request.Credentials = CredentialCache.DefaultNetworkCredentials
            Using response As HttpWebResponse = CType(request.GetResponse, HttpWebResponse)

                If (True) Then
                    ' We getting the response stream, that raise again the 'BeginRequest' event (that why we marked the request)
                    Dim responseStream As Stream = response.GetResponseStream()

                    Dim contentType As String = response.ContentType.ToLower()

                    ' Not a javascript or css content.
                    ' We compress only WebResources that are Javascript or css file.
                    ' The problem is, that we can know the content type only after we got the response. TODO: find a better solution
                    ' for non CSS or JS content
                    If Not IsContentSupported(contentType) Then
                        ' Set the response type
                        app.Context.Response.ContentType = contentType

                        ' Send the file to the client without compression
                        StreamCopy(responseStream, app.Response.OutputStream)
                        responseStream.Dispose()
                        app.Context.Response.End()
                        Return
                    End If

                    ' Copy the response stream into memory stream, so we can convert it into byte[] easly.
                    Dim dataStream As New MemoryStream()
                    StreamCopy(responseStream, dataStream)
                    responseStream.Dispose()

                    ' Convert the response into byte[]
                    Dim data As Byte() = dataStream.ToArray()
                    dataStream.Dispose()
                    Dim encodingType As String = String.Empty

                    Using memstream As MemoryStream = New MemoryStream
                        Dim compress As Stream = Nothing

                        ' Choose the compression type and make the compression
                        If IsGzipEncodingSupported() Then
                            compress = New GZipStream(memstream, CompressionMode.Compress)
                            encodingType = GZIP
                        Else
                            If IsDeflateEncodingSupported() Then
                                compress = New DeflateStream(memstream, CompressionMode.Compress)
                                encodingType = DEFLATE
                            End If
                        End If
                        compress.Write(data, 0, data.Length)
                        compress.Dispose()

                        app.Application.Lock()
                        app.Application.Add(cacheKey, memstream.ToArray())
                        app.Application.Add(cacheKey + ENCODING_TYPE, encodingType)
                        app.Application.Add(cacheKey + CONTENT_TYPE, response.ContentType)
                        app.Application.UnLock()

                    End Using
                End If
            End Using

        End Sub 'CompressedIntoCache




        Private Shared Sub StreamCopy(ByVal input As Stream, ByVal output As Stream)
            Dim buffer(2048) As Byte
            Dim read As Integer
            Do
                read = input.Read(buffer, 0, buffer.Length)
                output.Write(buffer, 0, read)
            Loop While read > 0
        End Sub 'StreamCopy

        Private Shared Sub SetCachingHeaders(ByVal app As HttpApplication)
            Dim etag As String = """" + app.Context.Request.QueryString.ToString().GetHashCode().ToString() + """"
            Dim incomingEtag As String = app.Request.Headers("If-None-Match")

            app.Response.Cache.VaryByHeaders("Accept-Encoding") = True
            app.Response.Cache.SetExpires(DateTime.Now.ToUniversalTime().AddDays(365))
            app.Response.Cache.SetCacheability(HttpCacheability.Public)
            app.Response.Cache.SetLastModified(DateTime.Now.ToUniversalTime().AddDays(-1))
            app.Response.Cache.SetETag(etag)

            If [String].Compare(incomingEtag, etag) = 0 Then
                app.Response.StatusCode = CInt(HttpStatusCode.NotModified)
                app.Response.End()
            End If
        End Sub 'SetCachingHeaders


        Private Shared Function IsBrowserSupported() As Boolean
            ' Because bug in Internet Explorer 6
            Return Not (HttpContext.Current.Request.UserAgent Is Nothing Or HttpContext.Current.Request.UserAgent.Contains("MSIE 6"))
        End Function 'IsBrowserSupported


        Private Shared Function IsEncodingSupported() As Boolean
            Return IsGzipEncodingSupported() Or IsDeflateEncodingSupported()
        End Function 'IsEncodingSupported

        Private Shared Function IsGzipEncodingSupported() As Boolean
            Return Not (HttpContext.Current.Request.Headers("Accept-encoding") Is Nothing) And HttpContext.Current.Request.Headers("Accept-encoding").Contains(GZIP)
        End Function 'IsGzipEncodingSupported

        Private Shared Function IsDeflateEncodingSupported() As Boolean
            Return Not (HttpContext.Current.Request.Headers("Accept-encoding") Is Nothing) And HttpContext.Current.Request.Headers("Accept-encoding").Contains(DEFLATE)
        End Function 'IsDeflateEncodingSupported

        Private Shared Sub SetEncodingType(ByVal encoding As String)
            HttpContext.Current.Response.AppendHeader("Content-encoding", encoding)
        End Sub 'SetEncodingType

        Private Shared Function IsContentSupported(ByVal contentType As String) As Boolean
            If contentType.Contains("text/css") Or contentType.Contains("javascript") Then
                Return True
            End If
            Return False
        End Function
    End Class
End Namespace
Sign up to request clarification or add additional context in comments.

3 Comments

Web.cnfig have not includedFileTypes' and excludedFilePaths` tags.and I have for example 50 ages thar 50 of them using ms-ajax that can not be compress.in your example do I write this 50 pages in excludedFilePaths section? If I can enable IIS compression is it as better as asp.net compression?
Of course web.config does not have these sections. This a custom section specifically for my custom http module that handles compression. i dont know which is better at compression. you can also specify a directory - such as <add value="~/demos"/>
may I know what HTTP Module you use?Are you using your module for MS-Ajax?was it without problem?
1

Have you tried HTTP compression (either dynamic and/or static content) via IIS 7, that will compress all the data that is communicated between the client and the server.

http://technet.microsoft.com/en-us/library/cc771003%28WS.10%29.aspx

Comments

0

I would personally use an HTTP module to compress .axd files.

There is an example of one here...

http://www.codeproject.com/KB/aspnet/httpcompression.aspx

Comments

0

this is may be useful for you this accepts deflate and gzip compression

  void Application_PreRequestHandlerExecute(object sender, EventArgs e)
    {
        HttpApplication app = sender as HttpApplication;
        string acceptEncoding = app.Request.Headers["Accept-Encoding"];
        Stream prevUncompressedStream = app.Response.Filter;

        if (!(app.Context.CurrentHandler is System.Web.UI.Page ||
            app.Context.CurrentHandler.GetType().Name == "SyncSessionlessHandler") ||
            app.Request["HTTP_X_MICROSOFTAJAX"] != null)
            return;

        if (acceptEncoding == null || acceptEncoding.Length == 0)
            return;

        acceptEncoding = acceptEncoding.ToLower();

        if (acceptEncoding.Contains("deflate") || acceptEncoding == "*")
        {
            // deflate
            app.Response.Filter = new DeflateStream(prevUncompressedStream,
                CompressionMode.Compress);
            app.Response.AppendHeader("Content-Encoding", "deflate");
        }
        else if (acceptEncoding.Contains("gzip"))
        {
            // gzip
            app.Response.Filter = new GZipStream(prevUncompressedStream,
                CompressionMode.Compress);
            app.Response.AppendHeader("Content-Encoding", "gzip");
        }
    }

1 Comment

You use this module with MS-AJAx?I think it has problem with ms-ajax

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.