Today I was working on some kind of WCF Data Service, when suddenly while I was testing my data service this error came up:
When I see this kind of errors, I'm always wondering if there is a way that my code can give me some more information on this error. Sure it can! All you need to do is add the following attribute to your service class:
[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
I compiled my projects again and ran it. This time I was given some more information on the error.
The additional information the exception gave me, immediately revealed the problem. I changed the constructor of my 'ExampleContext' from an empty constructor to a constructor that required one argument and since WCF Data Service still wants to call my empty constructor it throws an exception because it can't find the empty constructor.
I was wondering why this constraint wasn't enforced at compile time instead of runtime. The WCF people could have defined the DataService class as follows,
public class DataService<T> : IRequestHandler, IDataService where T : new()
which enforces every T to have an empty constructor, but they defined it as
public class DataService<T> : IRequestHandler, IDataService
without the empty constructor requirement. Why would they have done that? Of course this could be an issue with the DataService class, but as Scott Hanselman said at the Dav Days 2011: "Don't blame Microsoft for your bad design." Why would you enforce every T to have an empty constructor? It is just removing flexibility. It was more likely that I did something wrong, so I googled on "dataservice context needs empty constructor". The second hit took my attention, because it talked about an "IDataContextProvider in a constructor", so I clicked on it.
The blog post talked about the usage of Inversion of Control in a webservice and the code in the blog post showed a method called "CreateDataSource()" that was overriden from its base class "DataService" and returned the type T. This was a great solution because know I could call my custom constructor myself. While writing the code to override that method, another thought came up in my head. Of course removing the empty constructor an adding a custom one leads to problems for data services, because it doesn't know about all parameters of the custom constructor and their constraints.