Microsoft released the .NET Runtime 4.0 and with it comes a brand spanking new version of ASP.NET - version 4.0 - which provides an incremental set of improvements to an already powerful platform. .NET 4.0 is a full release of the .NET Framework, unlike version 3.5, which was merely a set of library updates on top of the .NET Framework version 2.0. Because of this full framework revision, there has been a welcome bit of consolidation of assemblies and configuration settings. The full runtime version change to 4.0 also means that you have to explicitly pick version 4.0 of the runtime when you create a new Application Pool in IIS, unlike .NET 3.5, which actually requires version 2.0 of the runtime.

In this first of two parts, I’ll take a look at some of the changes in the core ASP.NET runtime. In part two, I’ll go over improvements in Web Forms and Visual Studio.

Core Engine Features

Most of the high profile improvements in ASP.NET have to do with Web Forms, but there are a few gems in the core runtime that should make life easier for ASP.NET developers. The following list describes some of the things I’ve found useful among the new features.

Clean web.config Files Are Back!

If you’ve been using ASP.NET 3.5, you probably have noticed that the web.config file has turned into quite a mess of configuration settings between all the custom handler and module mappings for the various web server versions. Part of the reason for this mess is that .NET 3.5 is a collection of add-on components running on top of the .NET Runtime 2.0 and so almost all of the new features of .NET 3.5 where essentially introduced as custom modules and handlers that had to be explicitly configured in the config file. Because the core runtime didn’t rev with 3.5, all those configuration options couldn’t be moved up to other configuration files in the system chain. With version 4.0 a consolidation was possible, and the result is a much simpler web.config file by default.

A default empty ASP.NET 4.0 Web Forms project looks like this:

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true"
                 targetFramework="4.0" />
  </system.web>
</configuration>

Need I say more?

Configuration Transformation Files to Manage Configurations and Application Packaging

ASP.NET 4.0 introduces the ability to create multi-target configuration files. This means it’s possible to create a single configuration file that can be transformed based on relatively simple replacement rules using a Visual Studio and WebDeploy provided XSLT syntax. The idea is that you can create a “master” configuration file and then create customized versions of this master configuration file by applying some relatively simplistic search and replace, add or remove logic to specific elements and attributes in the original file.

To give you an idea, here’s the example code that Visual Studio creates for a default web.Release.config file, which replaces a connection string, removes the debug attribute and replaces the CustomErrors section:

<?xml version="1.0"?>
<configuration
    xmlns:xdt="http://schemas.microsoft.com/XML-
Document-Transform">
    <connectionStrings>
      <add name="MyDB"
        connectionString="Data Source=
                 ReleaseSQLServer;Initial
                 Catalog=MyReleaseDB;Integrated
                 Security=True"
        xdt:Transform="SetAttributes"
xdt:Locator ="Match(name)"/>
    </connectionStrings>
  <system.web>
    <compilation xdt:Transform=
       "RemoveAttributes(debug)" />
    <customErrors defaultRedirect=
       "GenericError.htm"
        mode="RemoteOnly" xdt:Transform="Replace">
        <error statusCode="500"
        redirect="InternalError.htm"/>
      </customErrors>
  </system.web>
</configuration>

You can see the XSL transform syntax that drives this functionality. Basically, only the elements listed in the override file are matched and updated - all the rest of the original web.config file stays intact.

Visual Studio 2010 supports this functionality directly in the project system so it’s easy to create and maintain these customized configurations in the project tree. Once you’re ready to publish your application, you can then use the Publish <yourWebApplication> option on the Build menu which allows publishing to disk, via FTP or to a Web Server using Web Deploy. You can also create a deployment package as a .zip file which can be used by the WebDeploy tool to configure and install the application. You can manually run the Web Deploy tool or use the IIS Manager to install the package on the server or other machine.

You can find out more about WebDeploy and Packaging here: http://tinyurl.com/2anxcje.

Improved Routing

Routing provides a relatively simple way to create clean URLs with ASP.NET by associating a template URL path and routing it to a specific ASP.NET HttpHandler. Microsoft first introduced routing with ASP.NET MVC and then they integrated routing with a basic implementation in the core ASP.NET engine via a separate ASP.NET routing assembly.

In ASP.NET 4.0, the process of using routing functionality gets a bit easier. First, routing is now rolled directly into System.Web, so no extra assembly reference is required in your projects to use routing. The RouteCollection class now includes a MapPageRoute() method that makes it easy to route to any ASP.NET Page requests without first having to implement an IRouteHandler implementation. It would have been nice if this could have been extended to serve *any* handler implementation, but unfortunately for anything but a Page derived handlers you still will have to implement a custom IRouteHandler implementation.

ASP.NET Pages now include a RouteData collection that will contain route information. Retrieving route data is now a lot easier by simply using this.RouteData.Values["routeKey"] where the routeKey is the value specified in the route template (i.e., "users/{userId}" would use Values["userId"]).

The Page class also has a GetRouteUrl() method that you can use to create URLs with route data values rather than hard coding the URL:

<%= this.GetRouteUrl("users",new {
    userId="ricks" }) %>

You can also use the new Expression syntax using <%$RouteUrl %> to accomplish something similar, which can be easier to embed into Page or MVC View code:

<a runat="server"
href='<%$RouteUrl:RouteName=user, id=ricks
%>'>Visit User</a>

Finally, the Response object also includes a new RedirectToRoute() method to build a route url for redirection without hard coding the URL.

Response.RedirectToRoute("users", new { userId =
"ricks" });

All of these routines are helpers that have been integrated into the core ASP.NET engine to make it easier to create routes and retrieve route data, which hopefully will result in more people taking advantage of routing in ASP.NET.

