Generics in Serviced Component interfaces.

Here’s a thing that’s bugging me right now. I’m refactoring a client server application to use Enterprise Services. It’s already split into UI, Buslness Logic and Data Access on the client with direct calls to the SQL server stored procedures so we’re just moving some of those layers to the server and turning them into serviced components. Simple and effective….OK so it’s not THAT simple but in broad strokes that’s the strategy.
So I’m looking at the newly formed COM+ API with its interfaces and methods using the Component Services explorer and I notice that lots of the methods are missing. I mean, I know they’re there right, because I can call them and they work, but COM+ is telling me that they don’t exist.
It turns out that the thing all of the “missing” methods have in common is that they have a generic somewhere in the method signature, like 
int foo(Nullable<int> bar);
List<string> foo(string bar);
 So I ask around and I get a number of explanations/guesses, a common one being “you can’t use generics across a COM+ boundary”. But, sure I can, because these methods are working. So what’s the deal here ?
I know that if I have a simple signature like : 
int foo(string bar);
 then COM+ will have no problem with it and I am wondering if this is similar to the issue with the serializer. There are some CLR types (mainly the value types) that COM+ understands and so if a method signature contains only these types the COM+ serializer will be used when the method is called. However, if the method signature contains a type that COM+ does not undertsand and cannot serialize it will defer to the .NET remoting serializer when the method is called. Similarly when I query the interface COM+ simply doesn’t have the language to communicate the method signatures of the methods that contain generics because it’s stuck with IDL so it doesn’t bother trying. But then if I look at method signatures that have DataSets, or strongly typed derivatives thereof, in them they appear just fine so IDL is communicating those just fine.
So maybe I shouldn’t be worrying about this because it works and if it ain’t broke….right ? But now I’m looking at profiling this application and I’m looking at various tools that will give me some metrics on calls to the methods in the COM+ API and I have a sneaking suspicion that the metrics for all my missing methods are going to get lumped together under calls to IRemoteDispatch or some such horror.
Anyway, I banged my head on this for a while and in the end I took a flyer and emailed Juval Lowy. Yes, me. I did that. So over the weekend I exchange a few emails with Juval and you know what ? He didn’t tell me the answer. I think he kind of hinted at it but in the end what he actually did was make me feel a whole lot better about learning not to care. I mean, if you look at this method : 
DataSet GetData(Nullable<int> id);
why would I spend hours agonising over the perfomance issues that might be associated with the difference between Nullable<int> and just int. I’ve already made my bed in performance terms by deciding to pass a DataSet. At the end of the day I have a working application, the client is happy and if performance is adequate why should I care ? The answer is, I don’t know, I just know that I do and I find it hard not to.

Essex Wildlife…carpeting the A12 one fox at a time

I am continually amazed by the sheer volume of roadkill on the A12 between the M25 and Colchester. Some days I think I could walk the entire route without ever stepping on tarmac…just hopping from carcass to carcass. I’d need a good pair of wellies obviously 🙂

Enterprise Services, COM+ Proxies & ClickOnce

Although WCF and .NET 3.0 seem to have taken over my life I am still doing a fair amount of .NET Enterprise Services stuff. Hey, it’s good technology and it got us through some tough times, right ? There are actually still a lot of people out there with a big installed client base of Windows 2000. No, really, there are. While we’re all getting excited about Vista there are a lot of people who never made it to XP. Sure they have moved their server platforms to 2003 for better stability, performance, scalability etc but what’s the business case for the workstations especially when you add the cost of a roll out and updating the PC hardware ?
So these people don’t get to play with our new .NET 3.0 toys, at least not “client-side” anyway. In some environments I have been building hybrids where the client-server communications within an application works over .NET Enterprise Services and DCOM but between the application servers WCF is used to create SOA-type messaging with Pub/Sub events and so on. You know, the cool stuff Juval Lowy likes. This is actually a nice compromise. The move to WCF was always going to be gradual anyway so you can phase it in at the server level and roll it down to the clients as they catch up.
This has thrown up some interesting problems though. Notably with ClickOnce because my .NET 2.0 SmartClient UI application needs to be deployed with its COM+ proxy. When I first came across this it quickly became apparent that I would have to create a pre-requisite package containing my proxy and then use the ClickOnce bootstrapper to install it. Not a problem per se. I already had Brian Noyes book on ClickOnce, plus Michelle Leroux Bustamante’s downloadable examples and I had found the Bootstrap Manifest Generator on GotDotNet, so I was well armed in that respect.
However, I was not happy with the whole approach and furthermore it raised some problems about the rights of the user running the ClickOnce install to perform com registrations on their workstation. So I did what any responsible architect would do and I Googled the issue…without much success. I found a post on by Rocky Lhotka in which he desrcibed the issue as “problematic” so I emailed him to see if it was a problem he’d solved or if “problematic” was simply a euphemism for “more trouble than it’s worth”. He replied almost immediately (which was cool because he’s a legend and all) but suggested that I read Brian Noyes book (which was not because I already had it open in front of me).
An alternative approach, since the pre-requisite is an .MSI package, is to use Active Directory and Group Policy to deploy the proxy. AD allows you to either publish or assign an application. The main difference being that with publication you can only publish to a user whereas you can assign to either a user or a computer. Applications that are published or assigned to a user will only have their icon(s) installed next time the user logs in. The application will not install until the user first tries to launch it. Applications that are assigned to a computer will be fully installed next time the computer is rebooted.
Assign Publish
Computer Complete application installed on next boot. n/a
User Application icon(s) only installed on next login. Complete application installed on first use. Application icon(s) only installed on next login. Complete application installed on first use.
OK, so now we can deploy our proxy without the security issue but we have separated its deployment from the deployment of the client application that uses it and we have introduced a reboot into the process. I suppose we could go the whole hog and package the entire client application along with its proxy as an MSI and AD-deploy it that way but I really like the idea of ClickOnce and I’m loathe to abandon it completely at this stage.
So now ClickOnce throws us another curve ball. Let’s say we bump up the permissions of the users on these workstations so they can install the proxy. So the first user logs in and installs the app and its pre-requisites via ClickOnce. It all works fine, we have beer. They log off and the next user logs on and has to install the app aswell because ClickOnce installs apps in the user’s local settings cache. But the proxy is already installed and ClickOnce tries to install it again. The install of the proxy fails which causes the whole installation to fail. We put down our beers and are sad.
It turns out that subsequent users can actually install and run the application without the prerequistiues by clicking on the lauch link on the install page. Our proxy is installed “globally” but our app is installed per user. So it “kinda works”. We go back to our beers agreeing with Rocky that this is indeed “problematic”.
%d bloggers like this: