Burned by the .NET Client Framework - 06 Oct 2011

I recently wasted over an hour dealing with a horrible development experience that made me wonder if I had strayed into some sort of sadistic alternate universe. And since bumping into this little slice of hell was so simple, I thought I’d share what I learned as a public service—lest anyone else bump into this same problem and question their sanity as I did.

Confusion Abound

What made this problem so difficult and confusing was the fact that I’ve come to heavily rely on IntelliSense (but haven’t we all?). More specifically, I was working on one of my own development efforts in a Visual Studio 2010 solution that was composed of six different projects. A number of the projects were simple class libraries where core functionality, interfaces, and other requisite members had been defined. However, one of these projects was also tasked with data access and persistence.

In order to make my problem easier to understand, the namespace in my solution roughly looks like the following:

MyProject

MyProject.Communication

MyProject.Data

MyProject.Localizatiion

MyProject.Service

MyProject.Tests

Each namespace listed above is a C# project, and the MyProject.Service project is just a placeholder ConsoleApp that is dependent on everything else in the solution, except for the MyProject.Tests project, which stores my unit tests.

Initially, the MyProject.Data assembly was using a NoSQL backend, but upon receiving intermittent ‘service unavailable’ errors when testing a hosted NoSQL offering, I decided to ditch that approach and go with a SQL Server storage solution backed by PLINQO.

After adding in all requisite PLINQO dependencies and generating a SQL Server backed persistence layer, the MyProject.Service simply would not build, claiming that it wasn’t able to find objects clearly defined in the MyProject.Data namespace and assembly. Like any good .NET developer, I cleaned my solution, and manually rebuilt each dependent project to make sure that build errors in my lower assemblies weren’t preventing the requisite objects from being visible.

Although everything was built correctly, Visual Studio was still telling me that it didn’t recognize classes that were clearly defined in the MyProject.Data assembly. Was I missing an assembly reference it politely asked? So, I tried voodoo—meaning that I removed and re-added these assembly references. Nothing changed.

When the Universe Stops Making Sense

Still thinking that this was just a minor setback or a simple hiccup, I went into the .cs files where Visual Studio was having a hard time finding necessary references. For kicks and giggles, I deleted the ‘using MyProject.Data; statement at the top of one of my files. Then, things got very interesting because in the lines below where I was working with these classes, Visual Studio prompted me to include the exact statement that I had just removed.

Baffled, I repeated this exercise a few times, trying to think of what might cause the C# compiler to miss these references, even though Visual Studio was able to see those same classes by prompting me to include the correct namespaces needed to use them. So, I cracked open the Object Browser and pointed it at the MyProject.Data assembly. Sure enough, the classes and objects in question were all there, just as I had assumed they would be.

I looked at the namespaces and class names intently, to the point where my eyes almost bled, looking for typos or some simple spelling problem. Nothing.

Then, like the proverbial poor musician who blames his instrument, I figured that PLINQO was a new addition, and therefore was the potential culprit. I removed PLINQO and my project was able to compile again, and all of my references worked correctly.

I’ve used PLINQO on many projects, and I’ve never run into this problem. So, like a wild dog chasing its tail, I began to suspect that maybe my problem wasn’t PLINQO so much as it was a combination of PLINQO and the fact that I was now also using a WCF class library. I couldn’t remember mixing those two project types before.

I spent nearly an hour trying to figure out what it was about PLINQO and my WCF class library that was causing my problems. Like a dummy I tried modifying namespaces thinking that there was a collision somewhere, and I tried a few other things. But, once I removed PLINQO from my solution, it built fine. And as soon as I would add PLINQO back in, Visual Studio would throw errors about not being able to see classes in the MyProject.Data namespace, even though I could clearly build that project and plainly discern the objects from within the Object Browser. Even more perplexing, I still kept bumping into that goofy scenario in which Visual Studio would prompt me to reinclude namespace references as soon as I’d remove them, continuing to make me wonder if the universe still made sense anymore.

The Solution

In the end, I finally ended up wondering if I hadn’t somehow managed to toggle one of my projects to x86 (instead of x64) so I started peeking at the Properties > Application tab for each of my projects. Within about 3 seconds I spotted what was up—my WCF class library and the console application that I was using to test my service were set to target the .NET Framework 4 Client Profile.

I toggled both of those to use .NET Framework 4 (non client-profile) and everything built as anticipated. No more spooky actions in which the compiler couldn’t see the contents of my assemblies while Visual Studio kept prompting me to re-add them as soon as I removed the corresponding ‘using’ statements.

Sadly, I’m not the only one that has bumped intosuch a problem. And since several Visual Studio project templates target the client framework right out of the gate, I’m guessing that plenty of folks will bump into this problems. Personally, as great as I think the .NET Client Profile is, I think it’s a crime for anything in Visual Studio to target it by default.

In my case, as a server-side developer it never occurred to me that my projects weren’t able to see the contents of my other assemblies because they were using a dumbed-down version of the .NET Framework. Although the option to target the lighter-version of the framework makes perfect sense, defaulting projects to target the .NET client profile is really lame. I’m guessing the majority of folks that encounter this as a problem will bump into it in the same way I did, which means that they’ll scratch their heads and lose time trying to figure out what was up.