This article applies to Mono version 2.7 (at least SVN revision 157449) or newer
With this post I am starting a series of post on new features found in ASP.NET 4.0 and Mono 2.8.
There's no real schedule to the series, I will post new articles as code gets committed to Mono and
whenever I have time to develop a sample or two to demonstrate the feature.
ASP.NET 4.0 introduces a feature described by Phil Haack in
his recent post. Ability to execute methods before application starts is useful to register BuildProviders without the need to modify web.config - this is
its primary purpose, as Phil states in his post, but not the only possible use. Application can take advantage of this feature to provide code to perform early
site setup (steps which do not require user feedback or interactivity - creating cache directories, populating freshly installed application with sample content,
performing access checks etc) or to load dynamically configurable plugins. After a quick recap of how the feature works, I will describe a simple example of such
an application which performs both of the above steps.
To execute code before ASP.NET compiles your site and creates an instance of HttpApplication (or a derived class, if your application has it) you need to take
advantage of a new custom attribute introduced in ASP.NET 4.0, PreApplicationStartMethodAttribute. This attribute can be used once per each assembly in your application's bin/ folder. Attribute takes two parameters - type which contains your pre-application start method
and a method name. Method must be public static and can take no parameters. Code from sample accompanying this article which demonstrates the usage:
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Web;
using PreApplicationStartSupport.Core;
// There can be only one such attribute instance per assembly.
[assembly:PreApplicationStartMethod (typeof (PreApplicationStart.Application.Init), "InitializeApplication")]
namespace PreApplicationStart.Application
{
public class Init
{
public static void InitializeApplication ()
{
// perform initialization
}
}
}
There are several new 4.0 methods around the ASP.NET class hierarchy which can be called only before or during the pre-application start phase
(two of those methods - BuildProvider.RegisterBuildProvider
and BuildManager.AddReferencedAssembly are mentioned in Phil's
article and pretty well documented on MSDN.
In the sample application, the method shown in the code excerpt above performs all the actions mentioned previously - initial site setup and plugin loading:
public static void InitializeApplication ()
{
string appDir = HttpRuntime.AppDomainAppPath;
string stampFile = Path.Combine (appDir, "App_Data", ".setup_done");
MessageContainer messages = MessageContainer.Instance;
messages.Clear ();
if (!File.Exists (stampFile)) {
messages.Add ("First run - need to perform setup steps.");
RunSetup (messages, appDir);
}
Assembly pluginAssembly = PluginLoader.LoadPlugin ("SamplePlugin");
if (pluginAssembly == null)
messages.Add ("Init: failed to load plugin 'SamplePlugin'");
else
LoadPluginResources (pluginAssembly, messages);
}
As you can see, there's nothing at all special to this code - just a regular method. For the links to full source code, see the bottom of this article.
To run the sample application under Mono, you need to have Mono version mentioned at the top of the post and execute this command, in the application's root
directory:
MONO_OPTIONS="--debug" xsp4
After browsing to
http://localhost:8080/ you will be greeted with the following output (yes, spartan, ugly etc - I know :D):
Event log:
[5/17/2010 6:00:40 PM] First run - need to perform setup steps.'
[5/17/2010 6:00:40 PM] Plugin 'SetupPlugin' loaded successfully.'
[5/17/2010 6:00:40 PM] Init: setup type 'SetupPlugin.Setup' v0.0.0.0 loaded'
[5/17/2010 6:00:40 PM] Setup: creating directories'
* directory /tmp/PreApplicationStart/PreApplicationStart/App_Data/directory1 created'
* directory /tmp/PreApplicationStart/PreApplicationStart/App_Data/logs created'
* directory /tmp/PreApplicationStart/PreApplicationStart/App_Data/backups created'
[5/17/2010 6:00:40 PM] Init: setup successful.'
[5/17/2010 6:00:40 PM] Plugin 'SamplePlugin' loaded successfully.'
[5/17/2010 6:00:40 PM] Init: plugin type 'SamplePlugin.Sample' v0.0.0.0 loaded'
Now stop XSP by pressing
ENTER and run it once again. After browsing to the site, you will now see only the following:
Event log:
[5/17/2010 6:01:33 PM] Plugin 'SamplePlugin' loaded successfully.'
[5/17/2010 6:01:33 PM] Init: plugin type 'SamplePlugin.Sample' v0.0.0.0 loaded'
Which means that our pre-application start method has noticed that initial setup had already been performed and there's no need to load the setup plugin and re-run the code.
So, not rocket science but definitely a useful feature. Sample download links: