ASP.NET 2.0 and Visual Studio 2005: You win some, you lose some
Now that ASP.NET 2.0 and Visual Studio 2005 have been out for a few months and many of us have had some time to use the product in a day-to-day environment, it's interesting to take stock of the changes and how they affect the development environment and flow. For me, ASP.NET 2.0 and Visual Studio 2005 have been a bit of a love/hate relationship.
There are many new features in ASP.NET 2.0 that just make life a lot easier and make it hard go back to 1.1 for coding. In my own work, I've decided to move up most of my internal applications to 2.0 and not look back. So far, it has worked out great. There are many improvements that have reduced coding, improved performance, and reduced memory footprint, even with almost no changes at all. Moving to embrace more of the 2.0 feature set in existing applications is not something that will happen overnight, but I am finding myself rapidly including many 2.0 features in my applications. In the end, going back to ASP.NET 1.1 and Visual Studio 2003 would seem like a huge step backward.
Here’s a list of some of the key features that I find most useful and that it’s hard to do without.
File-based Projects in Visual Studio 2005 for Development
In Visual Studio 2005, you can now open a directory as a Web Project, which is very nice. On my development computer, I probably have 50 different Web projects hanging around; configuring and maintaining all of these as virtual directories in IIS and keeping the project references right like in Visual Studio 2003 is a pain. You don't think so? Have you ever tried to move projects to a new computer? In Visual Studio 2005, you point at a directory and the project opens. You can use the built in local Web server to run the application, which eliminates the need to configure a Web server in any way. This feature is also great for developers who share examples; anybody who wants to check out a sample Web application doesn't have to go through the pain of configuring virtuals on IIS. Instead you now have, at least for development scenarios, the true promise of xCopy projects. This is a great feature, but not one that comes without pain (more on this later).
The ability to define a Master Page template and reuse this master template easily throughout your application is a huge timesaver. There were ASP.NET 1.x-based implementations of this concept floating around before 2.0 shipped, but to me, the key feature that makes this viable is the visual support for it in Visual Studio. This way, you can see the Master layout along with the ContentPlaceholders used in each page to provide the page-level content. In addition to the important visual aspect of the designer, Master Pages are also great to hook related and reusable code into the Master template. Because Master Pages tend to wrap a fair amount of functionality that often required several user controls (for example, header, footer, sidebar), Master Pages can isolate logic more completely than you could before.
Visual Representation of User Controls
I prefer to see what the whole page looks like while I'm designing it. Like Master Pages, Visual Studio 2005 can display a rendered User Control in place in the Web Form Editor. You no longer have a non-descript grey box with a control name, but you now have a fully rendered layout right there in the Designer. Double-click and Visual Studio takes you to the User Control Designer. Although I don't use a lot of user controls, I find that this makes design mode a lot more useful, especially for my existing 1.1 applications that generally used user controls for headers, sidebars, and footers. I foresee many of my existing user controls being replaced by Master Pages.
Ok, this isn't an ASP.NET-specific feature, but Generics in .NET 2.0 has had a profound effect on the code that I write. In the past, I'd been very wary of creating custom collections because frankly, it was a pain in the butt having to subclass from CollectionBase and then reimplement the same code over and over again. In ASP.NET especially, I find that generic collections work really well for custom control development when you need collection properties. Use List<YourType> or one of the specialized generic collections as a property of the control and you're done. Visual Studio sees the collection and provides the collection editor for you in most cases. Using Generic Lists also lets me easily remove many ArrayList-based lists as strongly typed lists, which makes code cleaner in many places. Finally, using dynamic type replacement in business objects removes a fair amount of funky initialization code that had to be specified in each object to define which type to work with for entity objects. All that configuration code could be replaced simply by making the type generic and assigning a single generic parameter to the class. All class-level code can now generically use that generic class description to automatically generate the correct types at run-time. This has removed a huge chunk of traditionally cut-and-pasted code from all of my business objects and replaced it with one type parameter and a couple of class-level methods. There are many more places where Generics have had a similar effect on my code and I find it hard to go back to not using Generic types and collections.
Support for Embedded Resources
I tend to build a lot of custom controls for my own applications and occasionally for the tools and demos I put out. If you build controls that require dependent resources such as images, CSS files, and XML resources, it's a pain to have consumers of the control remember to distribute the appropriate files with their applications. Web Resources in ASP.NET allow you to easily embed and then access resources from within a project as a dynamic URL that ASP.NET generates. You simply add the [WebResource] attribute to your control's AssemblyInfo file and then use Page.ClientScript.GetWebResourceUrl to retrieve the URL that contains the resource content.
The Visual Studio ASP.NET Code Editor
The code editor in Visual Studio is a huge step up from the 2003 version. Most importantly, the new editor doesn't wreck your code formatting unless you reformat the document. In Visual Studio 2003, this was a huge issue for me where I tried to keep my content organized and Visual Studio gleefully stepped on it and reformatted the HTML for me when new controls were added. In Visual Studio 2005, the editor keeps the code intact for most things and also does a much better job with the default insertions of control markup into the code. Another big feature that enhances my productivity is IntelliSense in the HTML editor-it's everywhere! I tend to embed <%= %> expressions into the page frequently and having IntelliSense in place is very handy to avoid typos. ASP.NET also compiles the page and checks the embedded script code generated now, so that errors in the HTML markup can be caught at design time rather than run-time. IntelliSense also works for all controls, including your own. You no longer have to provide an undocumented schema file. Visual Studio simply finds your control and internally manages the IntelliSense. The IntelliSense support is good enough that it almost makes sense to skip the Visual Designer altogether and work in code. You'll see why this is actually more important then you might think in a minute.
The truth is that I could go on and on about features in ASP.NET 2.0 and Visual Studio 2005 that I now use frequently. Suffice it to say that there are many useful and productivity-enhancing features in Visual Studio 2005 that make it a very hard call to have to go back to ASP.NET 1.1 and Visual Studio 2003. Add to that a 10-20% performance gain without any changes from 1.1 at all and a smaller memory footprint, both also important to larger applications.
But there are also a number of issues with ASP.NET 2.0 and more specifically Visual Studio 2005 that don't sit well with me. It seems that although the ASP.NET 2.0 engine is very stable, tuned, and performing well, Visual Studio doesn't fare nearly as well.
Visual Studio 2005 is Slow, Slow, Slow, Especially for ASP.NET Applications.
I used to think that Visual Studio 2003 wasn't exactly a speed demon when it came to bringing up projects and switching views between documents, especially on Web Forms switching among code, HTML, and Design views. In Visual Studio 2005, the performance of the editing environment is considerably slower, especially for context switches between code and the Designer. It’s so slow that when I go back to Visual Studio 2003, I'm amazed at just how fast the older version is. The main issue seems to be the Web Form editor, which is dreadfully slow rendering controls onto the form. I have several large forms with about 50-70 controls on them and these forms take upward of 15 seconds to load for every context switch. I recently bought a new dual core laptop and while everything on my computer runs blazingly fast, Visual Studio 2005 is the one application I can say is still not even close to as responsive as I would like. If you are upgrading, make sure you have a fast computer and LOTS OF memory. Running Visual Studio commonly results in nearly 500 megs of memory usage on my computer for Devenv.exe alone. Add to that either IIS's worker process or the Visual Studio Web Server plus browsers, and you can easily chew through 2 gigs of memory.
Visual Studio 2005 Web Designer Bugs
The biggest time sink in Visual Studio 2005 is the variety of editor bugs I have found, as have many others (see also: http://www.west-wind.com/weblog/posts/3192.aspx). Most of these are non-critical, but they are highly annoying and waste lots of time. Here are a few of the more annoying examples:
The most frequent bug I run into is where the Visual designer refuses to switch focus to another control. You click on a new control, but the property sheet stays locked on the first control. You have switch into HTML view and then back to get it to work.
In some instances, when you try to rename a control, Visual Studio won't let you. It says there are already references in the mark up and asks if you want to continue. If you continue or not, the rename doesn't take and you have to switch to HTML view to change the name. Even when renames from the Web designer do work, they are very, very slow in a large project, as Visual Studio is doing a full refactoring on the new name. It can take 10-20 seconds plus a dialog box click for the rename to complete. Now, keep in mind, we're changing the name of a PROTECTED control attached to a Web Page here. Why is Visual Studio searching through the whole project/solution? I think it's safe to assume that a name change to a Designer page control isn't going to have much effect outside of the current page scope. Talk about the 99% scenario getting the shaft so that the 1% scenario (a subclassed page used elsewhere) can work reliably. Besides, if you change the control name in HTML view, there are no checks at all. I expect the Web designer to behave the same.
Another annoying bug is using stock collections and the default Collection Editor. If you rename the default item names to a custom name, Visual Studio 2005 simply doesn't save the changes. It blows away the properties and items you've entered. You have to use the default names or change the names in HTML view, and then you can edit with the Collection Editor.
If you have style sheet references in the page, Visual Studio .NET doubles up the style references randomly. I recently opened a page that had 10 of the same CSS references in the file.
Another issue that's not a bug but an odd implementation of a feature is that Visual Studio .NET 2005 flags HTML validation errors as errors. Validation errors are grouped in the same error list as a break-the-build error. Not only is the HTML validation overly literal with what if flags (example: it doesn't understand named colors), but it gets in the way of seeing real application errors. It's not uncommon for me to have 20-30 HTML ”errors” and one code error. The code error is at the bottom but there's no visual separation. Validation is useful, but it needs to be separate and easily toggled on and off, ideally with a separate error tab. Instead, you can turn it on and off in the Options: it’s all or nothing.
The list could go on and on with these small but time-sapping little bugs. The end result is that I spend a lot more time in HTML view than I should. Luckily, HTML view is a lot more useful in Visual Studio 2005 with IntelliSense making it much easier to enter property settings in code. I tend to use the Designer to drop my controls on the form and move them into place, then use HTML view for most of my property assignments: at this point it's simply more efficient to work this way. But it shouldn't have to be this way.
Web Projects Aren't Real Projects
ASP.NET projects aren't real Visual Studio .NET projects; they're a custom project type that is based on the operating system file system by default. If you open an ASP.NET Web project, it pulls in any and all files below that project folder. This means that you really have no control over what gets pulled into your ”project.” One particularly disastrous example is my root Web site, which sits on top of a large number of virtuals. There are probably 50,000 files below the Web root. When I opened the root in Visual Studio .NET, it pulled in all of that-images, XML files, doc files, utilities-everything. It took about 20 minutes to open that project.
File projects have no way of excluding anything. Any file in the tree becomes part of your project. That includes images, support files, configuration utilities, documentation files-all of which have little to do with my project. The reason for this is that there really is no “project.” A few things, like the path mapping etc., are stored with the solution, but overall, there's none of the typical project configuration available that you see in class projects.
ASP.NET 2.0 compiles projects using a new ASPNET_COMPILER utility that copies everything to a deployment directory. So not only is your project huge, but compiling it copies the entire project-including images and support files-to a new location. As you can imagine, this process is very slow. Compiling a medium-sized Web of about 50 ASPX pages takes a good 30-40 seconds on my dual core computer. Compare that with only a couple of seconds for the same project under Visual Studio 2003. Granted, the compilation is more complete and the results are in a deployment directory, but while developing, 30-40 seconds is too long. It takes so long that I rarely compile my Web project. Most of the time, I work on a page, test run it, and move on, but rarely do I do a full compile. The compile cycle is just too slow.
Any code outside of CodeBehind pages stored in the same path as the ASPX files needs to reside in the APP_CODE folder. Everything in APP_CODE is compiled and can contain plain classes and controls. Be careful if you create backup files: for example, I often do things like copying Control1.cs to Controlbak.cs. Because both controls now exist in the same project with the same code, this causes a compilation error as you end up with duplicate classes.
All the project dialog boxes look different than the stocked projects in Visual Studio .NET. There's no stock AssemblyInfo file, no support for XML comments, and no direct MSBUILD support for a Web project. There is no “project.” All the information about the application is stored based on the filesystem layout and a few Solution file settings.
One workaround for the massive file importing of file projects is to use IIS Web projects instead, which requires explicitly adding files. This is a little closer to the old model and at least respects virtual directory boundaries.
To Microsoft's credit, they are aware of the project and compilation issues and have started to provide a new Web Application Projects add-in (see also: http://msdn.microsoft.com/asp.net/reference/infrastructure/wap/default.aspx) that is still in beta. It provides Visual Studio 2003-style Web projects (with some enhancements for the 2.0 functionality, including file-based project access). This tool addresses most of the concerns I've raised here about page compilation as it produces a single assembly that gives access to all types and the project management features that have gone missing in Visual Studio 2005 Web Project. It works well, but it's still in beta and still has a few rough edges.
Deployment of Web Applications
Deploying ASP.NET applications got a whole lot more complicated with ASP.NET 2.0. You now have many, many options for deploying your applications, some of which overlap, none of which are simple, and none of which produce a repeatable install. The new ASPNET_COMPILER utility is used to compile projects into a deployment folder. Options exist to compile every page in a single assembly or group all pages into a single assembly per directory, but none of the options produce a single assembly to deploy. In fact, there are lots of files to deploy, including stub files and assemblies for APP_CODE and Master Pages.
Microsoft apparently intended people to completely re-deploy applications every time an update is made. The compilation creates a deployment folder with a copy of the Web site. Visual Studio 2005 includes tools that let you upload the deployment folder to your Web site, but that's pretty unrealistic. Typically, you need to adjust web.config and possibly other configuration files, and you certainly wouldn't want to redeploy all of the incidental files-like images-for every update. But you can't update a site by simply copying one file with this new model.
The simplest install is a source install that deploys exactly as you are developing, installing both ASPX and code-behind source code on the server. Both are compiled on the fly. This is easy to deploy and you don't actually need to run ASPNET_COMPILER, but it's not exactly secure and you have to track changes to all source files.
You can deploy compiled assemblies for each page, which create one assembly per page that are stored in the BIN directory. That would be OK, except every time ASPNET_COMPILER is run, the timestamp and file name changes, so the next time you upload you have to clean up the old compiled files. Options allow you to compile both ASPX and CS files or leave the ASPX file intact and let ASP.NET compile the ASPX page content at run-time.
You can also group directories together into a single assembly of all ASPX files in that directory. This produces fewer assemblies, but unfortunately there are marker files for every page which-you guessed it-change names on every compile. So the number of files is no less with this kind of installation. In both cases, additional assemblies are created for the APP_CODE directory, Master Pages, and a few other separated files, all of which are dynamically named.
The worst thing about this deployment is that there's no quick and dirty way to deploy with the stocked options. You have to remove files on the server before you copy them back up. And while you're copying files to the server, your application is in a very unstable state as there are many files that can become out of sync while uploading. In short, live updates are not really possible on a busy site.
Microsoft has heard the message from developers a little late and has made an add-in tool available, called Web Deployment Projects (see: http://msdn.microsoft.com/asp.net/reference/infrastructure/wdp/default.aspx), and that is in Beta. This tool builds on top of the ASPNET_COMPILER functionality and can combine all the assemblies into a single assembly. Further, it can create stub files that have a consistent name, so you can create a repeatable deployment image. The tool also allows custom build actions to modify Web.Config files easily for deployment on the fly. This add-in provides a new Visual Studio .NET project type and you can use MSBUILD to customize the process. I've been using the command line version of the tool for my deployment needs and it works much better than the stock behaviors. It makes the process much more manageable. The Web Application Projects tool mentioned in the previous section also addresses this scenario, as it builds a single assembly from all CodeBehind code.
With all these choices available, I created a GUI front-end to ASPNET_COMPILER and the Web Deployment Projects with a West Wind ASP.NET 2.0 Compiler Utility (http://www.west-wind.com/tools/aspnetcompiler.asp). The tool lets you experiment with the various different compilation modes, save the configuration, create batch files, and more.
Will Microsoft Do the Right Thing?
There are a number of things that bug me about ASP.NET 2.0 and Visual Studio 2005, but there are also many things that make life a lot easier for development. The productivity and feature gains and the slowness and bugs roughly offset each other in net productivity in my estimation. But with a little effort on Microsoft's part, it could be so much better.
It's not there yet. When I stand in front of developers describing some of these issues at presentations, one look at their faces says it all: "this stuff looks like beta software”. It happens all the time. I can't tell you how many people have asked me whether they should upgrade to Visual Studio 2005 and whether it's “good enough.” I'd say yes it is, but don't expect a bug-free environment in Visual Studio.
Microsoft is aware of the issues and I've seen many Microsoft developers get involved in blogs and message boards to address these issues. So if and when a Service Release for Visual Studio .NET 2005 becomes available, most of these issues should be resolved. I sincerely hope that Microsoft is making a strong commitment to fixing these and other issues and fixing them sooner rather than later. Microsoft has a tendency to move on to the next big thing and already we're hearing talk about the next version of Visual Studio .NET (Orcas). Let's hope that this release can still be made all that it was meant to be for so many years.