Tuesday, March 3, 2009

The type initializer for ‘SomeClass’ threw an exception.

I spent a good hour this afternoon troubleshooting a bizarre WPF designer error. I've been working on an app for my church, and I was using an ObjectDataProvider in a particular page to return a "Donation" object from my data-layer with some appropriate defaults set.

<ObjectDataProvider x:Key="defaultDonation" ObjectType="{x:Type classes:Data}" MethodName="GetNewDonation" />

This had been working fine for a while, but after I refactored a bit of the code in my data layer, the WPF designer stopped loading any form that touched this data layer. It kept returning the error:

The type initializer for 'WouldBeTheologian.PledgeManager.Classes.Data' threw an exception.

Interestingly enough, although the WPF forms wouldn't load, the project itself would run just fine; and specifically, the Data class would load and execute just fine. But it's a pain and a half to lose IntelliSense, and to have no hint of what your XAML is gonna look like.

It took some work to figure out what was going on. It turns out that after I refactored my Data class, I was instantiating a reference to my Entity Data Model during the class' constructor, like so:

static Data() {     pledgesEntities = new PledgesEntities(); }

But beneath the hood, when the EF tries to initialize its ObjectContext, it's doing so by reading the appropriate connection strings from the application's .config file. That works fine when the "application" is, in fact, your own application. But when it's called by the WPF designer, the "application" is Visual Studio, which (presumably) doesn't have the appropriate connection strings in its .config file; and hence the constructor throws an exception.

Once I figured this out, I fixed it by moving the instantiation of my Entity Data Model into a property, like so:

private static PledgesEntities pledgesEntities = new PledgesEntities(); public static PledgesEntities PledgesEntities {     get     {         if (pledgesEntities == null)         {              pledgesEntities = new PledgesEntities();         }         return pledgesEntities;     }     set { pledgesEntities = value; } }

It's a bit uglier and infinitesimally slower, but it works.

Of course, I'm not the first person to figure out that the Visual Studio WPF designer sucks at providing any help troubleshooting these errors. Among many other things, there's no way to access the InnerException of the error in question, which is a serious limitation, and has bit me on several occasions. Hopefully VS 2010 will fix this, though I haven't yet seen any firm indication that will be the case.