В ASP.NET 2.0 как удалить дополнительные вкладки и разрывы строк из вывода обработанной страницы / элемента управления? - PullRequest
2 голосов
/ 16 сентября 2010

Я изучал этот вопрос некоторое время. Я нашел несколько ресурсов на эту тему, и все они, как правило, используют один и тот же подход - переопределить Page.Render, использовать HtmlTextWriter для преобразования вывода в строку, а затем использовать серию скомпилированных регулярных выражений для удаления лишних пробелов. Вот пример .

Ну, я попробовал, и это работает ... но ....

В Safari 5.0 это, похоже, вызывает всевозможные проблемы с производительностью при загрузке изображений и возникновении ошибок «сервер слишком занят». IE 7, FireFox 3.6 и Google Chrome 6.0, кажется, работают нормально, но я не слишком стресс-тестировал сервер. Иногда кажется, что во время создания страницы возникают задержки, но как только HTML отправляется в браузер, страница отображается быстро.

В любом случае, когда вы думаете об этом, кажется довольно глупым, чтобы .NET создавал все эти вкладки и разрывы строк только для того, чтобы лишить их всех снова при помощи анализа строк - наименее эффективный способ их вырезать. Было бы более разумно переопределить HtmlTextWriter и передать его в дерево по запросу главной страницы, чтобы вообще не помещать их в вывод - по логике в этом случае должно быть повышение производительности, а не попадание.

Даже если я смогу удалить только 50% пробелов с помощью этого метода, он все равно оставит гораздо меньше работы для регулярных выражений - это означает, что он должен работать лучше, чем для одних только регулярных выражений.

Я попытался с помощью адаптера управления и переопределить несколько членов

  1. Направление всех вызовов метода WriteLine () в соответствующий метод Write ()
  2. Задание для свойства NewLine пустой строки
  3. Переопределение метода OutputTabs () и простое удаление кода
  4. Переопределение свойства Indent и возвращение 0

Я также пытался переопределить RenderChildren, Render, BeginRender и EndRender, чтобы передать мой пользовательский HtmlTextWriter, но я не могу заставить даже простой элемент управления меткой удалять вкладки перед его тегом. Я также перерыл фреймворк с помощью Reflector, но я просто не могу понять, как генерируются эти символы - я думал, что использовал подход «поймать все», но, очевидно, я что-то упустил.

Во всяком случае, вот что я придумала. Этот код не работает так, как мне бы хотелось. Конечно, я также попытался переопределить различные методы Render на странице напрямую и передать экземпляр моего пользовательского HtmlTextWriter, но это тоже не сработало.

Public Class PageCompressorControlAdapter
    Inherits System.Web.UI.Adapters.ControlAdapter

    Protected Overrides Sub RenderChildren(ByVal writer As System.Web.UI.HtmlTextWriter)
        MyBase.RenderChildren(New CompressedHtmlTextWriter(writer))
    End Sub

    Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
        MyBase.Render(New CompressedHtmlTextWriter(writer))
    End Sub

    Protected Overrides Sub BeginRender(ByVal writer As System.Web.UI.HtmlTextWriter)
        MyBase.BeginRender(New CompressedHtmlTextWriter(writer))
    End Sub

    Protected Overrides Sub EndRender(ByVal writer As System.Web.UI.HtmlTextWriter)
        MyBase.EndRender(New CompressedHtmlTextWriter(writer))
    End Sub

End Class

