In this post we will take a look how to consume a REST service from the Smart Office JScript code. Related blog posts that focus on M3 APIs can be found at the following links.
Calling M3 APIs in JScript
Background workers in Smart Office scripts
Setting up the REST Data Service
Let’s start with the script code. It’s necessary to import the following three assemblies to gain access to the necessary classes and interfaces.
import MForms;
import Mango.Core.Services;
import System.ComponentModel;
The first step is to get a handle to the REST data service from the DataServiceManager.
var svc : IDataService = DataServiceManager.Current.Get("REST");
The REST data service is configured with a parameter set put in a DataItemCollection, so we start by setting the service address. I’m going to use a fake online REST service for the example to demonstrate how it’s done.
var params = new DataItemCollection();
params.Add(new DataItem(RestDataService.KeyBaseAddress, "https://jsonplaceholder.typicode.com"));
The available parameters can be found in the RestDataService class, the name starting with Key. It’s necessary to set KeyBaseAddress for the REST requests. KeyUri can contain a relative URI that is combined with KeyBaseAddress. Both parameters support variable substitution using names within curly braces {}. For example:
params.Add(new DataItem(RestDataService.KeyUri, "/users/{userId}"));
params.Add(new DataItem("userId", e.Argument));
or like this. Both will will result in the same endpoint URL.
params.Add(new DataItem(RestDataService.KeyUri, "/users/" + e.Argument));
If the userId variable equals to 7 the combined parameters results in the REST URL:
https://jsonplaceholder.typicode.com/users/7
The service request and response type headers must be specified unless the default values are required. The default values are the following two lines, that can be added for clarity but also omitted.
params.Add(new DataItem(RestDataService.KeyAcceptHeader, RestDataService.ContentTypeApplicationXml));
params.Add(new DataItem(RestDataService.KeyOutputType, RestDataService.OutputTypeDataItem));
Use the Background Worker to Prevent UI Freeze
Now we’re almost done, but the data service require that it’s running on a background thread. If not, it will throw an Exception to make you aware of that. This is done to prevent potential UI freeze and annoyed users. Let’s have a look at a simple solution by using the BackgroundWorker class.
var worker = new BackgroundWorker();
// Set the function that performs the service call
worker.add_DoWork(OnDoWork);
// Set the function that performs update and clean-up after the call is done
worker.add_RunWorkerCompleted(OnRunWorkerCompleted);
// Launch the service call and provide start parameters
worker.RunWorkerAsync(serviceParameters);
The OnDoWork function will execute on the background thread and call the data service. When done the OnRunWorkerCompleted function will execute on the UI thread to handle the response and do clean up after the call. Please, always handle Exceptions in your code!
public function OnDoWork(sender : Object, e : DoWorkEventArgs)
{
try
{
var serviceParameters = e.Argument;
// The data service call is done here (this is the background thread)
e.Result = serverResponse
}
catch(ex)
{
// Exceptions must be handled
}
}
public function OnRunWorkerCompleted(sender : Object, e : RunWorkerCompletedEventArgs)
{
try
{
var worker = sender;
worker.remove_DoWork(OnDoWork);
worker.remove_RunWorkerCompleted(OnRunWorkerCompleted);
var serviceResponse = e.Result;
// The worker has completed its work (this is the UI thread)
}
catch(ex)
{
// Exceptions must be handled
}
}
The Full Script Example
Here is the full script example for you to test in the ISO Script Tool mforms://jscript:
import MForms;
import Mango.Core.Services;
import System.ComponentModel;
package MForms.JScript
{
class RESTDemo
{
var debug;
var controller;
public function Init(element: Object, args: Object, controller : Object, debug : Object)
{
this.debug = debug;
this.controller = controller;
debug.WriteLine("Script Initializing.");
DoRestCallOnBackgroundWorker();
}
public function DoRestCallOnBackgroundWorker()
{
debug.WriteLine("The REST service call is made on a background worker");
var worker = new BackgroundWorker();
worker.add_DoWork(OnDoWork);
worker.add_RunWorkerCompleted(OnRunWorkerCompleted);
var userId = 7;
worker.RunWorkerAsync(userId);
}
public function OnDoWork(sender : Object, e : DoWorkEventArgs)
{
try
{
debug.WriteLine("OnDoWork started");
debug.WriteLine("Calling a REST service getting DataItem response data");
var svc : IDataService = DataServiceManager.Current.Get("REST");
var params = new DataItemCollection();
params.Add(new DataItem(RestDataService.KeyBaseAddress, "https://jsonplaceholder.typicode.com/"));
params.Add(new DataItem(RestDataService.KeyUri, "users/{userId}"));
params.Add(new DataItem(RestDataService.KeyAcceptHeader, RestDataService.ContentTypeTextXml)); // default value
params.Add(new DataItem(RestDataService.KeyOutputType, RestDataService.OutputTypeDataItem)); // default value
params.Add(new DataItem("userId", e.Argument));
var dataRequest = new DataRequest(params);
dataRequest.OperationType = "GET";
var dataResponse = svc.Execute(dataRequest.OperationType, dataRequest);
e.Result = dataResponse.Data;
debug.WriteLine("OnDoWork done");
}
catch(ex)
{
debug.WriteLine("Exception: " + ex.Message);
e.Result = null;
}
}
public function OnRunWorkerCompleted(sender : Object, e : RunWorkerCompletedEventArgs)
{
try
{
debug.WriteLine("OnRunWorkerCompleted running on UI thread");
var worker = sender;
worker.remove_DoWork(OnDoWork);
worker.remove_RunWorkerCompleted(OnRunWorkerCompleted);
if(e.Error != null)
{
debug.WriteLine("Error: " + e.Error.Message);
return;
}
debug.WriteLine("Fetched user data for:");
var dataItem = e.Result;
debug.WriteLine(dataItem["name"] + " (" + dataItem["username"] + ")" + " Phone " + dataItem["phone"]);
}
catch(ex)
{
debug.WriteLine("Exception: " + ex.Message);
}
}
}
}
Debug output when running the sample in the Script Tool.
Script Initializing.
The REST service call is made on a background worker
OnDoWork started
Calling a REST service getting DataItem response data
OnDoWork done
OnRunWorkerCompleted running on UI thread
Fetched user data for:
Kurtis Weissnat (Elwyn.Skiles) Phone 210.067.6132
You must be logged in to post a comment.