How to send a Post query using Excel Power Query - excel

I am trying to retrieve data from the Betfair API and have to send some extra info as headers and Json data. Details below:
Url:
https://api.betfair.com/exchange/account/json-rpc/v1
Headers:
{ 'X-Application' :'exampleappid', 'X-Authentication' :'examplesessionkey','Content-Type':'application/json' }
formdata:
{"jsonrpc": "2.0","method": "AccountAPING/v1.0/getAccountStatement", "params": {"itemDateRange":{},"includeItem":"ALL"}, "id": 1}
Currently in excel I go to the Data tab then click on New Query>From Other Sources>From Web>Advanced then I type in the url and the headers in the respective fields. Where do I put in the other form data, or its just not possible?
Edit:
I have created the following query in the query editor :
let
formdata = "{""jsonrpc"": ""2.0"",""method"": ""AccountAPING/v1.0/getAccountStatement"", ""params"": {""itemDateRange"":{},""includeItem"":""ALL""}, ""id"": 1}" ,
Source = Web.Contents("https://api.betfair.com/exchange/account/json-rpc/v1",[Headers= [#"X-Application"="appkey", #"X-Authentication"="sessionkey", #"Content-Type"="application/json"],
Content=Text.ToBinary(formdata)])
in
Source
and I get the following error DataSource.Error: The server committed a protocol violation. Section=ResponseHeader Detail=Header name is invalid
Details:
https://api.betfair.com/exchange/account/json-rpc/v1

Unfortunately I don't think there is a field in the UI for web connections to set the formdata, but it can be done by manually setting up the connection. I think what you have without the formdata would look like this in the M code
Web.Contents(
"https://api.betfair.com/exchange/account/json-rpc/v1",
[Headers=[#"X-Application"="exampleappid", #"X-Authenticaion"="examplesessionkey", #"Content-Type"="application/json"]]
)
There is a "Content" field that can be added after the Headers. In most examples I've seen (and I recall doing this myself once though I don't remember what for), you setup a string for the form data and use Text.ToBinary before passing it into the Content field. So a full query would look something like this:
let
formdata = "{""jsonrpc"": ""2.0"",""method"": ""AccountAPING/v1.0/getAccountStatement"", ""params"": {""itemDateRange"":{},""includeItem"":""ALL""}, ""id"": 1}" ,
Source =
Web.Contents(
"https://api.betfair.com/exchange/account/json-rpc/v1",
[
Headers=[#"X-Application"="exampleappid", #"X-Authenticaion"="examplesessionkey", #"Content-Type"="application/json"],
Content = Text.ToBinary(formdata)
]
)
in
Source

Related

Construct form-data with duplicate keys in Nodejs client post request body

I am trying to make a post request which body consists of form-data. But the API rest spec, says the form data should look like this :
names[]= company name 1&names[]=company name 2
I tried
form: {'names[]': "google" ,'names[]': "kraft", 'fields[]': "Country",
'fields[]':"ISIN"}
But the server receives only the first names[] and fields[]. The second ones are cut.
Server: Post data: {"names"=>["kraft"], "fields"=>["ISIN"]}
Then I tried to add array as value:
form: {'names[]': ["google", "kraft"], 'fields[]': ["Country","ISIN"] }
Server: Post data: {"names"=>[{"0"=>"google", "1"=>"kraft"}], "fields"=>[{"0"=>"Country", "1"=>"ISIN"}]}
Looking at the server request, I see that it accepts body in this format:
BODY: names[]=google&names[]=kraft&fields[]=ISIN&fields[]=Country
But I cant construct such form in my node-client side.
I am using this library: https://www.npmjs.com/package/request
********* EDIT ********
This one actually woked:
form: "names[]=google&names[]=kraft&fields[]=Country&fields[]=ISIN"
Now the question is how to form this string using https://github.com/form-data/form-data
No append doesn't work I tried.
It's recommended for keys to be unique and not have brackets in their naming. In your case, names[] and fields[] repeat themselves
const form = {
form: {
names: ['google', 'kraft'],
fields: ['Country', 'ISIN']
}
};
request.post('http://yourwebsite.com', form);
EDIT
names[]=google&names[]=kraft&fields[]=ISIN&fields[]=Country
May be valid, but depending on framework/language, only one entry will be taken into consideration (first or last). So it is equivalent to
names[]=google&fields[]=ISIN // considering first are chosen
Also as you can see
Server: Post data: {"names"=>["kraft"], "fields"=>["ISIN"]}
The brackets were filtered out, so this will be again the same thing
names=google&fields=ISIN // considering first are chosen

Parse values from the JSON returned by URL of Google Place API

I am creating a bot using dialogflow-fulfillment, and I am using Google Place API to pull additional information about hospitals.
I have made a dummy response, for the sake of example, that is returned by Google Place API, here is the link: http://www.mocky.io/v2/5c2b9f9e3000007000abafe3
{
"candidates" : [
{
"formatted_address" : "140 George St, The Rocks NSW 2000, Australia",
"name" : "Museum of Contemporary Art Australia",
"photos" : [
{
"height" : 3492,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/105784220914426417603/photos\"\u003eKeith Chung\u003c/a\u003e"
],
"photo_reference" : "CmRaAAAAaGaCX-kivNEaJ-z97AduTYgW3d98uv53-8skNrS1k1GTgOtiQ1-Z2gfWJydrpkrshuV_kHPKizl088dezEJgIxYGoTWqtJgah-u_I46qNNYMfUbk8LKBZqxzkHyIL1nWEhBO6lPa0NgvlyLGBrXpXFPUGhT0lAUj_oCiOWV2MEYdBeKf-kTtgg",
"width" : 4656
}
]
}
],
"status" : "OK"
}
I need to parse values of my choice from the JSON returned by Google Place API. For example, If I had to parse value of 'name' from the JSON above using Python, I would do this:
import requests, json
api_key = ''
r = requests.get('https://maps.googleapis.com/maps/api/place/findplacefromtext/json?input=Museum%20of%20Contemporary%20Art%20Australia&inputtype=textquery&fields=photos,formatted_address,name&key=' + api_key)
x = r.json()
y = x['candidates']
print(y[0]['name'])
Above code for the job is lucid and works perfectly. Considering my inexperience in Nodejs, would you please let me know something similar in Nodejs to parse the value, for instance, the value of 'name'?
Your valuable reply will encourage me.
P.S: Humbly, the question involves first making a call to Google Place API and then parsing values from the returned JSON. Please follow the steps given in Python code above for better understanding.
Get the API response in an async HTTP request (there are tons of npm libraries like request to help you automatically set headers etc), then use standard library JSON.parse(body) to get an plain JavaScript object which contains a structured representation of the API response.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse

DataTables reload table with different pageLength param

Based on this question.
I initialize my datatables.js table with the following code:
var table_entity = $('#myTable').DataTable({
"pageLength":getParameterByName('pageLength'),//getting param from query string
fixedHeader: true,
"ajax": {
"url": myUrl,
"data": function(d) {
d.type = $('#mytype').val();
}
}
});
So I know how to reload my datatable with different ajax params. Now I need to reload it with different pageLength param which does not belong to ajax section and is recorded during datatables init stage. I tried to pass it directly during reloading with the following code:
table_entity.ajax.reload({
"pageLength":77 //some new param different from the initial one
});
But it did not work, the table is reloaded with initial pageLength value. Any ideas how to fix it would be welcome. Thank you.
UPD_1
managed to do that with
1st: complete destruction of a table:
$('#MyTable').DataTable().destroy();
$('#MyTable tbody').empty();//note tbody here
2nd: reinit the table with updated params:
table_data.displayStart = Number(getParameterByName('displayStart'));
table_data.pageLength = Number(getParameterByName('pageLength'));
table_data.iDisplayStart = Number(getParameterByName('displayStart'));
table_data.iDisplayLength = Number(getParameterByName('pageLength'));
$('#MyTable').DataTable(table_data);
Note 2 params - iDisplayStart and iDisplayLength here
Is it possible to do the same without destruction of the table, but during ajax.reload phase? Thank you.
Is it possible to do the same without destruction of the table, but
during ajax.reload phase?
You can hook into the xhr.dt event and update page.len() from there. Example :
$('#example').on('xhr.dt', function(e, settings, json, xhr) {
table.page.len(json.data.length).draw()
})
Will dynamically set the page length to maximum i.e length of data. Demo -> http://jsfiddle.net/d72zbyus/
So you could use table.page.len(77).draw() or whatever. xhr.dt is triggered after each AJAX request.
It is not clear to me where your new pageLength come from exactly. If it is part of the returned JSON (as I suspect) you could do table.page.len(json.pageLength).draw().

Outlook REST API to extract URLs in the message body

Is there an Outlook REST API that gives me all the urls extracted from the body of the message? Some thing like what EWS's EntityExtractionResult does?
No there isn't. However, you can retrieve extended properties, so you should be able to request the PidNameExtractedUrls property.
If you dig through those open specs, you should find these details on PidNameExtractedUrls:
Property set: PSETID_XmlExtractedEntities {23239608-685D-4732-9C55-4C95CB4E8E33}
Property name: XmlExtractedUrls
So that would mean I could make the following request (assuming you're using the Outlook endpoint, not Graph):
GET https://outlook.office.com/api/v2.0/me/messages?$expand=SingleValueExtendedProperties($filter=PropertyId eq 'String {23239608-685D-4732-9C55-4C95CB4E8E33} Name XmlExtractedUrls')
For Graph, you would replace PropertyId with id.
That will include something like this in the message entities that have this property set:
"SingleValueExtendedProperties": [
{
"PropertyId": "String {23239608-685d-4732-9c55-4c95cb4e8e33} Name XmlExtractedUrls",
"Value": "<?xml version=\"1.0\" encoding=\"utf-16\"?><UrlSet><Version>15.0.0.0</Version><Urls><Url StartIndex=\"0\"><UrlString>https://www.google.com</UrlString></Url><Url StartIndex=\"23\"><UrlString>https://developer.microsoft.com/outlook</UrlString></Url></Urls></UrlSet>"
}
]

add/read parameters to/from the url

If I add parameters to the url in the Objective-C code, is it possible to read it from the client?
Example:
- (NSURL *)serverURL {
return [NSURL URLWithString:#"http://rap.eclipsesource.com/demo?parametername=value"];
}
In the Client-JavaCode I can get the value of the parameter like this:
String parameter = RWT.getRequest().getParameter("parametername");
If I access the "app" with the browser I get a value for the parameter. If I access the app with the TabrisClient the value is null.
Is there a way to get the value also in the TabrisClient?
Update:
The server does not directly extract the query string from the request URL, but from the first JSON message received from the client. The web client provides the parameter queryString in the head part of the first UI request. Example:
{
"head": {
"queryString": "foo=23&bar=42",
"requestCounter": ...
},
"operations": [
...
]
}
You would have to fake this behavior in your Tabris client. I'd suggest that you file an issue against Tabris to provide API to set startup parameters.
Original answer:
If you're going to hard-code the parameter in the tabris client anyway, you could set the variable based on the connected client:
parameter = (RWT.getClient() instanceof WebClient)
? RWT.getRequest.getParameter("parametername")
: "tabris-value";
BTW, access to request parameters is going to change in RAP 3.0. Instead of RWT.getRequest().getParameter(), a ClientService will provide the parameters.

Resources