Last week I needed to use a third-party web service in AX2009. I created a service reference in AOT, so AX generated necessary code and configuration and I was immediately able to get data from the service. Quickly done, almost without any work. Great.
But I wouldn’t write about it if that was all. The given web service is to be used interactively – you type some input, the web service is called, data is displayed and so on. Sometimes you also type incorrect input and the services returns a special message with an error code and text describing the problem.
What I expected was getting a FaultException that I would catch and handle in some way. Instead I got the following error:
Type ‘System.ServiceModel.Channels.ReceivedFault’ in assembly ‘System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′ is not marked as serializable.
I tried to search the web and I’m obviously not the first one running into this error, but I didn’t find any useful explanation or solution.
So I looked into the actual implementation and discovered that the proxy generated by AX extends the Microsoft.Dynamics.IntegrationFramework.WebService.WebReferenceBase class (in Microsoft.Dynamics.IntegrationFramework.dll). The class creates a new application domain for each web services, which allows – if nothing else – to load the app.config file, but the application domain border obviously cause the problem with the ReceivedFault instance.
I don’t see any way how to use AX-generated service references and avoid the serialization error in the same time. Service references in AX offer nice integrated configuration, but in my case the proper exception handling is more important. Therefore I created a separate .NET class library that references the web services, creates the proxy, sets a binding, an endpoint address and calls the service.
Leaving aside configuration and input validation, the whole implementation is really simple:
public static Object GetData(string input) { using (var client = new MyService_SoapClient( new BasicHttpBinding(), new EndpointAddress("http://somewhere/service.ws"))) { return client.GetData(input); } } |
The ReceivedFault is correctly translated to FaultException, which is subsequently sent to AX and can be caught there without any problems.
Although I haven’t tried to use the same web service in AX2012, I don’t expect the same problem there. It’s because AX2012 handles web services very differently from AX2009.