To find out more about the routing improvements you can check out Dan Maharry’s blog which has a couple of nice blog entries on this subject: http://tinyurl.com/37trutj and http://tinyurl.com/39tt5w5.

Session State Improvements

Session state is an often used and abused feature in ASP.NET and version 4.0 introduces a few enhancements geared towards making session state more efficient and to minimize at least some of the ill effects of overuse. The first improvement affects out-of-process session state, which is typically used in web farm environments or for sites that store application sensitive data that must survive AppDomain restarts (which in my opinion is just about any application). When using OutOfProc session state, ASP.NET serializes all the data in the session statebag into a blob that gets carried over the network and stored either in the State server or SQL Server via the Session provider.

Version 4.0 provides some improvement in this serialization of the session data by offering an enableCompression option on the web.Config <Session> section, which forces the serialized session state to be compressed. Depending on the type of data that is being serialized, this compression can reduce the size of the data travelling over the wire by as much as a third. It works best on string data, but can also reduce the size of binary data.

In addition, ASP.NET 4.0 now offers a way to programmatically turn session state on or off as part of the request processing queue. In prior versions, the only way to specify whether session state is available is by implementing a marker interface on the HTTP handler implementation. In ASP.NET 4.0, you can now turn session state on and off programmatically via HttpContext.Current.SetSessionStateBehavior() as part of the ASP.NET module pipeline processing as long as it occurs before the AquireRequestState pipeline event.

Output Cache Provider

Output caching in ASP.NET has been a very useful but potentially memory intensive feature. The default OutputCache mechanism works through in-memory storage that persists generated output based on various lifetime related parameters. While this works well enough for many intended scenarios, it also can quickly cause runaway memory consumption as the cache fills up and serves many variations of pages on your site.

ASP.NET 4.0 introduces a provider model for the OutputCache module so it becomes possible to plug-in custom storage strategies for cached pages. One of the goals also appears to be to consolidate some of the different cache storage mechanisms used in .NET in general to a generic Windows AppFabric framework in the future, so various different mechanisms like OutputCache, the non-Page specific ASP.NET cache and possibly even session state eventually can use the same caching engine for storage of persisted data both in memory and out of process scenarios.

For developers, the OutputCache provider feature means that you can now extend caching on your own by implementing a custom cache provider based on the System.Web.Caching.OutputCacheProvider class. You can find more info on creating an output cache provider in Gunnar Peipman’s blog at: http://tinyurl.com/2vt6g7l.

Response.RedirectPermanent

ASP.NET 4.0 includes features to issue a permanent redirect that issues as an HTTP 301 Moved Permanently response rather than the standard 302 Redirect respond. In pre-4.0 versions you had to manually create your permanent redirect by setting the Status and Status code properties - Response.RedirectPermanent() makes this operation more obvious and discoverable. There’s also a Response.RedirectToRoutePermanent() which provides permanent redirection of route Urls.

Preloading of Applications

ASP.NET 4.0 provides a new feature to preload ASP.NET applications on startup, which is meant to provide a more consistent startup experience. If your application has a lengthy startup cycle it can appear very slow to serve data to clients while the application is warming up and loading initial resources. So rather than serve these startup requests slowly in ASP.NET 4.0, you can force the application to initialize itself first before even accepting requests for processing.

This feature works only on IIS 7.5 (Windows 7 and Windows Server 2008 R2) and works in combination with IIS. You can set up a worker process in IIS 7.5 to always be running, which starts the Application Pool worker process immediately. ASP.NET 4.0 then allows you to specify site-specific settings by setting the serverAutoStartEnabled on a particular site along with an optional serviceAutoStartProvider class that can be used to receive “startup events” when the application starts up. This event, in turn, can be used to configure the application and optionally pre-load cache data and other information required by the app on startup.

The configuration settings need to be made in applicationhost.config:

<sites>
  <site name="WebApplication2" id="1">
    <application path="/"
    
         serviceAutoStartEnabled="true"
         serviceAutoStartProvider="PreWarmup" />
  </site>
</sites>
<serviceAutoStartProviders>
  <add name="PreWarmup"
       type="PreWarmupProvider,MyAssembly" />
</serviceAutoStartProviders>

Hooking up a warm up provider is optional so you can omit the provider definition and reference. If you do define it, here’s what it looks like:

public class PreWarmupProvider
   System.Web.Hosting.IProcessHostPreloadClient
{
    public void Preload(string[] parameters)
    {
        // initialization for app
    }
}

This code fires and while it’s running, ASP.NET/IIS will hold requests from hitting the pipeline. So until this code completes, the application will not start taking requests. The idea is that you can perform any pre-loading of resources and cache values so that the first request will be ready to perform at optimal performance level without lag.

Runtime Performance Improvements

According to Microsoft, there have also been a number of invisible performance improvements in the internals of the ASP.NET runtime that should make ASP.NET 4.0 applications run more efficiently and use less resources. These features come without any change requirements in applications and are virtually transparent, except that you get the benefits by updating to ASP.NET 4.0.

Summary

The core feature set changes are minimal which continues a tradition of small incremental changes to the ASP.NET runtime. ASP.NET has been proven as a solid platform and I’m actually rather happy to see that most of the effort in this release went into stability, performance and usability improvements rather than a massive amount of new features. The new functionality added in 4.0 is minimal but very useful.

A lot of people are still running pure .NET 2.0 applications these days and have stayed off of .NET 3.5 for some time now. I think that version 4.0 with its full .NET runtime rev and assembly and configuration consolidation will make an attractive platform for developers to update to.

If you’re a Web Forms developer in particular, ASP.NET 4.0 includes a host of new features in the Web Forms engine that are significant enough to warrant a quick move to .NET 4.0. I’ll cover those changes in my next column. Until then, I suggest you give ASP.NET 4.0 a spin and see for yourself how the new features can help you out.