How to debug a power BI connector? - powerbi

I am creating a custom Power BI connector and I have this line of code in my *_PBI.pq
headers=[
#"Accept"="application/csv",
#"Content-Type" = "application/x-www-form-urlencoded"
]
MySec = () =>
let
m_url="https://myComapny.com/api/",
m_token="ABCDEFGH",
myurl=Value.ReplaceType(m_url,Uri.Type),
mytoken=Value.ReplaceType(m_token,Password.Type),
My_Dataset=Web.Contents(myurl, [Content = Text.ToBinary("token="&mytoken&"), Headers = headers]),
Dataset_csv=Csv.Document(My_Dataset)
Dataset_csv_with_header=Table.PromoteHeaders(Dataset_csv)
in
Dataset_csv_with_header;
When I run this connector, it hangs.
I am developing it in VS 2019.
How can I debug it? How can I find which line is the source of the problem?
Is there any way that I can print out (or save it in a file) My_Dataset to check what I am getting from the server to debug the connector?
I am trying to increase the Web.Contents timeout but the following syntax is no correct:
My_Dataset=Web.Contents(myurl, [Content = Text.ToBinary("token="&mytoken&"), Headers = headers],Timeout=1000)
What is the correct format?

This may have been solved already given the time elapsed since asked - but you're missing a comma between the last two lines of your let statement:
Dataset_csv=Csv.Document(My_Dataset) //<------ here
Dataset_csv_with_header=Table.PromoteHeaders(Dataset_csv)

Related

PowerBI expression error using List.Genrate

I've been following some tutorial to handle pagination when calling an API limited to 100 records per request.
I'm using the latest version of PowerBI Desktop.
I have created a blank query and opened the Advanced Editor
let
allDeployments = List.Generate(
() => [result=GetDeployments(0), continuation=0],
each [continuation] <> null,
each [result=GetDeployments(GetNextContinuationToken(continuation)), continuation=GetNextContinuationToken(continuation)],
each [result])
in
allDeployments
and I get this error :
Expression.Error: The name 'continuation' wasn't recognized. Make sure it's spelled correctly.
I can't figure out what is the problem.
Do you have an idea ?
After a good night of sleep, I finally found the issue in my syntax.
I forgot some square brackets around "continuation" variable.
Here is the correct code:
let
allDeployments = List.Generate(
() => [result=GetDeployments(0), continuation=0],
each [continuation] <> null,
each [result=GetDeployments(GetNextContinuationToken([continuation])), continuation=GetNextContinuationToken([continuation])],
each [result])
in
allDeployments

Power BI connect to CRM 2016 Web API

I'm trying to use Power BI Desktop to connect to a CRM Online (2016 Spring Wave 1) instance using CRM's new Web API methods.
When I put my api into a browser like Chrome I get results back. For example if I use https://xxx.crm.dynamics.com/api/data/v8.0/my_records?$select=my_recordid I can see all the results being listed (in batches of 5000)
However, when I try the same thing in PowerBI I get an error telling me that a field already exists (see screenshot)
I've seen some approaches where the URL is wrapped
= Json.Document(Web.Contents("<same url as above>")
but this doesn't seem like a good approach, and I don't know how to use this approach with paging.
So has anyone managed to get Power BI working with the new Web API calls?
I created a new CRM Online Trial instance and retried using the WebAPI URL (https://xxx.crm.dynamics.com/api/data/v8.0/my_records?$select=my_recordid) in Power BI and this time it worked.
It must be something to do with the customisations that I have in place.
Also, I noticed that even though I included a $select=my_recordid filter in my WebAPI request, that PowerBI still loaded all columns names; however, only the column specified in my filter had values.
This would explain why the error occurs even when I specify a single attribute in the $select
I'm rather late to this question, but I've had good success with the "Json.Document(Web.Contents())" method. The trick to the paging issue was wrapping the call in a recursive function. For convenience, I've wrapped that recursive function such that I can pass in the name of a Saved View/Advanced find and get the results of that query.
As a Gist: https://gist.github.com/d4hines/b5d9900fc1ea9d26311d2145505837cb
(OrgUrl as text, QueryName as text, UserView as logical) =>
let
GetQueryByName =
//https://mycrm.mydomain.com/MYORG
(OrgUrl as text, QueryName as text, UserView as logical) =>
let
QueryType = if UserView then "user" else "saved"
,return = OData.Feed(
OrgUrl & "/api/data/v8.0/" & QueryType & "queries?$select="& QueryType & "queryid&$filter=name eq '" & QueryName & "'"
)[userqueryid]{0}
in
return,
QueryAll =
(nextURL, prev) =>
let
prevList = if prev <> null then prev else {},
responseData = Json.Document(Web.Contents(nextURL, [Headers=[Prefer="odata.include-annotations=""OData.Community.Display.V1.FormattedValue"""]])),
return = if responseData[#"#odata.nextLink"]? <> null then #QueryAll(responseData[#"#odata.nextLink"], prevList & responseData[value]) else responseData[value] & prevList
in return,
NamedQuery = OrgUrl & "/api/data/v8.0/contacts?userQuery=" & GetQueryByName(OrgUrl, QueryName, UserView),
return = Table.FromList(QueryAll(NamedQuery, null), Splitter.SplitByNothing(), null, null, ExtraValues.Error)
in return
There are a bit more instructions on the gist if that helps. Hope it helps someone!

Unparsable MOF Query When Trying to Register Event

Update 2
I accepted an answer and asked a different question elsewhere, where I am still trying to get to the bottom of this.
I don't think that one-lining this query is the answer, as I am still not getting the required results (and multi-lining queries is allowed in .mof, as shown in the URLs in comments to the answer ...
Update
I rewrote the query as a one-liner as suggested, but still got the same error! As it was still talking about lines 11-19 I knew there must be another issue. After saving a new file with the change, I reran mofcomp and it appears to have loaded, but the event which I have subscribed to simply does not work.
I really feel that there is not enough documentation on this topic and it is hard to work out how I am meant to debug this - any help on this would be much appreciated, even if this means using a different more appropriate method.
I have the following .mof file, which I would like to use to register an event on my system :
#pragma namespace("\\\\.\\root\\subscription")
instance of __EventFilter as $EventFilter
{
Name = "Event Filter Instance Name";
Query = "Select * from __InstanceCreationEvent within 1 "
"where targetInstance isa \"Cim_DirectoryContainsFile\" "
"and targetInstance.GroupComponent = \"Win32_Directory.Name=\"c:\\\\test\"\"";
QueryLanguage = "WQL";
EventNamespace = "Root\\Cimv2";
};
instance of ActiveScriptEventConsumer as $Consumer
{
Name = "TestConsumer";
ScriptingEngine = "VBScript";
ScriptText =
"Set objFSO = CreateObject(\"Scripting.FileSystemObject\")\n"
"Set objFile = objFSO.OpenTextFile(\"c:\\test\\Log.txt\", 8, True)\n"
"objFile.WriteLine Time & \" \" & \" File Created\"\n"
"objFile.Close\n";
// Specify any other relevant properties.
};
instance of __FilterToConsumerBinding
{
Filter = $EventFilter;
Consumer = $Consumer;
};
But whenever I run the command mfcomp myfile.mof I am getting this error:
Parsing MOF file: myfile.mof
MOF file has been successfully parsed
Storing data in the repository...
An error occurred while processing item 1 defined on lines 11 - 19 in file myfile.mof:
Error Number: 0x80041058, Facility: WMI
Description: Unparsable query.
Compiler returned error 0x80041058
This error appears to be caused by incorrect syntax in the query, but I don't understand where I have gone wrong with this - is anyone able to advise?
There are no string concatenation or line continuation characters being used in building "Query". To keep it simple, you could put the entire query on one line.

Pgocaml customizing sql queries

I am trying to write a query that simply drops a table.
let drop_table dbh table_name =
let query = String.concat " " ["drop table"; table_name] in
PGSQL(dbh) query
I am receiving the following error from the query
File "save.ml", line 37, characters 10-11:
Parse error: STRING _ expected after ")" (in [expr])
File "save.ml", line 1:
Error: Preprocessor error
Why am I getting this error? It appears that this function is valid Ocaml syntax.
Thanks guys!
You cannot construct query when using PG'OCaml's syntax extension. You must provide a literal string. This is the tradeoff for getting PG'Ocaml's compile time query validation. If query could be any OCaml expression, PG'OCaml wouldn't know how to validate it at compile time.
Personally, I've stopped using the syntax extension completely. My feeling is it doesn't scale to large projects. Instead I call prepare and execute directly. For example, this function will create a new database connection (assuming the connection parameters are previously defined), run the given query, and close the connection:
let exec query =
let db = PGOCaml.connect ~host ~user ~database ~port ~password ()
PGOCaml.prepare db ~query ();
let ans = PGOCaml.execute db ~params:[] () in
PGOCaml.close db;
ans
Of course, this isn't a robust implementation and shouldn't be used in production code. It doesn't handle errors and isn't asynchronous.

SBL-ODU-01007 The HTTP request did not contain a valid SOAPAction header

I am hoping someone can help get me in the right direction...
I am using Powerbuilder 12 Classic and trying to consume a Oracle CRM OnDemand web service.
Using Msxml2.XMLHTTP.4.0 commands, I have been able to connect using https and retrieve the session id, which I need to send back when I invoke the method.
When I run the code below, I get the SBL-ODU-01007 The HTTP request did not contain a valid SOAPAction header error message. I am not sure what I am missing??
OleObject loo_xmlhttp
ls_get_url = "https://secure-ausomxxxx.crmondemand.com/Services/Integration?command=login"
try
loo_xmlhttp = CREATE oleobject
loo_xmlhttp.ConnectToNewObject("Msxml2.XMLHTTP.4.0")
loo_xmlhttp.open ("GET",ls_get_url, false)
loo_xmlhttp.setRequestHeader("UserName", "xxxxxxx")
loo_xmlhttp.setRequestHeader("Password", "xxxxxxx")
loo_xmlhttp.send()
cookie = loo_xmlhttp.getResponseHeader("Set-Cookie")
sesId = mid(cookie, pos(cookie,"=", 1)+1, pos(cookie,";", 1)-(pos(cookie,"=", 1)+1))
ls_post_url = "https://secure-ausomxxxx.crmondemand.com/Services/Integration/Activity;"
ls_response_text = "jsessionid=" + sesId + ";"
ls_post_url = ls_post_url + ls_response_text
loo_xmlhttp.open ("POST",ls_post_url, false)
loo_xmlhttp.setRequestHeader("COOKIE", left(cookie,pos(cookie,";",1)-1) )
loo_xmlhttp.setRequestHeader("COOKIE", left(cookie,pos(cookie,";",1)-1) )
ls_post_url2 = "document/urn:crmondemand/ws/activity/10/2004:Activity_QueryPage"
loo_xmlhttp.setRequestHeader("SOAPAction", ls_post_url2)
loo_xmlhttp.send()
ls_get_url = "https://secure-ausomxxxx.crmondemand.com/Services/Integration?command=logoff"
loo_xmlhttp.open ("POST",ls_get_url, false)
loo_xmlhttp.send()
catch (RuntimeError rte)
MessageBox("Error", "RuntimeError - " + rte.getMessage())
end try
I believe you are using incorrect URL for Login and Logoff;
Here is the sample:
https://secure-ausomxxxx.crmondemand.com/Services/Integration?command=login
https://secure-ausomxxxx.crmondemand.com/Services/Integration?command=logoff
Rest of the code looks OK to me.
I have run into similar issues in PB with msxml through ole. Adding this may help:
loo_xmlhttp.setRequestHeader("Content-Type", "text/xml")
you need to make sure that the your value for ls_post_url2 is one of the values that is found in the wsdl file. Just search for "soap:operation soapAction" in the wsdl file to see the valid values for SOAPAction.