Working with WS links in ELMA Designer

When integrating ELMA with other IT systems, it often happens that a third-party system has a deployed WEB service, described according to the rules of WSDL (Web Services Description Language).

The description is XML-based and is represented by a structure of server requests/responses and data formats.

An example of free WSDL without authentication – information service of the Central Bank of Russia.

ELMA provides a service for starting business processes from external systems (you can find use cases in this article): <ELMAServerAddress>/Modules/EleWise.ELMA.Workflow.Processes.Web/WFPWebService.asmx?WSDL.

ELMA designer allows initializing a correctly described WSDL as a new class in a script module. At the same time, you can use such a service without the need to additionally initialize WEB requests.

Let's take a look at several examples of working with WSDL. They have different integration specifics and result processing.

Getting currency exchange rates for the current date

You can get all the currency exchange rates in the script module of a process and display them in the console as plain text with separators. For this, use the service described above.

First, add a link to the service by selecting Add a link to a service in the context menu (fig. 1):

Fig. 1. Adding a service

After that, a dialog box will open, where you need to specify the WEB service address and add the necessary namespace for the imported class. By clicking Go To you can view what methods are implemented on the service end. The namespace must not match an existing one. An example of filling out the dialog box is shown in fig. 2:

Fig. 2. WS link import settings

Use the following namespaces:

using System.ServiceModel;
using System.Data;

Also, add the System.Data assembly.

Script text:

public void GetCBCourses()
{
    //initialize the required parameters
    BasicHttpBinding myBinding = new BasicHttpBinding();
    //the address must match the address of the added WS link
    EndpointAddress address = new EndpointAddress("http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx?WSDL");
    //for illustrative perposes, the code contains the full path to the added class
    //services usually contain a class with the name like "SoapClient" or something similar; it will be the main service for calling other methods
    //initialization must include the parameters, intitialized above (protocol and address settings)
    EleWise.ELMA.Model.Scripts.CBRru.DailyInfoSoapClient newWFP = new EleWise.ELMA.Model.Scripts.CBRru.DailyInfoSoapClient(myBinding,address);        
    //Use the service method, which returns the information as DataSet - this is a structure that contains a set of data tables
    //the GetCursOnDateXML method allows returning the exchange rate as XML
    DataSet cursSet = newWFP.GetCursOnDate(DateTime.Now);
    //usually, service documentation specifies, what data is stored in each field, however, as an example, take a look at fool cycle for each table from the received structure
    foreach(DataTable dTable in cursSet.Tables)
    {
        Console.WriteLine("Table name: "+dTable.TableName);
        //show table column names
        foreach(DataColumn tColumn in dTable.Columns)
        {
            Console.Write(tColumn.ColumnName+" | ");
        }
        //change line
        Console.WriteLine("");
        //for each line, show the values from all the columns
        foreach(DataRow tRow in dTable.Rows)
        {
            for(int i = 0; i < dTable.Columns.Count; i++)
            {
                Console.Write(tRow[i].ToString().Trim()+" | ");
            }
            //change line
            Console.WriteLine("");
            
        }
    } 
}

Starting a process via WS with parameters

With some services, a more complex integration is possible. Some methods imply using non-standard data types, which are also described in WSDL, as parameters.

Let's take a look at such an integration. As an example, a business process will be started in ELMA via a special service, mentioned at the beginning of this article. The process will be started in the same system, where the script is executed. However, such integration can be implemented with different ELMA server instances.

Similarly, add a link to the service. In this case, ELMA is installed on localhost:8000 (fig. 3).

Fig. 3. Setting up the process start service

Start the process using a script and set the value of the Description context variable.

