Webservice

Description
A webservice is a software component that can be called using the standard internet protocolls. Webservices are based on XML protocolls: WSDL is used to describe the interface; SOAP is used to call the service and receive the response. Because the communication and interface description is XML based, webservices are technology neutral. Service Oriented Architecures (SOA) are built upon webservices. Webservices can be call synchronouse and asynchronouse. A synchronouse usage is like RMI where a method is called and the client is idle until response. For example online payment. Asynchronouse services are used for long term actions. The client only submits data to the service and doesn't wait for response. For example placing a sales order.

Types of nodes
The webservice infrastructure has 3 types of nodes:


 * Registries are used to register a service so it can be found by consumers. The registry holds information about the service like Quality of Service, Provider, Description, Keywords etc. Registries either be public or private. Clients can query for services that fit their needs. Like the yello pages for software components. Most registries use UDDI
 * Service Providers are hosting services and register them to registries. The provider is the owner of the service and has to keep it alive and the registry entries up to date.
 * Service requesters query the service registries to find appropriate services. The registry provides the contact information (URL). In a SOA the requesters query the registries, exchange and arrange services automatically based on the business needs.



REST Webservice
The term webservice is almost a synonyum for XML/SOAP webservice. Just to mention, webservices are not limited to XML/SOAP. REST is a lightweight way to provide and use functionallity over the internet.

Soap Toolkit
Using Mantis WebService in Ax 3.0 via MSSOAP COM object static void test_Mantis(Args _args) {   // create an MSSOAP object COM ws = new COM('MSSOAP.SoapClient30'); Array priorities; COM item; int i;   XMLSelection priority; str getValue(XMLSelection _selection, str _name) {       int j;        str id; str name; XMLElement element; for (j=0; j<_selection.length; j++) {           element = _selection.item(j); if (element.baseName == _name) return element.text; }   }    // init this object pointing it to WSDL of the Mantis web service ws.MSSoapInit("http://www.mantisbt.org/bugs/api/soap/mantisconnect.php?wsdl"); // enumerate priorities of tasks in the mantis bugtracker // user name and password are empty priorities = ws.mc_enum_priorities(,); // output IDs and Names of all priorities for (i=1; i<=priorities.lastIndex; i++) {       priority = priorities.value(i); info(strFmt('%1: %2', getValue(priority, 'id'), getValue(priority, 'name'))); } }

COM Web Service Wrapper
While the SOAP Toolkit is okay for tiny methods with primitive parameters, it's not good for calling methods with complexe parameters. The best way to handle methods with complex parameters is to create C# wrapper classes in visual studio. Following steps are necessary to call the TerraService web service in AX 3

'''1) Create the .NET wrapper library Open Visual Studio and create a new class library project. Right click on the project node in the visual studio solution and add the web service as web reference. The WSDL file for the TerraService web service is located here.

'''2) COM Visibility Open the project properties from the project context menu. In the first tab open assembly information and mark the option COM Visibility. Compile the class library and copy the DLL to your Client\Bin directory

'''3) Register on local computer Make sure the DLL is in your client\bin directory. Open the command prompt and use the regasm tool to create the type library and register the library on the local computer. The regasm tool is part of the .NET framework SDK. Check if the registration was successful: Open the registry with regedit and search for your class library in HKEY_CLASSES_ROOT. regasm /tlb:MyWrapper "C:/Program Files/Navision/Axapta Client/Bin/MyWrapper.dll"

'''4)Use your library in AX 3 Use the COM wrapper wizard in AX to create X++ stub classes for the C# wrapper classes. I made the experience that there is no intellisense for methods, so you have to know what method to call.

