Thursday, February 22. 2007Using SOAP via a .NET in Dynamics AXOur company was the first to use the European Commission's VIES system via SOAP to validate VAT numbers automatically. We used to have a custom hack to perform this operation within Axapta 3.0, waiting for what was then a rumour that Dynamics Ax 4.0 would be able to call .NET assemblies via CLR interoperability. In my previous article, I touched on calling code within Ax from C#, but now I want to explain how this works the other way around. To create a proper SOAP connector for VIES, I've used the wsdl.exe tool from the .NET Framework 2.0 SDK to generate the basis for a .NET Assembly from a WSDL definition (I'll use VIES's WSDL): "C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\wsdl.exe" /language:CS /protocol:SOAP http://ec.europa.eu/taxation_customs/vies/api/checkVatPort?wsdl This creates a generated piece of code that works well, but needs some modification. You'll want to wrap the generated class in your own namespace, based on the name of your assembly. In my example, we also need to add a wrapper method, since Ax cannot properly handle variables in C# that use the out keyword. Without this, Ax will claim the method you're trying to call does not exist. You'll need this for any SOAP call that returns multiple variables. To return the variables, I've used an Array since it's an easy object to "unwrap" within Ax using standard System.Array methods. For my VIES example, I added this to the class:
Dynamics Ax will only call code within strong-named assemblies within the GAC, so you will need to generate a key and use it when you compile your code. From the SDK, you can use the sn.exe tool, or just use Visual Studio itself to set the parameters on the assembly correctly. If you're a command-line freak like me, use this: "C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\sn.exe" -k viessoap.snk "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\csc.exe /target:library /keyfile:viessoap.snk /out:My.Namespace.Goes.Here.ViesSoap.dll .\checkVatService.cs" To install the assembly in the GAC, you can drag-and-drop the DLL file using Windows Explorer into C:\WINDOWS\Assembly, or alternatively use gacutil.exe. With that code compiled and installed, it's time to jump into Dynamics Ax 4.0, and create a reference to the assembly. Open up the AOT node for References and add your assembly. If it's correctly installed in the GAC and you opened Ax after you installed it, it should appear automatically in the grid. If not, go back and fix the installation. Make sure, once it's referenced, that the public key and version matches the assembly correctly. Some versions of Ax have problems with this step, and you may find that your reference is not actually saved correctly. If this happens, a work-around is to create the reference, export it as an XPO file, and import it again immediately. You'll be able to tell if the reference will save correctly if you're viewing the AOT with layers shown: If the reference is not assigned a layer when you save it (i.e. CUS), then you'll need to perform the work around. If the reference is installed well, we can now write a job to demonstrate this .NET call. You'll notice similarities with C# bleeding into X++ in the following example:
Obviously, for VIES, I had to add additional code within Ax to fix country codes. For Greek VAT codes, the prefix is EL and not GR as you might presume for the other European countries. Also, VAT numbers in Ax can be entered with formatting (spaces, hyphens, and so forth) which need to be stripped out in the same manner as when they are sent electronically to tax authorities. Deeper in, though, you'll notice the first thing we do is request permission. Ax has code security which protects code from unwittingly calling external services in situations it shouldn't be allowed to. You must assert your rights to call CLR objects before you can instantiate classes! As normal, make sure you clean up after yourself when you're done - This is where we revert our "assert". You'll also notice that we can deal with native objects from .NET, such as System.Array easily, but converting back to native Ax types should be done via Ax's AnyType primitive type. In order to do this with some amount of intelligence, you should use ClrInterop::getAnyTypeForObject() to convert from a CLR object to Ax, and ClrInterop::getObjectForAnyType() to convert from Ax to a CLR object. Some objects will, however, automatically convert themselves, such as strings and integers, but be careful. Ax will natively tell you some details about the class you're using via IntelliSenseā¢, such as the methods you can call, however it is presently incapable of listing the variables you need to pass to those methods, so make sure you have the documentation or source code on hand. If you're keen to find the C# code without the adventure, you can find it here. Of note is the Happy coding! Comments
Display comments as
(Linear | Threaded)
Dominique on :Simon Butcher on :Dominique on :Dominique on :Dominique on :Simon Butcher on :Dominique on :Simon Butcher on :Gary Holsopple on :Simon Butcher on :Stefaan Lesage on :Simon Butcher on :The author does not allow comments to this entry
|
Calendar
Creative Commons |
Simon Butcher on : Upgrading Axapta 3 to Dynamics AX 4