Hi,
Is there an easy way to expose all the Service Methods (and datatypes, arrays and such) to the Script for .Net so js can be written with these methods and datatypes?
Thanks!
Hi,
Is there an easy way to expose all the Service Methods (and datatypes, arrays and such) to the Script for .Net so js can be written with these methods and datatypes?
Thanks!
Hello
No, unfortunately there is no such way.
You’ll need to write or generate wrapper classes for the services/methods/data types.
ok thanks for the quick response… I am assuming it can be done manually. ?
Yes.
However let’s start from the very beginning: what do you need to achieve?
I want to be able to call a service method from my javascript and run it within my application. or have the javascript pass back the method I want to run with the parameters (some being complex types) and run it.
So something like this:
var user = {name: “john”, password: “psw”}
Service.Login(user.name, user.password);
where Login is a service method in the rodl file.
Anton,
essentially, Dana is looking for how to expose custom APIs to the script engine.
Yes Marc is right. Sorry if I am not explaining it well. Currently I have a “wrapper” around the rodl methods that I read in from a script. So in the above example a user in the script does a function call but that function is just an exposed wrapper of the real method of the service. This is extremely limited and way too much coding. I want to call service method directly from my script without the wrapper. It gets complicated (to me anyway) because we have a lot of complex datatypes that need to be passed. It is simple if it is a string or int but not so much when they are arrays and such. So, in the script if we could populate the complex datatype and pass it that would be awesome. OK, maybe I just talked about 2 different things.
Calling an method that is in the Intf file and passing complex datatypes in the script.
So, you want to call an RO SDK server from Script and need to pass custom type parameters w/o writing a lot of wrapper code.
Take a look at the HttpAPI then. This is a feature that allows to expose server methods via REST protocol. The only code you’d need to implement in .NET and then pass to the Script in this case will be a class that will expose to Script methods like
function get(url, options);
function post(url, payload, options);
function put(url, payload, options);
function delete(url, options);
Using it you would be able to perform calls using code like
var user = {'name': 'john', 'password': 'psw'};
var response = http.post('login', user);
Server-side changes are minimal in this case - attributes are added to methods exposed via API to define Http method and Uri used to call them. Also a login method can be added that will return access token instead of plain true/false
If needed I can write a sample for you where a complex typed parameter will be sent from the server and then response is utilized by the caller script.
yes an example would be awesome. Thank you for the suggestion.
Another option could be to look at dynamically generating requests. i.e. rather than using the code generated in the Intf, dynamically read the RODL and build & send off the message yourself.
I was actually headed down this path. thanks marc!
thank you Antonk, I will take a look at this.
Hello
Debugger.zip (144.7 KB)
This is the sample that allows to execute this script:
var login = http.post('login', { 'username': 'AAA', 'password': 'AAA' });
if (login.code >= 300) {
// Something went wrong. Login was successful
throw 'Login error';
}
var token = login.content;
var options = [];
options['Access-Token'] = token;
var customers = http.get('customers', options).content;
for(int i = 0; i < customers.length; i++) {
writeln(i + ': ' + customers[i].Name);
}
// Let's try to insert come data
var customer = new Object();
customer.Id = 'd973ddb3-69fc-4e7d-8403-dac4d574b226';
customer.Name = 'Test Name';
customer.Discount = 0;
// Note that we now send the auth header with the request
http.post('customers', customer, options);
// 'delete' is a reserved word in JS. So this replacement is used
http.deleteRequest('customers/' + 'd973ddb3-69fc-4e7d-8403-dac4d574b226', customer, options);
http.post('logout', options);
In this script we log in into a server and then receive array of complex types from it and then send a request with a complex type to the server. None of the type structures and.or server methods are hardcoded in the .NET code. The only changes made to the original samples were registration of the Http service
ScriptEngine.Globals.SetVariable("http", new HttpService(ScriptEngine.GlobalObject, "http://localhost:8099/api/"));
and that service itself: HttpService.zip (1.2 KB)
The server will be described in the next post
This is the server used: HttpAPI Sample.zip (64.2 KB)
In the server app:
Note that in the sample above separate ApiService service was added only because the original Data Abstract methods are hard to expose via Http API. In most cases no additional method definitions are required. Instead one can just mark existing methods with additional attributes and let RO SDK to do the rest
Here you can find more information on HttpAPI:
This feature is also available in Delphi servers as well
Thank you very much Antonk. I am looking into your code and info.
Just a side note - in the HttpService I hardcoded the root Url.
If you remove that hardcode and let the user to call http as
var customers = http.get('http://localhost:8099/api/customers', options).content;
(ie with full Url) then you will be able to call any service/website that provides REST interface.
Also, your initial way of calling the service via _Intf file can be also simplified. There is no need to write wrappers for data structures. Instead I’d implement a reflection-based mapper that would take the destination object (based on the method RODL definition) and fill it from the Script-provided object. There will be some efforts in writing such mapper (in terms of support complex-typed values and arrays) yet it is not impossible.
Then you could call the serviceeither using the DynamicRequest approach mentioned by Marc or just by calling the _Intf method using reflection.
I like this approach a lot. I want to make the rodl file totally decoupled from the core application. So like Service Tester it reads the rodl file, reads the scripts on what service methods to execute on the server and schedule it to go.