public void RunProcWithWSDL()
{
    //initialize instances of the classes, described in the service
    //WebData - is an array of items to pass
    EleWise.ELMA.Model.Scripts.WFPRun.WebData newWebDt = new EleWise.ELMA.Model.Scripts.WFPRun.WebData();
    //WebDataItem - is an item to pass, represented as: "Name"-"Value", where "Name" matches the name of the started process context variable
    EleWise.ELMA.Model.Scripts.WFPRun.WebDataItem newWebDtItm = new EleWise.ELMA.Model.Scripts.WFPRun.WebDataItem();
    //Separately initialize the WebDataItem list, which then is converted to an array
    List<EleWise.ELMA.Model.Scripts.WFPRun.WebDataItem> newWebDtItmArr = new List<EleWise.ELMA.Model.Scripts.WFPRun.WebDataItem>();
    //set parameters of the started process; the context contains the "Description" parameter
    newWebDtItm.Name = "Description";
    newWebDtItm.Value = "Start from a script via a WEB service";
    newWebDtItmArr.Add(newWebDtItm);
    //if there are several variables, they must be added consequently to  newWebDtItmArr
    newWebDt.Items = newWebDtItmArr.ToArray();
    //parameters for starting the service methods
    BasicHttpBinding myBinding = new BasicHttpBinding();
    EndpointAddress address = new EndpointAddress("http://localhost:8000/Modules/EleWise.ELMA.Workflow.Processes.Web/WFPWebService.asmx?WSDL");
    //similarly, initialize the main WEB service class
    EleWise.ELMA.Model.Scripts.WFPRun.WFPWebServiceSoapClient newWFP = new EleWise.ELMA.Model.Scripts.WFPRun.WFPWebServiceSoapClient(myBinding,address);
    //method parameters: "Login", "Password", "Process token", "Instance Name", "WebData array"
    //the instance name is not specified, since a mechanism for naming instance by a template is used
    var rslt = newWFP.Run("userlogin","userpwd","4a489e0b-e4da-4799-9a5a-c0f353d7925f","",newWebDt);
    //display the ID of the started instance
    Console.WriteLine(rslt.ToString());
}

After executing the script, you get the ID of the started instance (fig. 4).

Fig. 4. Script execution result

On the process instance information page, check that the context variable was filled in (fig. 5).

Fig. 5. Process instance information

Getting data from a service, that requires authentication

If the information, accessible via a WEB service, must be restricted, the service uses authentication parameters.

Consider an example of getting data on tables of the Microsoft Navision 2017 system, via its WEB service. 

In this case, when adding a link, a dialog box for entering a login and password will open. The link will be added after you sign in (fig. 6).

Fig. 6. WEB service authentication parameters

The service initialization will also be different in the code. In particular, additional description of authentication parameters will be required.

public virtual void GetInfoFromNavision (Context context)
{
    //initialize parameters
    BasicHttpBinding myBinding = new BasicHttpBinding();
    //if authentication is used, additional security parameters must be specified
    myBinding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
    //you can find out which authentication type to use from the system administrator
    myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
    //the address must match that of the added link
    EndpointAddress address = new EndpointAddress("http://adressHide.net:7117/adressHide_Oper2/WS/adressHide/Page/UMD_TablesList");
    //in this case, the main service-class name includes the word Client
    EleWise.ELMA.Model.Scripts.NavisionTables.UMD_TablesList_PortClient navClien = new EleWise.ELMA.Model.Scripts.NavisionTables.UMD_TablesList_PortClient(myBinding,address);
    //specify authentication parameters (the same as when adding the link)
    navClien.ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential("userlogin", "userpws");
    //call a method for getting all the system tables
    //this method requires passing parameters, which are types, described in WSDL
    //initialize an empty object array-filter
    List<EleWise.ELMA.Model.Scripts.NavisionTables.UMD_TablesList_Filter> tabFilt = new List<EleWise.ELMA.Model.Scripts.NavisionTables.UMD_TablesList_Filter>();
    var tablFiltArray = tabFilt.ToArray();
    //get a collection of table items; method parameters: "filter-table", "filter-string", "number of selected items" 
    var tabl = navClien.ReadMultiple(tablFiltArray,"",100);
    foreach(var element in tabl)
    {
        //display the attributes of each item; all the available attributes will be available via IntelliSense for the item
        //in this case, those are table ID and name
        Console.WriteLine(element.Table_ID.ToString()+" * " + element.Table_Caption_Rus);
    }
}

These use cases allow conveniently working with WEB services. There is no need to describe additional classes for serializing and deserializing data. Object attributes, service classes and methods are available via IntelliSense (fig. 7). It significantly facilitates code development and improves readability.

Fig. 7. Working with a WEB service in code