A project our team (in my employer) has been working on for a good number of months now makes extensive use of Windows Communication Foundation (WCF). WCF is nothing really ground-breaking; its significance is that it unifies the various inter-process communication facilities into one common programming interface. Moreover, it is extensible so it can easily be extended to support different protocols and message formats that may come in vogue in the future.
We've encountered some WCF gotchas along the way, of course. These are not bugs; these are simply stuff that one can overlook or fail to find in the official (MSDN) documentation. We had to resort to blogs and other non-official documentation to find a resolution to some of them. I think one of the problems I saw in the WCF body of knowledge in the Internet was the significant amount of outdated information about it. A lot of people worked on pre-release WCF (when it was still called Indigo, some three years back) and as a result some of the articles and blogs out there made use of APIs, configuration settings and other stuff which have already changed in the WCF that was RTM-ed with .NET 3.0 and now .NET 3.5. I wish that some of these authors were responsible enough to mention that the information they have were based on beta versions of WCF -- if not, they should have made it a point to update their code and/or discussions to suit the actual released version of WCF. But anyway...
One operation we had to make available via WCF web services was retrieval of matching records based on a user-defined set of criteria. At that time we were using WCF on the server but our client used ASMX web services, because we had to support Windows 2000 (and .NET 3.0 cannot be installed on Win2K). We encountered three minor issues here:
- The method signature generated by the client proxy (using WSDL.EXE or the "Add Web Reference" option in Visual Studio 2005) was different from the actual server-side method/operation, especially if you pass or return basic data types like int. For example, if we have a server-side method int GetNumberOfItems(string username) it would come out in the proxy as something like void GetNumberOfItems(string username, out int result, out int resultSpecified). It was quite disorienting at first but we got used to it soon.
- The operation for retrieving an array of records would fail with a vague exception whenever it would try to return a huge number of records to the client. I couldn't remember the exact exception that was thrown but it took time for us to realise that we had to set parameters such as maximum string length and maximum message size in the WCF server-side configuration.
- Whenever we called service methods from the client we would enclose the code inside a try-catch block, but we would only be catching WebExceptions. We provided a way for the client to cancel a long-running operation, so whenever we caught a WebException we checked the exception's Status property for WebExceptionStatus.RequestCanceled. If that was the Status then we know it was because the client cancelled the service operation so the app will just ignore it; otherwise it was a real exception and the user had to be notified (and a log created) about it. But lo and behold, our users would report that they would sometimes see an exception dialog box whenever they cancel the retrieval operation -- even though this should mean that the WebException's Status was RequestCanceled and the app should have just ignored it. It turns out that when the operation is cancelled, it was possible for it not to throw a WebException but instead an InvalidOperationException because the XML (SOAP) message sent back from the server was cut off! Uh -- how come this wasn't mentioned in the documentation? It wasn't even mentioned in the docs that a web service call can throw this kind of exception -- we had to experience it to know that such a thing was actually possible. So we had to catch InvalidOperationException in our code as well.
Eventually our clients were all upgraded to Windows XP so we had no need to bend over backwards to support good ol' Windows 2000. That means we can use .NET 3.0 in the client and make full use of WCF! We had to regenerate our client proxies to make use of the "Add Service Reference" with Visual Studio 2005 instead of "Add Web Reference" (which used old ASMX web services). This time the client proxy method signatures matched exactly that of the server-side signatures so we had to edit our existing (ASMX client-based) code base. Then we ran into another problem!
It turns out that the "Add Service Reference" feature for Visual Studio 2005 did not generate asynchronous client proxy methods. The "Add Web Reference" feature did, and we used them extensively. We had an option to create additional methods on top of the plain synchronous client proxy methods, but it was too much work. Luckily the SVCUTIL.EXE command line tool had an option to generate asynchronous methods in the client proxy, so we used that instead. So whenever we had to change the service methods or objects and had to regenerate/refresh the client proxy, we had to manually check out the auto-generated files from our source control, run a batch file that executed SVCUTIL.EXE, then check the regenerated proxy classes back into source control -- instead of a simple right-click then "Refresh" in the Visual Studio 2005 Solution Explorer. More work, yes, but at least we did get those asynchronous methods that we need. If you are using Visual Studio 2008, the "Add Service Reference" feature is now capable of generating asynchronous methods...but in our case we won't be getting the new IDE until next year.
The reason we moved to use WCF both on server and client is because we needed the HTTP callback feature of WCF, using WsDualHttpBinding. In this configuration, the client connects to the server to initiate a retrieval request. The server will then periodically push data to the client -- in effect, the roles get reversed: the client becomes the server and the server becomes the client. We were able to get it to work satisfactorily, and the performance boost was significant. However, one of our testers reported that she couldn't get the retrieval feature to work. She kept on encountering this AddressAccessDeniedException message. We were puzzled as none of us ever encountered the problem before. It turns out that she does not have administrative privileges on her machine (good user!), and that there was this thing called HTTP namespace reservations that was introduced in XP SP2. The solution to the problem is described in the previous link, but how come this wasn't mentioned in the MSDN documentation for WsDualHttpBinding in the WCF section? Maybe it's there, I don't know, but it certainly wasn't prominently placed. I'm sure others who would be using this feature will be likely to run into the same problems.
So there...some of the WCF gotchas we've encountered, and hopefully this information can be of help to you should you encounter them too. WCF is great technology and it's really worth exploring! If you are thinking of using ASMX web services or Remoting on a .NET application, I suggest you skip that and go directly to WCF instead.
10-05-2008 11:48 AM