Since I’ve been back from DevTeach I’ve spent a bit of time converting my West Wind Web Store application to run properly on ASP.NET 2.0 in fact the store on the site is now running on ASP.NET 2.0. I’ll post more about the process in moving in a couple of days.

 

Part of the reason to do this is that the West Wind Web Store is my main business application that I use here for managing my online and offline sales, and I wanted something real to work with. Taking a chance isn't a problem with this app, because the 1.1 app (and even a Fox app as well) is running side by side with it at the moment, so in case of a problem there's an easy fallback. Moving the app took a bit of work, getting through the conversion errors, some subtle differences and figuring out the best way to deploy the app.

 

The biggest issue that I’m still struggling with is compilation of the site and how to manage the process of updating a site. I definitely want to pre-compile my site and the only way that seems to make sense is to compile and make the site not updateable.

 

Anyway, VS.NET doesn’t make deployment easy at all. There’s a Deploy option but currently this dialog doesn’t allow access to all of the features that the compiler has available. For example, it defaults to compiling each and every ASPX/ASCX file into a separate assembly - I prefer the option to build one assembly per directory. The fewer files the better.

 

VS.NET also includes a Site View dialog that is supposed to allow you to transfer files between your project and a live site, but I don’t see how this can work with a precompiled site as the dialog points at the development directory and can’t be changed. This app looks like it hasn't been update since the Alpha when compilation worked completely differently. This app needs to point at a deployment directory and then allow you to copy files from there. <shrug>

 

Anyway, at this point I found myself using the command line compiler a lot to build my project(s) to get single assemblies for each directory. Since this is a hassle I built a small utility that helps me with this process so I don't have to remember long compiler syntax lines:

 

Basically this is a front end the ASP.NET Command Line compiler that can be run without having VS.NET or anything but .NET 2.0 installed. It gives you visual options for the various compiler options (minus the security and signing options which I haven’t looked at yet) plus the ability to choose the runtime version to compile with. You can compile from within the environment and it provides a nice preview of the compiler results which is a bit more readable than what the command line spews out. You can also save a set of settings as a Compiler Configuration so next you need to compile you can just pick from the list of settings.

 

Finally you can also generate a batch file from the current settings that you can add to your project for automatically building your application as part of the build process (in Release mode maybe).

 

Given that I can’t do these simple tasks in VS.NET at the moment this has saved a bunch of time and scrambling for my directions on the command line switches for the ASP.NET Compiler. We can only hope Microsoft will add this functionality into VS.NET directly (it looks like the options are in the configuration, but UI doesn’t allow setting them).

 

I’ve posted this free utility and you can grab it from here:

http://www.west-wind.com/tools/aspnetcompiler.asp

 

I think I got a little carried away with the UI, experimenting with some of the new UI controls in .NET 2.0 <g>. Too bad that databinding still sucks. Damn how many strikes do they need?

Deployment? Not so fast, buddy

When you use the ASPNET_COMPILER.EXE (or the utility above which drives it), it generates output into a directory – it doesn’t deal with sending files up to a server. The VS.NET UI supports this and allows uploading through FTP, HTTP or a remote file path. I tried that actually, but didn’t have much luck – the FTP upload just locked up VS after sending 10 or so files.

 

So, I’ve been using the command line compiler, compiling into a directory and then using FileZilla FTP to send the files to the server. The compiler creates output for your entire directory - everything: ASPX files, code files, images, support files, web.config, project and solution files (if any), SQL files etc. Everything.

  

So, the question is: Would you really want to send your project up lock, stock and barrel? All files to the server? For a first time deployment the answer might be yes. You can send up all of your ASPX files, all your BIN file generated assemblies (all bijillion of them that the compiler generates) and you’re probably good to go.

 

On my first installation I actually sent everything then went back and deleted a handfull of files that shouldn't be there. Couple of things to watch out for: If you store application settings in your Web.Config you might want to make sure that the setting in there are correct and match your SERVER environment and not your development or staging environment. 

 

Ok, so for first time deployment this full on, copy all approach actually works reasonably well. But what do you do once the app is there and you're updating?

 

For me and my apps I usually install the app on the server and then tweak code and once in a while, so usually I upload only new binaries to the server. This is in 1.1. Usually there aren’t new pages or files added to the application only the functionality of the existing binaries changes usually. In 2.0 I don't get that luxury.

 

How about that all or nothing deployment scenario now? I think we can count out the copy everything to the server scenario now. Why should I send all of my images and even the empty ASPX marker files (I compile with the Updateable option off, which generates ASPX files that only have a marker string in them) back up to the server AGAIN? If I do I may get problems with old files that shouldn't be there staying there and I have a maintenance mess.

 

