tags:

views:

349

answers:

5

Is there a way to change ASPX file soure before it is precompiled into temporary files.

i.e. to remove empty spaces and new lines.

A: 

It may help if you gave some background as to why you want to do this.

If, as I suspect, it's so the html is nicely laid-out when users view source, you can get visual studio to tidy up your html using the chord ctrl+k, ctrl+d.

Hope this helps.

Paul Suart
On the contrary I want the end result (rendered HTML) to be efficient as opposed to good looking.There is no need for final rendered HTML code to have code formating spaces/tabs/new-lines in it. That just uses unnecessary bandwidth
Donnie
A: 

ASPX files will not be "compiled" into HTML. ASPX pages are declarative code. All the content is compiled in .NET executable code.

If you want to save bandwidth deleting white spaces etc., consider using IIS compression (GZIP etc.). Here is a blog entry by Jeff Atwood about compression in IIS 6.0 which explains the details. A more difficult alternative would be to write a HTTPModule.

splattne
I am aware of these techniques but they both waste CPU resources whereas I am looking for a solution that would eliminate that.
Donnie
Here is a bit of code from ASP.NET cache. Lots of uneeded characters added to this literal@__parser.AddParsedSubObject(new System.Web.UI.LiteralControl("\r\n <table class=\"data\">\r\n <tr>\r\n " + " <th style=\"width:1px;\">"));
Donnie
damn, the spaces were stripped :) but anyways, I'd like to strip \r\n from this cache code.
Donnie
Hm, I understand. But I would try to measure the CPU performance. I noticed that even on heavy load the webserver's CPU did a fine job compressing...
splattne
There is a discussion here: http://discuss.joelonsoftware.com/default.asp?dotnet.12.449363.13
splattne
Take a look at this solution: http://omari-o.blogspot.com/2009/09/aspnet-white-space-cleaning-with-no.html
thorn
A: 

Going by your comments for thedorko's post you might want to look in to GZIP / deflate for compressing the rendered html.

Have a look at this example

TWith2Sugars
+1  A: 

I would suggest not going this at build time but at runtime. You probably have enough processor speed to deal with the generating of the HTML. I would aim to save on bandwidth.

I would definitely set your web server to send out the pages as compressed files (GZip)

On the application side, you can build in filters that will take your finalized rendered HTML pages and do the processes you speak of, removing whitespace, ect.

You could build an ISAPI filter, which is the older harder way.

Or you could create Stream filter and just override the write method. Set the HttpResponse.Filter Property to be your Stream Filter. Here's a quick example.

Glennular
+3  A: 

Yes, there is, but it is not easy and may not be worth your trouble.

One way of doing it is to create your own BuildProvider and replace the default System.Web.Compilation.PageBuildProvider with it in the config file:

<compilation debug="true">
    <buildProviders>
     <add extension=".aspx" type="MyProject.MyPageBuildProvider" />
    </buildProviders>
</compilation>

You would also create your own PageParser, most likely inherited from the TemplateParser. The BuildProvider is responsible for supplying the PageParser. In most primitive situation you could overwrite the ParseFile method, read the ASPX file, process it, create a copy and pass it to the base method.

Unfortunately, all ASPX parsing code is sealed and internal to MS libraries, so you can't inherit. Rewriting it would mean building entire compilation engine.

The alternative method is to create your own page builder and put it in the attribute. The drawback is that you get an easy access to literals (all your spaces etc) of the first level (the page) only. To get to inner controls and their literals, you have to either hack the parser using reflection or (proper) manipulate the code dom. This way you would get properly built .cs files and temporary assemblies.

Here is a simplified sample:

namespace MyProject
{
    [FileLevelControlBuilder(typeof(MyPageBuilder))]
    public partial class _Default : System.Web.UI.Page
    {
     //this is Default.aspx
    }

    //The builder of the page
    public class MyPageBuilder : FileLevelPageControlBuilder
    {
     //This is where you'd strip white space, but only of top level,
     //such as between the head and form, or form and the end of file
     public override void AppendLiteralString(string text)
     {
      //let's replace some white spaces with garbage
      base.AppendLiteralString(text.Replace(" ", "#").Replace("\t", "@").Replace("\r", "$").Replace("\n", "%"));
     }

     //Here you can manipulate the entire generated code using CodeDom
     public override void ProcessGeneratedCode(System.CodeDom.CodeCompileUnit codeCompileUnit, System.CodeDom.CodeTypeDeclaration baseType, System.CodeDom.CodeTypeDeclaration derivedType, System.CodeDom.CodeMemberMethod buildMethod, System.CodeDom.CodeMemberMethod dataBindingMethod)
     {
      base.ProcessGeneratedCode(codeCompileUnit, baseType, derivedType, buildMethod, dataBindingMethod);
     }

     //Alternatively, you can "hack" the PageParser here using reflection
     //However, the _text field at this point is irrelevant, so it can't be used
     public override void Init(TemplateParser parser, ControlBuilder parentBuilder, Type type, string tagName, string ID, System.Collections.IDictionary attribs)
     {
      FieldInfo fi = parser.GetType().BaseType.BaseType.BaseType.GetField("_text", System.Reflection.BindingFlags.FlattenHierarchy | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
      string s = (string) fi.GetValue(parser);
      fi.SetValue(parser, s.Replace("\t", "*"));

      base.Init(parser, parentBuilder, type, tagName, ID, attribs);
     }
    }
}

In my opinion, it is not worth the effort.

edited typo

Ruslan