Last active
August 29, 2015 14:05
-
-
Save NightOwl888/c1f0a558d69f82dedfef to your computer and use it in GitHub Desktop.
WhiteSpaceCleaner for ASP.NET
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Imports System.Collections | |
Imports System.Reflection | |
Imports System.Web.UI | |
Namespace MyNamespace | |
' This class relies on the internal implementation details of ASP.NET. Tested for ASP.NET 2.0, 3.5 , 4.0 | |
Public NotInheritable Class ControlBuilderExtensions | |
Private Sub New() | |
End Sub | |
Const InstPubNonpub As BindingFlags = BindingFlags.[Public] Or BindingFlags.NonPublic Or BindingFlags.Instance | |
Public Shared Function GetParentBuilder(ByVal controlBuilder As ControlBuilder) As ControlBuilder | |
If controlBuilder Is Nothing Then | |
Throw New ArgumentNullException("controlBuilder") | |
End If | |
Return DirectCast(controlBuilder.[GetType]().GetProperty("ParentBuilder", InstPubNonpub).GetValue(controlBuilder, Nothing), ControlBuilder) | |
End Function | |
Public Shared Function GetRootBuilder(ByVal controlBuilder As ControlBuilder) As ControlBuilder | |
If controlBuilder Is Nothing Then | |
Throw New ArgumentNullException("controlBuilder") | |
End If | |
While GetParentBuilder(controlBuilder) IsNot Nothing | |
controlBuilder = GetParentBuilder(controlBuilder) | |
End While | |
Return controlBuilder | |
End Function | |
Public Shared Function GetSubBuilders(ByVal controlBuilder As ControlBuilder) As ArrayList | |
If controlBuilder Is Nothing Then | |
Throw New ArgumentNullException("controlBuilder") | |
End If | |
Return DirectCast(controlBuilder.[GetType]().GetProperty("SubBuilders", InstPubNonpub).GetValue(controlBuilder, Nothing), ArrayList) | |
End Function | |
Public Shared Function GetDefaultPropertyBuilder(ByVal controlBuilder As ControlBuilder) As ControlBuilder | |
If controlBuilder Is Nothing Then | |
Throw New ArgumentNullException("controlBuilder") | |
End If | |
Dim pi As PropertyInfo = Nothing | |
Dim type As Type = controlBuilder.[GetType]() | |
While type IsNot Nothing AndAlso (InlineAssignHelper(pi, type.GetProperty("DefaultPropertyBuilder", InstPubNonpub))) Is Nothing | |
type = type.BaseType | |
End While | |
Return DirectCast(pi.GetValue(controlBuilder, Nothing), ControlBuilder) | |
End Function | |
Public Shared Function GetTemplatePropertyEntries(ByVal controlBuilder As ControlBuilder) As ArrayList | |
If controlBuilder Is Nothing Then | |
Throw New ArgumentNullException("controlBuilder") | |
End If | |
Dim tpes As ICollection = DirectCast(controlBuilder.[GetType]().GetProperty("TemplatePropertyEntries", InstPubNonpub).GetValue(controlBuilder, Nothing), ICollection) | |
If tpes Is Nothing OrElse tpes.Count = 0 Then | |
Return New ArrayList(0) | |
Else | |
Return DirectCast(tpes, ArrayList) | |
End If | |
End Function | |
Public Shared Function GetComplexPropertyEntries(ByVal controlBuilder As ControlBuilder) As ArrayList | |
If controlBuilder Is Nothing Then | |
Throw New ArgumentNullException("controlBuilder") | |
End If | |
Dim cpes As ICollection = DirectCast(controlBuilder.[GetType]().GetProperty("ComplexPropertyEntries", InstPubNonpub).GetValue(controlBuilder, Nothing), ICollection) | |
If cpes Is Nothing OrElse cpes.Count = 0 Then | |
Return New ArrayList(0) | |
Else | |
Return DirectCast(cpes, ArrayList) | |
End If | |
End Function | |
Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, ByVal value As T) As T | |
target = value | |
Return value | |
End Function | |
End Class | |
End Namespace |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Imports System.Web.UI | |
Namespace MyNamespace | |
Public Class NotRestrictingParserFilter | |
Inherits PageParserFilter | |
Public Overrides ReadOnly Property AllowCode() As Boolean | |
Get | |
Return True | |
End Get | |
End Property | |
Public Overrides ReadOnly Property NumberOfControlsAllowed() As Integer | |
Get | |
Return Integer.MaxValue | |
End Get | |
End Property | |
Public Overrides ReadOnly Property NumberOfDirectDependenciesAllowed() As Integer | |
Get | |
Return Integer.MaxValue | |
End Get | |
End Property | |
Public Overrides ReadOnly Property TotalNumberOfDependenciesAllowed() As Integer | |
Get | |
Return Integer.MaxValue | |
End Get | |
End Property | |
Public Overrides Function AllowBaseType(ByVal baseType As Type) As Boolean | |
Return True | |
End Function | |
Public Overrides Function AllowControl(ByVal controlType As Type, ByVal builder As ControlBuilder) As Boolean | |
Return True | |
End Function | |
Public Overrides Function AllowServerSideInclude(ByVal includeVirtualPath As String) As Boolean | |
Return True | |
End Function | |
Public Overrides Function AllowVirtualReference(ByVal referenceVirtualPath As String, ByVal referenceType As VirtualReferenceType) As Boolean | |
Return True | |
End Function | |
Public Overrides Function GetCompilationMode(ByVal current As CompilationMode) As CompilationMode | |
Return MyBase.GetCompilationMode(current) | |
End Function | |
Public Overrides Function GetNoCompileUserControlType() As Type | |
Return MyBase.GetNoCompileUserControlType() | |
End Function | |
Public Overrides Sub PreprocessDirective(ByVal directiveName As String, ByVal attributes As System.Collections.IDictionary) | |
MyBase.PreprocessDirective(directiveName, attributes) | |
End Sub | |
Public Overrides Function ProcessCodeConstruct(ByVal codeType As CodeConstructType, ByVal code As String) As Boolean | |
Return MyBase.ProcessCodeConstruct(codeType, code) | |
End Function | |
Public Overrides Function ProcessDataBindingAttribute(ByVal controlId As String, ByVal name As String, ByVal value As String) As Boolean | |
Return MyBase.ProcessDataBindingAttribute(controlId, name, value) | |
End Function | |
Public Overrides Function ProcessEventHookup(ByVal controlId As String, ByVal eventName As String, ByVal handlerName As String) As Boolean | |
Return MyBase.ProcessEventHookup(controlId, eventName, handlerName) | |
End Function | |
Public Overrides Sub ParseComplete(ByVal rootBuilder As ControlBuilder) | |
MyBase.ParseComplete(rootBuilder) | |
End Sub | |
Protected Overrides Sub Initialize() | |
MyBase.Initialize() | |
End Sub | |
End Class | |
End Namespace |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Imports System.Collections | |
Imports System.Text.RegularExpressions | |
Imports System.Web | |
Imports System.Web.UI | |
Imports System.Web.Configuration | |
Namespace MyNamespace | |
Public Enum WhiteSpaceCleaning | |
None | |
Clean | |
CleanOnReleaseBuild | |
End Enum | |
Public Class WhiteSpaceCleaner | |
Inherits NotRestrictingParserFilter | |
Const WhiteSpaceDirectiveName As String = "whitespacecleaning" | |
Private _whiteSpaceCleaning As System.Nullable(Of WhiteSpaceCleaning) | |
Private Shared RegexLineBreaks As New Regex("\s*\n\s*", RegexOptions.Compiled) | |
Private Shared RegexWhiteSpace As New Regex("[\t ]{2,}", RegexOptions.Compiled) | |
Public Overrides Sub PreprocessDirective(ByVal directiveName As String, ByVal attributes As System.Collections.IDictionary) | |
If attributes.Contains(WhiteSpaceDirectiveName) Then | |
_whiteSpaceCleaning = CType([Enum].Parse(GetType(WhiteSpaceCleaning), DirectCast(attributes(WhiteSpaceDirectiveName), String)), WhiteSpaceCleaning) | |
attributes.Remove(WhiteSpaceDirectiveName) | |
End If | |
MyBase.PreprocessDirective(directiveName, attributes) | |
End Sub | |
Public Overrides Sub ParseComplete(ByVal rootBuilder As ControlBuilder) | |
Dim whiteSpace As WhiteSpaceCleaning = IIf(_whiteSpaceCleaning.HasValue, _whiteSpaceCleaning, WhiteSpaceCleaning.CleanOnReleaseBuild) | |
If whiteSpace = WhiteSpaceCleaning.Clean OrElse (whiteSpace = WhiteSpaceCleaning.CleanOnReleaseBuild AndAlso Not IsDebuggingEnabled()) Then | |
TrimStringSubBuilders(rootBuilder) | |
End If | |
MyBase.ParseComplete(rootBuilder) | |
End Sub | |
Private Shared Sub TrimStringSubBuilders(ByVal controlBuilder As ControlBuilder) | |
Dim subBuilders As ArrayList = ControlBuilderExtensions.GetSubBuilders(controlBuilder) | |
For i As Integer = 0 To subBuilders.Count - 1 | |
Dim literal As String = TryCast(subBuilders(i), String) | |
If String.IsNullOrEmpty(literal) Then | |
Continue For | |
End If | |
subBuilders(i) = CleanWhiteSpace(literal) | |
Next | |
For Each subBuilder As Object In subBuilders | |
If TypeOf subBuilder Is ControlBuilder Then | |
TrimStringSubBuilders(DirectCast(subBuilder, ControlBuilder)) | |
End If | |
Next | |
For Each entry As TemplatePropertyEntry In ControlBuilderExtensions.GetTemplatePropertyEntries(controlBuilder) | |
TrimStringSubBuilders(entry.Builder) | |
Next | |
For Each entry As ComplexPropertyEntry In ControlBuilderExtensions.GetComplexPropertyEntries(controlBuilder) | |
TrimStringSubBuilders(entry.Builder) | |
Next | |
Dim defaultPropertyBuilder As ControlBuilder = ControlBuilderExtensions.GetDefaultPropertyBuilder(controlBuilder) | |
If defaultPropertyBuilder IsNot Nothing Then | |
TrimStringSubBuilders(defaultPropertyBuilder) | |
End If | |
End Sub | |
Private Shared Function CleanWhiteSpace(ByVal literal As String) As String | |
literal = RegexLineBreaks.Replace(literal, vbLf) | |
literal = RegexWhiteSpace.Replace(literal, " ") | |
Return literal | |
End Function | |
Private Function IsDebuggingEnabled() As Boolean | |
If HttpContext.Current IsNot Nothing Then | |
Return HttpContext.Current.IsDebuggingEnabled | |
End If | |
Return DirectCast(WebConfigurationManager.GetSection("system.web/compilation", VirtualPath), CompilationSection).Debug | |
End Function | |
End Class | |
End Namespace | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
WhiteSpaceCleaner is enabled through the web.config file, like this.
Sorry, I don't have any additional info other than this - I put this in place in 2010 and didn't document it. I have also switched to using HTTP compression built into IIS 7 instead of the 3rd party component.