I'm trying to change Power BI connection string using their API (Microsoft.IdentityModel.Clients.ActiveDirectory). Using this API, I'm able to publish .pbix file to my PBI account. But Getting Bad Request error while trying to update dataset connection string. Here is my code.
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Accept", "application/json");
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
var restUrlImportPbix = POWER_BI_SERVICE_ROOT_URL + $"datasets/{dataset.id}/Default.SetAllConnections";
var postData = new { connectionString = _powerBISettings.DataConnectionString };
var response = client.PostAsync(restUrlImportPbix, new StringContent(JsonConvert.SerializeObject(postData), Encoding.UTF8, "application/json")).Result;
Also I found in a blog that SetAllConnections only works on direct query connections. Anybody help please.
In addition to trying to redirect the datasource by changing the connection string, you can achieve the same by allowing the report itself to switch it's data source. To do this, use connection specific parameters in the report. To do this, open Power Query Editor by clicking Edit Queries and in Manage Parameters define two new text parameters, lets name them ServerName and DatabaseName:
Set their current values to point to one of your data sources, e.g. SQLSERVER2016 and 'AdventureWorks2016. Then right click your query in the report and openAdvanced Editor`. Find the server name and database name in the M code:
and replace them with the parameters defined above, so the M code will look like this:
Now you can close and apply changes and your report should work as before. But now when you want to change the data source, do it using Edit Parameters:
and change the server and/or database name to point to the other data source, that you want to use for your report:
After changing parameter values, Power BI Desktop will ask you to apply the changes and reload the data from the new data source. To change the parameter values (i.e. the data source) of a report published in Power BI Service, go to dataset's settings and enter new server and/or database name:
If the server is on-premise, check the Gateway connection too, to make sure that it is configured properly to use the right gateway. You may also want to check the available gateways in Manage gateways:
After changing the data source, refresh your dataset to get the data from the new data source. With Power BI Pro account you can do this 8 times per 24 hours, while if the dataset is in a dedicated capacity, this limit is raised to 48 times per 24 hours.
To do this programatically, use Update Parameters / Update Parameters In Group and Refresh Dataset / Refresh Dataset In Group REST API calls, or if I modify your code, something like this:
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Accept", "application/json");
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
var restUrlUpdateParameters = POWER_BI_SERVICE_ROOT_URL + $"datasets/{dataset.id}/Default.UpdateParameters";
var postData = new { updateDetails = new[] { new { name = "ServerName", newValue = "NEWSERVER" }, new { name = "DatabaseName", newValue = "Another_AdventureWorks2016" } } };
var responseUpdate = client.PostAsync(restUrlUpdateParameters, new StringContent(JsonConvert.SerializeObject(postData), Encoding.UTF8, "application/json")).Result;
var restUrlRefreshDataset = POWER_BI_SERVICE_ROOT_URL + $"datasets/{dataset.id}/refreshes";
var responseRefresh = client.PostAsync(restUrlRefreshDataset, null).Result;
This is a easy way to make your reports "switchable", e.g. for switching one report from DEV or QA to PROD environment, or as part of your disaster recovery plan, to automate switching all reports in some workgroup to another DR server. In general I recommend to define such connection specific parameters in all reports.
Related
I am having some issues finding information about adding some logic field in my RestRequest using V 107. I am trying to add a filter to my GET query
dl_document_indexed_date gt '2020-12-07T08:30:42.483Z'
There are a few other queries in the call which i am using Dictionary<string, string> to store them, and it works great however it only works if i am looking for something equal to, as adding it to the parameters it seems by default its equal to and i am not finding any way to add any other logic, gt/ge/lt/le etc. using the older version i would just append the url adding the logic i need, but i am not seeing a way to append the url either. Looking over their documentation i either missed it, cant find it, or its not there. Any help would be greatly appreciated! My method looks like this
public static async Task<string> GET_API(String RequestUrl, string RequestObject, Dictionary<string, string> parameters)
{
var request = new RestRequest(RequestObject);
var options = new RestClientOptions(RequestUrl)
{
ThrowOnAnyError = true,
Timeout = -1
};
var client = new RestClient(options);
client.Authenticator = new OAuth2AuthorizationRequestHeaderAuthenticator("Bearer " + TokenManager.GetAccessTokenString("TRN"));
foreach (var parameter in parameters)
{
request.AddQueryParameter(parameter.Key, parameter.Value);
}
var response = await client.GetAsync(request);
return response.Content.ToString();
}
I send the BaseURL , the RequestObject would be table i am calling in the base URL, and my dictionary item contains the Field name, and the field values that i am dynamically generating on another method that would append the string. and example would be
parameters.Add("dl_document_name", "TableA");
which would append the URL with dl_document_name eq 'TableA'
it would call the API after i add the OAuth Token i create and return the data i need and send it back. or another option i guess could be appending the string with the logic i need to return the data
You should use OData, it's easy to implement and it has different kind of filters, you also can set which filters are usable and which aren't.
https://www.odata.org/
I figured out a work around, if i only have one i can add it to the first parameter and adding the filter as the first key, which will work unless i have multiple conditions that are not eq
parameters.Add("filter","dl_document_indexed_date gt '2020-12-07T08:30:42.483Z'");
I am building a program using C# and .WPF framework to create a personal recommendation system but I am having a problem when I get the audio tracks for multiple track Ids at once.
I have coded the below to request the audio features from the Spotify, and the Id array and Ids both work fine. If i change the RestRequest to a singular Id (Id[3]), the variable audio will be the features. Similiarly, if I put the request code in a for loop to do for each Id in the array each time the var audio would contain the audio features.
var client = new RestClient("https://api.spotify.com/v1/audio-features/");
client.Authenticator = new OAuth2AuthorizationRequestHeaderAuthenticator(accessToken, "Bearer");
string[] Id = (string[])TrackIds.ToArray(typeof(string));
string Ids = String.Join(",", Id);
var request = new RestRequest($"?ids={Ids}", Method.Get);
request.AddHeader("Content-Type", "application/json");
var response = client.GetAsync(request).GetAwaiter().GetResult();
var audio = JsonConvert.DeserializeObject<AudioFeatures>(response.Content);
I am not sure why it doesn't work for multiple id's at once! If it helps the audio variable holds null values if I try multiple Ids, no errors.
Any help would be greately appreciated.
I nee to connect to a mongo and run a commands.
I'm am connecting using the following piece of code. I want to test weather I am connecting by listing the databases.
MongoClient client = new MongoClient("mongodb://127.0.0.1:27017");
client.ListDatabases();
If I debug and click on the second line I cannot see the names of the databases. How can I print the names of the databases to screen to confirm I am connected to mongo.
You need to specify credentials in the Connection String. Couple ways you can do this:
var connectionString = "mongodb://user1:password1#127.0.0.1:27017";
Is the format expected, you will have to supply the username and password yourself, these are just placeholders.
Or you can create a MongoCredentials object and use that instead of a connection string (probably a bit cleaner this way, and allows more configuration if you look deeper into the object documentation)
var credential = MongoCredential.CreateMongoCRCredential("test", "user1", "password1");
var settings = new MongoClientSettings
{
Credentials = new[] { credential }
};
var mongoClient = new MongoClient(settings);
Both of these examples are found on MongoDB's documentation site
Try GetDatabaseNames() method and also assign the result to a variable. So that you can inspect it at breakpoint like
MongoClient client = new MongoClient("mongodb://127.0.0.1:27017/");
var databaseNames = client.GetDatabaseNames();
ListDatabases returns an IAsyncCursor so try the following:
var client = new MongoClient(<CONNECTION STRING>);
var cursor = client.ListDatabases();
cursor.ForEachAsync(db => Console.WriteLine(((BsonString)db["name"]).Value));
I am trying to insert elements into a MongoLab database (Sandbox plan) using C# (by parsing a xml file, but that is not the relevant part).
var connectionString = "mongodb://user:pass#ds011111.mongolab.com:11111/db";
var server = client.GetServer();
var database = server.GetDatabase("mydb");
var elementCollection = database.GetCollection<Entity>("entities");
XmlDocument doc = new XmlDocument();
doc.LoadXml(elementxml);
XmlNodeList elementList = doc.GetElementsByTagName("element");
foreach (XmlNode element in elementList)
{
var t = new Entity();
t.Name = element.FirstChild.InnerText;
elementCollection.Insert(t); // this causes the error below
}
This is the message I get:
WriteConcern detected an error 'not authorized for insert on mydb.entities'. (Response
was { "err" : "not authorized for insert on mydb.entities", "code" : 16544, "n" : 0,
"lastOp" : { "$timestamp" : NumberLong(0) }, "connectionId" : 33932414, "ok" : 1.0 }).
If I run the same code on localhost, everything works as intended
If I insert an element using mongo/shell I get Cannot use commands write mode, degrading to compatability mode, but it works
Does this mean I cannot populate my mongolab database with data (from C#) because I do not have the right permissions as a Sandbox user? If that is the case, what are my options?
The problem seems to be that you're authenticating to the "db" database but trying to use the "mydb" database. Except for specially-privileged/admin users, most users only have access to one database, hence the not authorized error. We run all our databases with authentication on, while the MongoDB defaults, which you're likely using locally, require no authentication; that's why you're not seeing the issue locally.
You should be grabbing the DB to be used from the URI. Here's an example from our Language Center.
// Standard URI format: mongodb://[dbuser:dbpassword#]host:port/dbname
String uri = "mongodb://user:pass#host:port/db";
MongoUrl url = new MongoUrl(uri);
MongoClient client = new MongoClient(url);
MongoServer server = client.GetServer();
MongoDatabase db = server.GetDatabase(url.DatabaseName);
If that doesn't sort you out, try our connectivity troubleshooting guide. In particular, the next thing I'd look at is whether you're using the right credentials (see the section entitled "Check your database credentials").
Finally, please don't hesitate to contact us as support#mongolab.com if you continue to have issues or have any other questions.
I'm struggling with the final part of getting my first bit of code working with the AWS - I have got this far, I attached the web reference in VS and this have this
amazon.AWSECommerceService service = new amazon.AWSECommerceService();
// prepare an ItemSearch request
amazon.ItemSearchRequest request = new amazon.ItemSearchRequest();
request.SearchIndex = "DVD";
request.Title = "scream";
request.ResponseGroup = new string[] { "Small" };
amazon.ItemSearch itemSearch = new amazon.ItemSearch();
itemSearch.AssociateTag = "";
itemSearch.Request = new ItemSearchRequest[] { request };
itemSearch.AWSAccessKeyId = ConfigurationManager.AppSettings["AwsAccessKeyId"];
itemSearch.Request = new ItemSearchRequest[] { request };
ItemSearchResponse response = service.ItemSearch(itemSearch);
// write out the results
foreach (var item in response.Items[0].Item)
{
Response.Write(item.ItemAttributes.Title + "<br>");
}
I get the error
The request must contain the parameter Signature.
I know you have to 'sign' requests now, but can't figure out 'where' I would do this or how? any help greatly appreciated?
You have to add to the SOAP request headers including your Amazon access key ID, a timestamp, and the SHA256 hash of the request operation and the timestamp. To accomplish that, you would need access to the SOAP message just before it is going to be sent out. There's a walkthrough and a sample project I put together at http://flyingpies.wordpress.com/2009/08/01/17/.
For the record:
Another reason to get this error is due to keywords with spaces in it.
Example:
'http://ecs.amazonaws.com/onca/xml?Service=AWSECommerceService&AWSAccessKeyId=xxx&AssociateTag=usernetmax-20&Version=2011-08-01&Operation=ItemSearch&ResponseGroup=Medium,Offers&SearchIndex=All&Keywords=Baby
Stroller&MerchantId=All&Condition=All&Availability=Available&ItemPage=1&Timestamp=2012-05-16T02:17:32Z&Signature=ye5c2jo99cr3%2BPXVkMyXX8vMhTC21UO4XfHpA21%2BUCs%3D'
It should be:
'http://ecs.amazonaws.com/onca/xml?Service=AWSECommerceService&AWSAccessKeyId=xxx&AssociateTag=usernetmax-20&Version=2011-08-01&Operation=ItemSearch&ResponseGroup=Medium,Offers&SearchIndex=All&Keywords=Baby%20Stroller&MerchantId=All&Condition=All&Availability=Available&ItemPage=1&Timestamp=2012-05-16T02:17:32Z&Signature=ye5c2jo99cr3%2BPXVkMyXX8vMhTC21UO4XfHpA21%2BUCs%3D'
PHP solution:
$Keywords = str_replace(' ', '%20', $Keywords);
or
$Keywords = urlencode($Keywords);