OdeToCode IC Logo

Return of the Web Project

Sunday, December 18, 2005 by scott

Do you remember the mood at the end of “The Empire Strikes Back”? Darth Vader froze Han Solo in carbonite, then proceeded to slap Luke around like a hockey puck. Just when we thought all was lost, along came “Return of the Jedi”. Luke broke out some new kung-fu moves, and Princess Leia donned a bikini (which perhaps not surprisingly, spawned this website). The galactic mood was on a definite upswing.

Similarly, the “project-less” web project in Visual Studio 2005 left little hope for some ASP.NET applications to make an easy transition to 2.0. Fortunately, ScottGu announced a preview of the Web Application Project model this week.

The preview has rough edges – but is familiar. Familiar because the project based WAP model works like the Visual Studio 2003 model. Code-behind files compile into a single assembly. The model is also familiar because it works like the Windows Forms designer model, the Windows Workflow designer model, the typed DataSet designer model, the WinFX / Avalon designer model, and so on.

I hope the final release will parse @ MasterType and @ Previous page directives, as well as profile settings, to make strongly typed properties available in code-behind. Pre-compilation with aspnet_compiler.exe appears to work against the new project type, which is good.

Will Web Application Projects make migration easier? Certainly, the mental migration from 1.1 to 2.0 will be easier. The codebase should also experience fewer hiccups. I wonder if the migration tool will attempt to separate the designer generated code and developer code living together in today’s code-behind files. Breaking up is hard to do, but keeping designer goo in a separate partial class is nice.

Death by Unhandled Exception

Wednesday, December 14, 2005 by scott

In .NET 1.1, an unhandled exception would terminate a process only if the exception occurred on the main application thread. The runtime would silently swallow unhandled exceptions on other threads to prevent termination. I’ll leave it for the reader to decide if this is behavior is naughty or nice.

In .NET 2.0, unhandled exceptions on any thread will most likely terminate the application (see Exceptions In Managed Threads for details). For ASP.NET developers taking threading into their own hands to implement a “fire and forget” strategy, it’s important to realize this change in behavior. Imagine the following code inside a web form.

protected void button1_click(object sender, EventArgs e)
{
doWork(
null);
}

protected void button2_click(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(
new WaitCallback(doWork), null
);
}

protected void doWork(object state)
{
string s = state.ToString();
}

Both button event handlers ultimately call the doWork method and pass a null value as the parameter. The doWork method will always throw a NullReferenceException. The button1_click method calls doWork synchronously. Since the exception in doWork occurs on a thread processing a request, the ASP.NET runtime will catch the exception and throw up the default ASP.NET error page. One technique for globallylogging these types of exceptions is to wire upApplication_Error.

The button2_click method uses a second thread to execute doWork. The second thread is not in a request processing context, so the exception will not be seenin the Application_Error event handler. This is true for QueueUserWorkItem and when working with aThread object directly. Note: I’m not encouraging anyone to use either QueueUserWorkItem or Thread.Start in ASP.NET. I generally recommend you avoid spinning off work unless you know what you are doing. Asynchronous pages might be what you are looking for instead.

In ASP.NET 1.1, the runtime would swallow the NullReferenceExceptionfrom the second thread and the application would continue in blissful ignorance - not so in ASP.NET 2.0. Here is what happens when doWork executes on a second thread with the WebDev server.

dead webdev

This couldn’t happen with IIS, right? Well, on XP (IIS 5), you won’t see an error dialog box, but check the Application event log afterwards….

aspnet_wp.exe (PID: 316) stopped unexpectedly.

For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.

It’s dead, Jim.

With IIS 6, w3wp.exe willgo down in flames. Iusually see two event log entries left behind. The first entry is a warning entry with healthy amounts of detail, including a stack trace if pdb files are available. The second entry is cryptic:

EventType clr20r3, P1 w3wp.exe, P2 6.0.3790.1830, P3 42435be1, P4 app_web_pion_w1z, P5 0.0.0.0, P6 439f8d74, P7 3, P8 1, P9 system.nullreferenceexception, P10 NIL.

Of course, another ASP.NET worker process will rise upimmediately afterwards, buttermination is just notin the "good thing" category.Make sure you have a try / catch in place if you are using your own threads in ASP.NET 2.0.

CLR Profiler and the WebDev Server

Monday, December 12, 2005 by scott

CLR Profiler for the .NET Framework 2.0 is available for download.

The profiler is a good tool to use when you want to find out what’s happening in memory. For instance, ASP.NET developers using InProc sessions state are always curious about how much memory they are using. Assuming the web project is file system based, the first step is to get CLR Profiler to work with the development web server: WebDev.WebServer.exe.

