Next year Microsoft will be launching Windows Server 2008, Sql Server 2008 and Visual Studio 2008 (VS2008) - Visual Studio 2008 has already been released to RTM and is available for MSDN subscribers as a download.
In version 4.7.0 we introduced a new Solution file that is compatible with VS2008 - DotNetNuke_VS2008.sln, and made sure that the project files were compatible with both VS2008 and Visual Studio 2005 (VS2005), so developers could work in either IDE.
Windows Server 2008 introduces a new version of Internet Information Server - IIS7. IIS7 is also included in Vista, so developers using Vista as their OS have had some experience with IIS7 already.
IIS7 introduces a new ASP.NET Request Pripeline - called Integrated Pipeline. As the name indicates, ASP.NET is fully integrated into the IIS7 pipeline in this mode. In previous versions ASP.NET was bolted on as an ISAPI module. This mode is still supported - it is called "Classic mode".
Ok - that was very technical - but what does it mean for DotNetNuke?
Well, first off - if IIS7 is configured to use the "Classic mode" - and this configuration can be applied to individual "Application Pools", IIS7 runs just like IIS6 or IIS5, so there is no impact on DotNetNuke in this mode.
The real challenge occurs when configuring IIS7 to use an "Integrated Pipeline" (IP) Application Pool, which is the default configuration for IIS7 on both Vista and clean installs of Windows Server 2008. (When IIS7 is being installed as an upgrade to IIS6 - IIS6 Application Pools are automatically configured as Classic mode, so they don't break.)
There are two issues that need to be addressed in IP mode, and which we have been able to address for the next release (4.8.0).
IIS7 configuration uses the application's web.config file for its application level settings. In particular, there is a new element required in web.config called . IIS7 looks in this node for information about the HttpHandlers and HttpModules.
ASP.NET also has a node in web.config where HttpModules and HttpHandlers are configured <system.web> . In "Integrated Pipeline" mode IIS7 requires the <system.webServer> node to be present.
If you look closely at the two main child nodes of this node (modules and handlers) they are similar to the sections defined under the node which is used by ASP.NET.
If the <system.webServer> node is not present IIS7 will display an Error screen when it detects the nodes, due to an invalid configuration file, so we have added the section to both release.config and development.config in 4.8.0.
The third child node in <system.webServer> is critical. This node tells IIS7 to ignore the <system.web> nodes when validating the configuration. This means that we can provide a single web.config that meets both the needs of IIS7 IP mode and IIS7 Classic mode (or IIS6 mode). IIS7 IP mode uses the new node and II7 Classic or IIS6 use the existing nodes. Luckily - the decision to use the new node was made early enough in IIS7's development cycle that ASP.NET 2.0 was designed to ignore (rather than fail) if <system.webServer> was present.
So, DotNetNuke 4.8.0 will include this new section, and the new XmlMerge class (introduced in 4.6.0) will be used to add the new section to existing sites on Upgrade.
One additional point I would like to make on this topic before moving on to the other issue is that the new node was generated using a command line tool which ships with IIS7:
%systemroot%\system32\inetsrv\APPCMD.EXE migrate config "Default Web Site/YourApp"
so if you have your own app that you wish to upgrade for IIS7 IP mode you can use this tool.
The other issue that arises with IIS7 IP mode is that due to the modified pipeline, the Application Start event is fired earlier in the pipeline, before the "Request" and "Response" objects have been created. In the Application_Start event handler in Global.asax.vb, we use these objects to redirect to the InstallWizard if the Application is not installed yet.
We have solved this by implementing the concept of "OnFirstRequest". As the BeginRequest event is the first place in the Application Life Cycle where the Request/Response objects are guaranteed to be instantiated, our code that determines if the Application is installed needed to be moved to the BeginRequest event. The problem is - we don't want this code to run on every request.
The solution was to create a new class - Initialize.vb. All the Application Start methods were moved to this class, and a new Init method was created
This new Init method is called on every Request - in fact it is called in each of the two HttpModules which implement the OnBeginReguest method (and will need to be added to ANY 3rd-party HttpModule that is used in a DNN installation). It uses a Shared private variable "InitializedAlready" to determine if the Application Startup logic has been run. If this value is false it runs the code within the SyncLock block. This code is exactly the same as the old Application_Start code. The SyncLock block ensures that only one request runs the code when multiple requests are initiated at the same time.
As this code works in IIS7 Classic or IIS7 IP modes we have been able to create a single version of DotNetNuke for both IIS modes.
If you would like to move an existing DNN installation to IIS7 IP, first upgrade to 4.8.0, then switch to IP mode.