Public Class CompressedHtmlTextWriter
    Inherits HtmlTextWriter

    Sub New(ByVal writer As HtmlTextWriter)
        MyBase.New(writer, "")
        Me.InnerWriter = writer.InnerWriter

        Me.NewLine = ""
    End Sub

    Sub New(ByVal writer As System.IO.TextWriter)
        MyBase.New(writer, "")
        MyBase.InnerWriter = writer

        Me.NewLine = ""
    End Sub

    Protected Overrides Sub OutputTabs()
        'Skip over the tabs
    End Sub

    Public Overrides Property NewLine() As String
        Get
            Return ""
        End Get
        Set(ByVal value As String)
            MyBase.NewLine = value
        End Set
    End Property


    Public Overrides Sub WriteLine()

    End Sub

    Public Overrides Sub WriteLine(ByVal value As Boolean)
        MyBase.Write(value)
    End Sub

    Public Overrides Sub WriteLine(ByVal value As Char)
        MyBase.Write(value)
    End Sub

    Public Overrides Sub WriteLine(ByVal buffer() As Char)
        MyBase.Write(buffer)
    End Sub

    Public Overrides Sub WriteLine(ByVal buffer() As Char, ByVal index As Integer, ByVal count As Integer)
        MyBase.Write(buffer, index, count)
    End Sub

    Public Overrides Sub WriteLine(ByVal value As Decimal)
        MyBase.Write(value)
    End Sub

    Public Overrides Sub WriteLine(ByVal value As Double)
        MyBase.Write(value)
    End Sub

    Public Overrides Sub WriteLine(ByVal value As Integer)
        MyBase.Write(value)
    End Sub

    Public Overrides Sub WriteLine(ByVal value As Long)
        MyBase.Write(value)
    End Sub

    Public Overrides Sub WriteLine(ByVal value As Object)
        MyBase.Write(value)
    End Sub

    Public Overrides Sub WriteLine(ByVal value As Single)
        MyBase.Write(value)
    End Sub

    Public Overrides Sub WriteLine(ByVal s As String)
        MyBase.Write(s)
    End Sub

    Public Overrides Sub WriteLine(ByVal format As String, ByVal arg0 As Object)
        MyBase.Write(format, arg0)
    End Sub

    Public Overrides Sub WriteLine(ByVal format As String, ByVal arg0 As Object, ByVal arg1 As Object)
        MyBase.Write(format, arg0, arg1)
    End Sub

    Public Overrides Sub WriteLine(ByVal format As String, ByVal arg0 As Object, ByVal arg1 As Object, ByVal arg2 As Object)
        MyBase.Write(format, arg0, arg1, arg2)
    End Sub

    Public Overrides Sub WriteLine(ByVal format As String, ByVal ParamArray arg() As Object)
        MyBase.Write(format, arg)
    End Sub

    Public Overrides Sub WriteLine(ByVal value As UInteger)
        MyBase.Write(value)
    End Sub

    Public Overrides Sub WriteLine(ByVal value As ULong)
        MyBase.Write(value)
    End Sub

End Class

Если вы не знакомы с адаптерами управления, просто поместите приведенный ниже XML-файл в файл .browser в папке ASP.NET App_Browsers. Вы можете изменить controlType, чтобы применить адаптер управления к метке или что-то еще для меньшего объема теста. Если мне удастся заставить это работать, не составит большого труда добавить сюда все элементы управления в моем проекте, если это будет необходимо.

<browsers>

    <browser refID="Default">
        <controlAdapters>
            <adapter controlType="System.Web.UI.Page"
                     adapterType="PageCompressorControlAdapter"/>
        </controlAdapters>
    </browser>

</browsers>

В любом случае, вы могли бы подумать, что будет простой параметр конфигурации, такой как VerboseHtml = "false" или PreserveHtmlFormatting = "false" или что-то в этом роде. Если вы посмотрите на выходные данные MSN.com, они используют какое-то сжатие, подобное этому ... и оно выглядит очень производительным.

1 Ответ

1 голос
/ 11 октября 2010

Решение включало использование модифицированной версии модуля компрессора, которую я нашел здесь:

http://omari -o.blogspot.com / 2009/09 / САШИ-бело-пространство-очищающий с-no.html

В этом решении реализован пользовательский PageParserFilter, который затем настраивается в файле web.config. Прелесть этого решения в том, что оно фильтрует пустое пространство во время компиляции, поэтому во время выполнения производительность не падает.

А потом, благодаря Аристосу и Диамандиеву, я искал разумный способ добавить сжатие в поток ответов для браузеров, которые его поддерживают. Я нашел другой модуль с открытым исходным кодом, который можно использовать для этого здесь: http://blowery.org/httpcompress/

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

Что касается статического содержимого, я планирую использовать метод из этой статьи, чтобы также сжать эти файлы (за исключением изображений, конечно, они уже сжаты): http://www.lostechies.com/blogs/dahlbyk/archive/2010/01/08/script-to-enable-http-compression-gzip-deflate-in-iis-6.aspx

Окончательное решение

Я добавил свое окончательное решение к этому Гисту .

...