The profiler can’t attach to a running process, so you have to tell the profiler how to launch the web server. WebDev requires at least two parameters: a port number (/port), and a physical path (/path) to the web application. Once profiler is running, you can use the File -> Set Parameters menu option and enter these parameters. The command line parameters together will look like /port:2112 /path:”c:\src\webapp1”.

With parameters set, you can launch the web server by clicking “Start Application” in the profiler form and browse to WebDev.WebServer.exe in the framework installation directory (typically \Windows\Microsoft.NET\Framework\v2.0.xxxx). The server icon will appear in the tray, where you can right click the icon and select “Open in Web Browser”. The application might feel sluggish during profiling.

While interacting with the web application you can press “Show Heap Now” to view a heap graph. A heap graph can be a busy looking diagram, but you can filter the view. For instance, to see what’s hanging around in session state, right click the graph and choose “Filter”. Enter “System.Web.SessionState” to filter the types, and you’ll be able to see the type and size of objects in session.

The CLRProfiler.doc file included with the tool contains a solid tutorial on using and interpreting profiler results. The document is worth a read, even if you don’t plan on using the tool right away. Someday it might come in handy.

Taking Care Of Pre_Init

Saturday, December 10, 2005 by scott

The Page class exposes a Pre_Init event because the MasterPageFile and Theme properties need to be set early in the lifecycle of a web form. Pre_Init is the event to hook if you want to assign these properties dynamically in code. The natural question is how to implement master page and theme selection for all web forms in an application without adding a Pre_Init event handler to every single web form.

Brock Allen has one elegant solution, which is to use an HttpModule. Brock’s module hooks the PreRequestExecuteHandler and ultimately handles all the PreInit events with a single method in an HttpModule. I haven’t touch VB in a week, so here is what that solution would look like in VB:

Imports System.Web

Public Class MasterAndThemeModule
    
Implements IHttpModule

    
Public Sub Dispose() Implements IHttpModule.Dispose
    
End Sub

    Public Sub Init(ByVal context As System.Web.HttpApplication) _
            
Implements IHttpModule.Init

        
AddHandler context.PreRequestHandlerExecute, _
                  
AddressOf Application_PreRequestHandlerExecute
    
End Sub

    Public Sub Application_PreRequestHandlerExecute(ByVal sender As Object, _
                                                    
ByVal e As EventArgs)
        
Dim application As HttpApplication
        application =
DirectCast(sender, HttpApplication)

        
Dim page As Page
        page =
TryCast(application.Context.CurrentHandler, Page)

        
If Not page Is Nothing Then

            AddHandler page.PreInit, _
                    
AddressOf Page_PreInit
        
End If
    End Sub

    Public Sub Page_PreInit(ByVal sender As Object, ByVal e As EventArgs)

        
Dim page As Page
        page =
DirectCast(sender, Page)
        page.MasterPageFile =
"code to select master page"

    End Sub

End
Class

You could drop the above code into an App_Code file and configure the module in web.config like so:

<httpModules>
   <
add name="MasterAndThemeSelection" type="MasterAndThemeModule"/>
</
httpModules>

Of course, the beauty of an HttpModule is that you could put the code into a class library and configure the module to run in a number of applications.

The alternative is to use inheritance, which requires a base class derived from the Page class. s

Imports System.Web.UI

Public Class BasePage
    
Inherits Page

    
Public Sub Page_PreInit(ByVal sender As Object, _
                            
ByVal e As EventArgs) Handles Me.PreInit
        
Me.MasterPageFile = "code to select master page file"
    End Sub
End
Class

Any web form that wants to take advantage of the common PreInit event handler will need to inherit from the BasePage class either by changing the Inherits attribute in the @ Page directive (for forms with no CodeFile) or by changing the Inherits line in the CodeFile. Inheritance can be slightly more intrusive, but it’s also easier to opt out of the behavior by not deriving from the BasePage.

Unveiling Visual Studio Commands

Friday, December 9, 2005 by scott
Customize dialog

Visual Studio 2005 customizes it’s menus based on a category you select when running the IDE for the first time (this is true of the Pro edition, I’m not sure about Standard and Express). I typically pick “General Development Settings” to avoid the C#, VB.NET, or Web Developer stereotypes.

The problem with using “General Development Settings” is I can’t develop anything specific [rim shot, cymbal crash].

Seriously, one irritation with the setup is that my menus are probably different from your menus. I read about File -> Export Template, but I don’t see any such command on my File menu. I’ve also missed familiar commands like Debugging -> Step Into, and some commands I find useful are hidden (Close All But This).

The solution is to use the Tools -> Customize dialog and drag commands into menus and toolbars where I can use them.

Once I get code snippets and settings setup just the way I like, I use the recently acquired and free FolderShare application to synchronize customizations across a number of computers.

That all for tonight, you’ve been a great audience! Remember to tip your servers, and try the veal!