Really I need to update only the BIN directory. But, it’s not that easy here either. The bin directory now is full of crap – depending on your compiler option you’ll have one assembly per ASPX/ASCX/MASTER etc. file or you have one assembly per directory, plus several others like the APP_CODE directory, your resources and a bunch of other generated code. Everything goes into its own assembly. Plus you have a .Compiler file for each file in the project. Since these files get regenerated everytime you compile, they don’t overwrite the old ones either.

 

This means for the BIN directory you don’t get a choice of selectively updating files. YOU HAVE TO UPDATE all of them all at once.

 

Several problems with this: If I copy the files to the server now I end up with two sets of DLLs in my Bin folder which after a few updates gets to be a real mess. I guess after a while I can delete the old files since at least all of the copied files in a compiled project have the same file date. Oh yeah, did I mention: your original file dates in case you needed them are blown away on compilation. That's or the generated assemblies as well as any assemblies that live in the BIN directory of your project for assembly references. Not a big deal for me, but I can see how for some people this will be a problem.

 

Ok, this is mildly annoying, but there’s a much more serious issue here. The fact that all of these files need to be copied to the server and that these files are no longer in one big assembly that gets updated all at once means that ASP.NET sees the new files coming into the BIN folder one at a time. And it will update the application and shadow copy the assemblies one at a time into the application. Depending on the order in which things get up to the server this can cause some serious mismatches in the application.

 

In my quick tests copying 50 or so assembly files in my project's bin directory caused my server to spew server exceptions while the update was in progress. Some requests came through Ok, but most failed until the transfer was complete. This makes sense – while copying files, the application is out of sync. This was a problem in 1.1 too but it was minimal because you had basically one assembly for almost all of your codebehind logic. But now you have pages, App_code, Global_asax all depending on separate assemblies which may not get to the server at the same time and while the app is out of sync it is likely going to fail.

 

Some of the errors were severe enough they even bypassed my error handling that's built into Application_Error. Presumably this can fail to if global.asax or one of its dependencies is 'in transit'.

 

Conveniently the ASP.NET Admin page has an option to take an application Offline. How thoughtful. Only one problem: The functionality is part of the Web Administration interface, which as far as I can see only runs through the local Web server, not a real Web Server. Meaning it’s of no help on a live server.  Regardless I tried it out locally and all that feature apparently does is throw 404 errors when active – hardly the sort of thing you’ll want to show your users.

 

I ended up putting a maintenance flag of my own into my apps and stick that into my Global.asax.cs file:

 

protected void Application_BeginRequest(Object sender, EventArgs e)

{

    if (App.WebStoreOffline)

    {

        //if ( !Context.User.Identity.IsAuthenticated )

        string Virtual = Request.Path.Substring(0,Request.Path.LastIndexOf("/")+1 );

        if (Virtual.ToLower().IndexOf("/admin/") == -1)

            MessageDisplay.DisplayMessage("Hold on",

                                            App.WebStoreOfflineMessage + "<p/>" +

@"Usually these operations only take a few seconds, so please retry your request by using

the Refresh button.");

}

   

}

 

This application specific code gives me a bit more control. I have a static property to control this App.WebStoreOffline, along with a request on my Admin page that toggles this flag on or off. I can get into the admin module by explicitly checking for the /admin/ path of the application – a bit of a heck but a lot more flexible than the default behavior.

 

I suspect this may still fail because there are still dependencies here: The App class and global.asax.cs class or any of its dependencies might still be out of sync.

 

So much for real XCOPY deployment. Maybe a little exaggerated, but I really think we lost some features here that weren't worth loosing over this funky compilation scheme that appears to have no upsides for anybody. 

Where’s the benefit?

So what’s the upside here?  Well, there’s not a whole lot on the plus side. We get an external compiler that we can drive through our projects. And we can precompile the entire site rather than having ASP.NET compile everything as it loads pages. To be honest the latter doesn’t seem to cause any better first page performance than my 1.1 apps. First load of the app is still pretty slow. The overhead is not in the IL generation into assemblies but in the CLR compiling the code into executing binary code and that overhead is still there.

 

What else? Beats me. It looks to me that this whole Pre-Compilation model has made deployment considerably more complicated requiring manual administration, and it has introduced a serious problem for doing live updates that was rarely an issue before.

 

Maybe somebody from Microsoft can explain how this model is supposed to make deployment easier or better or more efficient – maybe I’m missing something obvious.