I’m really struggling today with a Web Service issue that’s been a thorn in my side for some time, which is the lack of better type mapping in Web Service clients.
I’m working on a distributed Web service app where the main functionality is provided by a third party Web Service. The service is asynchronous so we submit messages to the service and the service responds with messages that are sent to a Web service on our end. After a few problems starting out that part of the process works quite well getting the very complex message structure passed over the wire and persisting as objects thanks to a nudge from Christian Weyer.
The next step in this interface is another Web Service – a store and forward service essentially – that takes the message received and allows a client application to retrieve these messages on demand. The Web server is central and remote to all clients and so clients can check in for updates.
I have the whole messaging mechanism working but the real problem in this system is that the end result – the final data retrieved from the messaging service needs to be sent back to clients via COM. Due to the complexity of the Web Service message, COM (at least into a FoxPro app) can’t directly publish the message back to the client application and requires a small front end wrapper class I’ve created that makes several of the types accessible that otherwise wouldn’t be.
So the real problem here is once again that there’s no way that I can see (short of manual coding the Web service proxy or seriously hacking the generated code) to force the results from the message service into the types that are required for the COM interop functionality. Every single type of these 100 or so types published from my Web service ends up as a ‘generated type’ reference rather than the actual type reference which in this case all points back at the types defined in the original vendor WSDL definition.
I’ve hacked proxy classes generated before and that works OK if you have relatively small number of interfaces to deal with. But this particular message type contains nearly 100 related types and it’s just not an option to manually customize these types.
I can only ask this question in frustration again: Why is there no support in the .NET framework to coerce types back into matching structures more easily. Specifically why can’t Web Service interfaces allow more flexibility in specifying how the marshalling is to occur? The structure is there – all it takes is picking up the message properly.
Maybe you know the feeling: I have the types, they’re right here on the client and on the server, but I can’t get the data into my own types. I’m stuck with a generated object that’s 20+ levels deep and I can’t pass back over COM because it doesn’t match the COM signature… <sigh>
So at this point I’ve more or less ditched the idea of strong types on the wire and instead ended up using raw XML messages – through eh Web Service - on the ‘private’ end of the Web Service. The way this works is that the remote Web service picks up the inbound data from the third party service as a strongly typed object and it stores this data in a database. When the client requests outstanding messages it goes out picks up those relevant message instantiates them as types, combines them together into a collection, and then serializes the whole collection – eventually down into an XmlNode - that is then returned as the result of the service method. The end result is that the data goes down to the client as a non-schema’d XML entity, which represents a serializable object, that can be restored on the other end. Because the data on the wire is not passing a strong type for the Web Service the client code can easily deserialize the XML into the required type.
Incidentally for the first shot at this I used a DataTable to pass the data down which also worked but severly bloated the string XML data which was nearly 3x as large as with the above method. While more intensive on server resources the smaller data amount is more important in this case.
This approach works, but I don’t feel good about it. The problem is that from an architectural view I’m one step above passing strings back and forth <g>. The data is perfectly fine XML and SOAP compliant, but it is of course not schema’d at all. It’s dynamic and if this service needs to be accessed externally there won’t be automatic parsing support unless the types in question exist on the client. For a private interface this is probably OK, but for a public facing interface this would definitely be a problem.
So what is the solution to this if any? Is there any way to do this with proper types and contracts and without the .NET generated proxies getting in the middle short of writing your own service proxy?
I keep saying this – I want to spend more time with WCF to see if this particular scenario improves in anyway. I guess I’m not exactly sure how this would work if it could do what I want – I suppose you first have to be able to express what I actually want here.
But I keep running into this same scenrario over and over again. So either I’m going about this all wrong most of the time, or this is a pattern that really needs a solution.