Now playing: Wayne Newton - Danke Schoen

Snippets

Tuesday, December 6, 2005 by scott

Code snippets are a great productivity feature in Visual Studio 2005 (or a mind rot – depends on your perspective). Michael Palermo even has a site dedicated to code snippets: GotCodeSnippets.com.

Code snippets are easy to author. I became tired of typing in the same keystrokes to start a unit test, and wrote a snippet myself. Now I type tm+TAB+TAB, and voilà, the following code appears. A savings of 20 keystrokes:

[Test]
public void Test()
{

}

The word Test is highlighted in green as a replacement – I can type over the word with a new method name. All of this is setup by dropping the a .snippet file into My Documents\Visual Studio 2005\Code Snippets\Visual C#\My Code Snippets. Here are the contents:

<xml version="1.0" encoding="utf-8" ?>
<
CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
   <CodeSnippet Format="1.0.0">
      <Header>
         <Title>Test Method<Title>
         <
Shortcut>tm<Shortcut>
         <Description>Code snippet for a unit test<Description>
         <
Author>scott@OdeToCode.com<Author>
         <
SnippetTypes>
            <
SnippetType>Expansion<SnippetType>
            <
SnippetType>SurroundsWith<SnippetType>
         <SnippetTypes>
      <Header>
      <
Snippet>      
         <
Declarations>
            <
Literal>
               <
ID>nameID>
               <
ToolTip>Method name<ToolTip>
               <
Default>Test<Default>
            <Literal>
         <Declarations>
         <
Code Language="csharp">   
    public void $name$()
   {
      $selected$
   }
   
]]
         <Code>
      <Snippet>
   <CodeSnippet>
<CodeSnippets>

It looks like a lot of work, but if you copy an existing snippet it’s almost too easy.

Snippets are better in VB.NET. A code snippet in VB.NET can add Imports for required namespaces to the source file, and reference any required assemblies when it expands. C# cannot. Perhaps this explains why there are over 350 VB.NET code snippets installed by Visual Studio, and only 50 for C#. It would be great to write a TestFixture snippet for C# that automatically added a using NUnit.Framework, and added a project reference to the NUnit assembly. Perhaps in the next version…

The Great Migration

Sunday, December 4, 2005 by scott

I popped into the Central Penn Code Camp this weekend and did a presentation on ASP.NET 2.0. There are plenty of presentations on the new features of ASP.NET - membership and master pages, web parts and wizard controls, the list goes on forever.

I took a different approach.

The problem is, you don’t get all the new features for free. 1.x programmers need to unlearn a few concepts, and migrate their existing code. The changes catch people off guard because the changes don’t get as much attention as the bells and whistles. Migration makes people angry. I know, because I have angry people on my contact list (names withheld to protect the angry).

Ms X: why did they change it
Ms X: I HATE MICROSOFT
Scott: it gets better after the migration
Ms X: it teases you
Ms X: you think you have it done and then it finds more errors
Scott: i know it’s frustrating
Ms X: what was microsoft thinking? were they thinking at all?
Scott: of course they thought about it
Ms X: im pretty close to never switching
Ms X: tell microsoft they just lost one developer
Scott: it will work, don’t give up
Ms X: do you know anyone else who converted a production app?
Scott: yes
Ms X: who wasn’t an MVP or part of some microsoft whitepaper?
Scott: yes
Ms X: i dont trust you
Ms X: i think ur biased
Scott: dont attack me, im trying to help

My presentation was about what you should know before making the transition / migration. I used 5 minutes of slides and 70 minutes of Visual Studio. Here are some of the online resources I mentioned during the presentation. If you arm yourself with this information before jumping in, the water won’t seem so deep.

Scott Guthrie: VS2005 Web Project System: What is it and why did we do it? Yes, Microsoft did think about the changes.

MSDN: Step-By-Step Guide to Converting Web Projects from Visual Studio .NET 2002/2003 to Visual Studio 2005. Don’t go in blind, go in with a plan.

MSDN: Common ASP.NET 2.0 Conversion Issues and Solutions. The migration tool is still undergoing some improvements. This document explains some of the pitfalls.

Scott Guthrie: HTML Validation Checking (and how to turn it off). I recommend you turn off HTML Validation checking when migrating a project and concentrate on getting a working application. Once all the migration issues are resolved, turn validation back on.

MSDN: Web Deployment Projects. This is an invaluable tool for moving bits into production. It is still a beta preview. Most of the issues I’ve seen with the tool revolve around merging assemblies.

Rick Strahl: Understanding Page Inheritance in ASP.NET 2.0. Rick provides excellent coverage of the how the new model works, why the new model is an improvement, and what to watch out for.

Me: Debug & Release Builds in ASP.NET 2.0. This post also covers a lot of the compilation differences.