This blog has moved!

Check out www.CodeBetter.com/blogs/grant.killian

<September 2008>
SuMoTuWeThFrSa
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011


Navigation

Professional Props...

Extracurricular Props...

Subscriptions

Article Categories



Server Script Tags for ASPX

The Windows Apps for .Net class I'm teaching is wrapping up and I'm starting to look forward to the Web Apps for .Net sections. I like the web stuff better, probably because most of my programming jobs are more web-centric. For people transitioning from ASP "classic" to ASP.Net the behaviour of the server script tags can be confusing. If you know where to look on the webserver, however, one can gain some insight into the rules of server script tags and also how ASP.Net processes your pages. I'll walk through this here.

If you create a new web app in VS.Net, WebForm1.aspx will be created by default. If you go into the HTML view of this page, you can add some code to end up with the following:
<HTML><HEAD></HEAD>
<body><form id="Form1" method="post" runat="server">
<%
Response.Write( System.DateTime.Now.ToShortDateString() );

private void writeStuff() {
  Response.Write( System.DateTime.Now.ToShortDateString() );
}
%>
</form></body></HTML>

ASP "classic" would process a page like this without error (assuming you were using vbScript, Jscript, etc); you'd get the current date listed on the page twice. Much to the dismay of the new ASP.Net developer, however, .Net throws a compilation error with a page like this. The contents of the server script tags (between the angled brackets and percent signs) aren't permitted in the ASP.Net model.

What's up?

Start by deleting the writeStuff method, it's the "wrong stuff" in our example (sorry, couldn't help it). Let's replace it with some code to help us understand what .Net is doing:
<script runat="server" language="C#">
private void writeSetupInfo() {
  Response.Output.Write( "{0}<BR>", AppDomain.CurrentDomain.SetupInformation.CachePath );
  Response.Output.Write( "{0}<BR>", AppDomain.CurrentDomain.SetupInformation.ApplicationName );
}
</script>
<%
  writeSetupInfo();
%>

Note how this new code shows the two forms of server script tags, the literal "<script . . ." and the more terse "<% . . . ", and the proper usage pattern for ASP.Net. As you'll see, methods can be defined inside the literal script tags while executable code (but not method definitions) can be in the terse "<%" tags. The writeSetupInfo method writes two strings of text to the browser, the first string is an absolute path to where ASP.Net places the cached output from your ASP.Net compilations. The second string is the name of the application according to ASP.Net's internal compilation engine . . . it is also the folder beneath the CachePath directory to find the specific .Net output of your program. If you browse the file system to the CachePath directory, and then open the AppName folder beneath the CachePath, you'll find what VS.Net generates as a result of compilation. Note that these CachePath and ApplicationName properties can be configured, I'm not so interested in that right now so I just go with the defaults.

We're only interested in one file in this directory, and it's name will vary; it's a .cs file, and if you sort the files by Date Modified, it will be the most recent file. In my experience, the file name will be something like "puun_xsh.0.cs". Open this file with Notepad, VS.Net, or whatever you prefer. This cs file is a generated representation of the WebForm1.aspx file.

In ASP "classic", I sometimes generated entire pages with Response.Write statements; in one project we even used COM dlls as our asp page factory -- writing text from the COM dll to the Response stream. I'd start with Response.Write( "<HTML><HEAD>" ) and so on.

The ASP.Net framework builds on this concept of generating pages by writing HTML from code and creates a class file for every aspx page; the class file for our WebForm1.aspx is the *.cs file I'm having you explore. There's a lot to the generated file. Don't be intimidated by the #line statements you find or anything else, this is just an ordinary c# file like any other and conforms to c# grammar/syntax (the #line statements aid in debugging and exception messages -- msdn help can clarify if you need). You'll find a __BuildControlTree method in this file that contains the code to produce some of your literal HTML with statements like:

__parser.AddParsedSubObject(new System.Web.UI.LiteralControl("\r\n<HTML>\r\n<HEAD>\r\n</HEAD>\r\n<body>\r\n"));

You'll also see the writeSetupInfo method you defined in the literal server script tags ("<script . . ."); code inside the literal script tags gets compiled into the definition of the class -- this is why simple code execution statements like Response.Write( "Hello" ); will fail with ASPX. Try adding a statement like Response.Write( "Hello" ); to the literal server script block, recompile your program, and check out the resulting class file created in the CachePath. You'll see:
public class WebForm1_aspx : aspxFoundations.WebForm1, System.Web.SessionState.IRequiresSessionState {
Response.Write( "Hello" );
/* . . . everything else omitted . . . */
}

Classes cannot have arbitrary code statements outside of method definitions; all code contained inside literal ASPX "<script" tags must abide by this same rule.

Moving on to the terse "<%" tags, everything placed inside these gets included in a "__Render.." method of our generated class. __RenderForm1 contains our call to writeSetupInfo and other executable statements. Try placing the "writeStuff" method we had earlier into the terse "<%" tags and see where the code gets placed in our generated file. It's like we're trying to nest methods within methods -- and why our page throws an exception.

Will you frequently browse the cached output of your ASPX applications? Doubtful; it's an academic exercise. But for those curious or struggling with the ASP to ASPX conversion, this can be a real eye opener. The code placed inside ASPX "<script..." tags gets combined with the type definition of the page class -- so no code statements outside of methods are allowed; the code place inside terse ASPX "<%" tags gets placed inside a method definition of the page class, so only executable code statements are permitted.

Happy .Netting!

posted on Friday, September 26, 2003 6:15 AM by grant.killian





Powered by Dot Net Junkies, by Telligent Systems