I'm doing some ASP.NET work on my current project (more about that in the coming months). I've spent most of my life doing client side code, so it's taken me a little time to really wrap my head around what's happening with ASP.NET. It often seems like there's a lot of magic going on. But, once you look into it, it's not really that complicated.
The job of an ASP.NET page is really to just respond to an HTTP request, usually with HTML. As with client software you build up a control tree that gets rendered. But, in the case of ASP.NET, it's rendered to HTML and then the control hierarchy is thrown away and there's no code related to the page running on the server backing the page. Postbacks are required to further operate with the server, and ASP.NET makes it fairly transparent that this happens.
One trick that helped me understand things better was suggested in the Architecture chapter of Fritz Onion's Essential ASP.NET 2.0 book. The trick is to insert something like:
<div> The source is in: <%= System.IO.Path.GetDirectoryName(GetType().Assembly.Location) %>.</div>
into the page. In the default compilation model for an ASP.NET page, the first time the page is loaded, it converts the .aspx file into code and compiles it along with your .aspx.cs files. When in debug mode, it will leave the intermediate .cs files it uses in the temp folder with the generated assembly. The files aren't incredibly human friendly, but they are very enlightening. Note: if edit things in Visual Studio and refresh the page in IE, the directory won't change, so you can comment the line above out after figuring out where it is.
I'm going to follow up with a couple of posts on what code actually gets generated in a few different cases as an exercise to learn the internals of ASP.NET better.