This code illustrates how to call the GetPlaceFacts(Place) method static void CallTerraService(Args _args) {   // replace my class ids with yours COM service = new COM('{E09B0CB7-7365-34D3-88BA-552C186E97F4}'); COM place  = new COM('{64B668A7-71C7-3DC6-B497-F57E64555136}'); COM facts  = new COM('{3FC8AD17-A2F5-3796-B34D-8BB2B24DF7F1}'); COM lonlat = new COM('{32392E18-1D42-36F1-98CB-B6EE7CFC8A70}'); real longitude; real latitude; ;

//build place parameter object place.City("Menlo Park"); place.Country("United States"); place.State("California");

// call web service facts = service.getPlaceFacts(place);

// process and display result lonlat = facts.center; latitude = lonlat.lat; longitude = lonlat.lon; info(strfmt("Menlo Park is located at %1 %2",longitude,latitude)); }



Call from Dynamics AX 4
Using webservices inside Dynamics AX 4 is easy. You may use the command line tools to generate the proxy classes or Visual Studio.

Command Line Tools
wsdl /namespace:com.company.ax.web /out:TerraServiceProxy.cs http://terraserver.microsoft.net/terraservice.asmx?WSDL sn -k mykey.snk csc /target:library /keyfile:mykey.snk TerraServiceProxy.cs
 * Create the proxy classes for your desired service. This can be done inside visual studio by adding a web reference or using the command line tool wsdl. The tool is located at C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\bin . The following call will create the proxy code for Microsoft Terraservice US, with namespace com.company.ax.web and write it to TerraServiceProxy.cs
 * Create a public/private key pair using the sn tool
 * Compile the generated file to a dll and sign it with the generated key

Visual Studio

 * Start Visual Studio and create a new C# Library project
 * In the project explorer add a new web reference
 * Copy the URL in the text field. The assistant will download the WSDL file and parse it
 * Accept or change the suggeste namespace. Visual Studio generates the proxy code for you
 * Right click on the library project and open the properties window
 * Go to the Signing tab. Activate the "Sign Assembly" checkbox. Open the dropdown an choose the "New" option. Provide a keyname like "mykey". It is not necessary to use a password. You may deactivate that option.
 * Save and close the properties window
 * Change the Build type from "Debug" to "Release" and build the solution

2 Register Assembly gacutil /i TerraServiceProxy.dll
 * Copy the dll to the Client/Bin directory. If you want to use the assembly on the server, copy the dll also in the Server/bin directory.
 * Use the gacutil tool to register the dll in the global assembly cache
 * Start Dynamics AX, open the AOT and add the Assembly to the references node

3 Use the Service

Unfortunately X++ has no support for namespace, so you have to use the full qualified name. Proxy.net.microsoft.terraserver.TerraService service = new Proxy.net.microsoft.terraserver.TerraService; Proxy.net.microsoft.terraserver.Place place = new Proxy.net.microsoft.terraserver.Place; Proxy.net.microsoft.terraserver.LonLatPt point; Proxy.net.microsoft.terraserver.PlaceFacts facts; System.String center; real lon; real lat;

/* where is fresno ? */ place.set_City("Fresno"); place.set_State("California"); place.set_Country("United States");

facts = service.GetPlaceFacts(place); point = facts.get_Center; lon = point.get_Lon; lat = point.get_Lat; info( strfmt("Fresno is located at Lon:%1 Lat:%2",lon,lat) );



Call from Dynamics AX 2009
Calling a webservice from Dynamics AX 2009 has become more easier than ever before. Simple create a new service reference in the AOT. The system generates the wrapper assembly for you. Use the assembly in X++ code as any other .NET assembly.



There are some issues to be aware of.
 * A webservice can only be called from the AOS. Make sure to set the RunOn property to server or write a method with static server modifiers
 * Make sure you have CLR Interop permissions

There is one limitation: A webservice reference in AX 2009 does not support credentials. So if your target service needs authentication (username/password) you still have to implement you own DLL like in AX 4.

Example
Add a reference to Microsoft Terraserver USA at the AOT and set the namespace to Microsoft.Terraserver. The WSDL file can be found here

public class TerraService {   ///     /// Simpliefed call that returns a string with the longitude and latitude. ///    ///     /// For demonstation purpose only. ///    public server static str getPlaceFacts(str country,str state,str city) {       InteropPermission permission; Microsoft.Terraserver.Place place; Microsoft.Terraserver.PlaceFacts facts; Microsoft.Terraserver.LonLatPt center; Microsoft.Terraserver.TerraServiceSoapClient wsClient; real lon,lat; ;

permission = new InteropPermission(InteropKind::ClrInterop); permission.assert; wsClient = new Microsoft.Terraserver.TerraServiceSoapClient; place = new Microsoft.Terraserver.Place; place.set_Country(country); place.set_State(state); place.set_City(city);

facts = wsClient.GetPlaceFacts(place); center = facts.get_Center; lon = center.get_Lon; lat = center.get_Lat;

CodeAccessPermission::revertAssert; return strfmt("Long:%1 Lat:%2",lon,lat); } }

Usage: str msg; ;   msg = TerraService::getPlaceFacts("United States","California","Menlo Park"); info(msg);

Links

 * Consuming Web Services in Microsoft Dynamics AX 2009 White Paper
 * Microsoft Architecture Journal
 * Understanding Microsoft Integration Technologies - A Guide to Choosing a Solution
 * Are Web Services Real? by Bruce Eckel
 * Microsoft Service Oriented Architecture
 * Microsoft Dynamics and "real world" SOA
 * SOA macht glücklich (German slides from Big Days 2009, SOA makes happy)