Adios 2.0

I upgraded to Community Server 2.1 last night and I have to say that the experience was surprisingly painless, even for someone like myself who is not use to SQL Server's heathen ways.

Apart from the SQL upgrade script balking because of an old record missing from the cs_SchemaVersion table (I just added it manually) the updating the database went without incident. Upgrading the web application was slightly more time consuming as I had to merge my changes to the *.config files with the new versions but after that I just copied my custom theme directory across and then uploaded it to the server.

Now I just need to find a new blog feature in Community Server 2.1 that I will actually use to make the upgrade worth it [:)]


The admin area is much improved. Most the rough edges around the post editor and post grid have been smoothed out. Also the new "named" URLs are much better than the old number system. I went through and updated all of the previous posts to use them (the old URL still works).

Overall I give 2.1 two thumbs up [Y] [Y] (did I mention the smilies in blog posts? [:)])


Download DetailedErrorEvent - DetailedErrorEvent dll and C# source code

One of the least talked about new ASP.NET 2.0 features, and one of my favorites, is the health monitoring system. Designed to help you monitor the status of a deployed website, the ASP.NET health monitoring system makes what could potentially be a chore easy. With just a few lines in your site’s web.config you can automatically log a variety of events to a file, a database or even send an email to an email address.

While overall health monitoring it is a great new feature for ASP.NET, the WebRequestErrorEvent class provides disappointingly small amount of information. Raised when an unhandled exception is thrown during a web request, only basic information about the request that caused the error is provided such as the URL, the user host address and the authenticated user. Vital information like the request headers, form values, cookies and server variables are missing, making debugging the error more difficult than it needs to be.


The WebRequestDetailedErrorEvent class inherits from WebRequestErrorEvent and includes the information that the base class is missing.

One interesting aspect of the health monitoring events is that they are written asynchronously. While this allows them to be buffered and written without impacting performance, it also means that a copy of the request details need to be taken as HttpContext.Current will be null when the FormatCustomEventDetails method is called.

private void Init(Exception exception)
    // FormatCustomEventDetails is called outside of a web request
    // need to take a copies of all the web request information to log
    HttpContext context = HttpContext.Current;
    if (context != null)
        HttpRequest request = context.Request;
        _cookies = new HttpCookie[request.Cookies.Count];
        request.Cookies.CopyTo(_cookies, 0);
        _httpHeaders = new NameValueCollection(request.Headers);
        _form = new NameValueCollection(request.Form);
        _queryString = new NameValueCollection(request.QueryString);
        _serverVariables = new NameValueCollection(request.ServerVariables);
        _cookies = new HttpCookie[0];
        _httpHeaders = new NameValueCollection();
        _form = new NameValueCollection();
        _queryString = new NameValueCollection();
        _serverVariables = new NameValueCollection();


Unfortunately there is no seamless way to automatically raise the new web request error event instead old so a new HttpModule is required to do it for us. WebRequestDetailedErrorModule attaches a method to the Error event of the HttpApplication object and then raises WebRequestDetailedErrorEvent when a web request exception goes unhandled. Not all exceptions raised the default event so some logic is required to filter them out.

private void RaiseErrorEvent(object sender, EventArgs e)
    HttpApplication application = (HttpApplication)sender;
    HttpContext context = application.Context;
    Exception exception = context.Error;
    // unwrap exception if top exception is an HttpUnhandledException
    if (exception is HttpUnhandledException && exception.InnerException != null)
        exception = exception.InnerException;
    HttpException httpException = exception as HttpException;
    // don't log file not found exceptions
    if (httpException != null && httpException.GetHttpCode() == 404)
    // viewstate exceptions raise a WebViewStateFailureAuditEvent, not an exception event
    if (httpException != null && httpException.InnerException is ViewStateException)
    WebBaseEvent.Raise(new WebRequestDetailedErrorEvent("An unhandled exception has occurred.", this, WebEventCodes.WebExtendedBase + 3005, 0, exception));

The old event will still be raised so if you may want to modify your web.config to not log events numbered 3005.


To use the WebRequestDetailedErrorEvent simply add the module to your website’s httpModule section.

    <add name="WebRequestDetailedErrorModule" type="Newtonsoft.DetailedErrorEvent.WebRequestDetailedErrorModule, Newtonsoft.DetailedErrorEvent"/>

And that’s it. The new error event is now raised whenever an unhandled exception is thrown from a web request. Note that if you haven’t already setup ASP.NET to log health monitor events you can find out how here.

Download DetailedErrorEvent - DetailedErrorEvent dll and C# source code

Well I think it's funny - .NET Edition

.NET Pickup Lines via K. Scott Allen

If I were a generic collection, I'd be strongly typed for you.

You must be the latest version, because I've been checking you out.

I have a small problem. I put an object in a Dictionary, but I lost the key! Can you come back to my place and help me look for it?

A TypeConverter just returned my heart, and it's ready to assign to you.

Let's turn off option strict and do some late night binding.

So, what's your hash code?

And some of my own:

The moment I saw you I knew my singleton days were over.

There is nothing IDisposable about my love for you.

I've been reflecting on your Attributes and I like what I see.

Oh dear.

Well I think it's funny

Made by the students of the Columbia Business School, this hilarious spoof "Every Change of Rate" features a man lamenting missing out on the Chairmanship of the Federal Reserve to the tune of "Every breath you take". Glenn Hubbard, Dean of the Columbia Business School, was rumored to be on the shortlist for the position which makes the whole thing even better. Here's a sample:

"First you move your lips

And hike a few more BiPS.

When demand then dips And the yield curve flips,

I'll be watching you."