ObjectDataSource, SOA Style
It’s been entirely too long since my last post, and with the olympics in full swing, we’ll go with a volleyball theme for this post.
BUMP
So here’s the scenario. After really digging your teeth into ASP.NET 2.0 and playing around wiih all the cool data access features, you decide to apply a liberal use of the ObjectDataSource for its ability to take care of the paging and sorting calls for you. Now, you begin to convert your site to a service oriented back end and you wonder how you’re going to make calls against your web service. You have a few options in front of you. You can create a thin facade layer that will act as a liaison between your presentation code and your service layer calls, and hook your ObjectDataSource to that. This works especially well when you have a complex object model that makes use of the web service calls behind the scenes. It’s also beneficial when you are generating your proxy classes from metadata or contacting a foreign web service. In the scenario I’m going to demonstrate here, I’m referencing a shared contract and service library, so I’ll be using using the ObjectDataSource to make direct calls to ChannelFactory
SET
The main ingredients for this technique include a dash of class inheritance, a heaping spoonful of refluxion (as one of my friends says it), and some method overriding, to taste. The main issue here is that since WCF contracts are interfaces, how can we declare them in the ObjectDataSource being that you can’t instantiate an interface. Well, let’s show some code, starting off with a very basic service contract and implementation:
So I need some way of creating an instance of ChannelFactory
For our example, we’re going to assume that the user is going to specify the name of the service contract in the existing “TypeName” property of the control. Using this, we’re going to generate our proxy. Here’s the code that creates the actual object:
SPIKE
Analyzing the code above, you can see that we use a heavy dose of reflection and some generics to create an instance of ChannelFactory
WATCH OUT FOR THE NET!
One little gotcha in this whole thing. There are cases when you have a master contract, which is an interface that inherits from another interface. Sometimes I do this to consolidate the number of services I expose so that I don’t have a configuration that’s a mile long with 100+ service contracts that each contain one method. consider this contract scenario:
This is pretty simplistic but you can get the idea. So, in this case, I may expose IMainContract as a service. If I use IMainContract as the “TypeName” property in my extended ObjectDataSource class, it will throw an exception that it could not find the “SayHello” method that I specified as the SelectMethod in the interface. This has to do with how C# deals with interface inheritance. Needless to say that there are workarounds, but because of the way ObjectDataSource was coded, you cannot change the way that it checks for these methods. Also, because the configuration file exposes the service as the IMainContract class, if you specify a TypeName of IContract, then the select method will be found, but you’ll get an error saying that the ChannelFactory could not find a service contract with the type IContract. Quite the Catch 22! The solution for this is to set the TypeName to IContract since our method is defined here. Also, I added a property called EndpointContractTypeName which can be set to IMainContract so that when the object is being created it will generate that type, and since IMainContract implements IContract it follows that once the instance is created, we can call any method that existed on IContract with no problems.
The full source for the version I’m using looks something like this: