Web Service that converts address to lat/Long - vb.net

I was wondering if anyone knows of a good web service that I can supply an address and it returns a Lat/Long in decimal degrees? I have been trying to play with the Google Maps API, but I cannot find the documentation for using a desktop app(Winforms) to return the data. I have used both WebClient and the WebRequest/WebResponse ways without success. The error is '610:Invalid key' though I am staring at the key and just copy/pasted it into the parameters - including making a new one. It seems Google is not an easy route and I would like a diff option if poss. Any ideas would be great. Thanks for looking.

You're looking for Google Geocoding API v3
There is no separate things for Desktop application. So you're looking exactly for this
"https://maps.googleapis.com/maps/api/geocode/xml?address=
your encodedAddress&sensor=false"
Here is a simple example I used in C#:
string address = "your address";
encodedAddress = HttpUtility.UrlEncode(address).Replace("+", "%20");
string googleApiURL = "https://maps.googleapis.com/maps/api/geocode/" + "xml?address=" + encodedAddress + "&sensor=false";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(googleApiURL);
request.Timeout = 10000;
request.Method = "GET";
WebResponse response = request.GetResponse();
if (response != null)
{
//Parse here to to capture the lat and long
}
else
{
//Handle if don't get response
}
For you, it won't be difficult to convert it to VB.NET.
The major part here is how you are going to parse the XML/JSON response, As I already bold faced in URL
Google provide two different response xml or json.
Don't forget to encode the address.
NOTE: Use of the Google Geocoding API is subject to a query limit of 2,500 requests per day.
Hope you got some idea.

Related

Cannot change the parameters in the API endpoint key

I am a new Xamarin developer. I am trying to integrate a data API to my Xamarin forms cross-platform mobile app.
Following is the site that I get my URL endpoint: navigate to the website
Following is the API endpoint I get from the above site: https://api.tidesandcurrents.noaa.gov/api/prod/datagetterdate=latest&station=8518750&product=air_temperature&datum=MTL&time_zone=gmt&units=metric&format=json
The API endpoint URL sends back data when based on the weather station IDparameter in the API endpoint. The problem is that it is hardcoded in the API endpoint itself. Therefore, I must change the whole API endpoint when I need to request data from another weather station ID.
I have no idea how to send the stationID as a variable in the same URL, like in following end point I got from openweather API service:
http://api.openweathermap.org/data/2.5/weatherlat{location.Latitude}&lon{location.Longitude}&appid=d6533ef259a2c612eb50836b198fc366&units=metric
In the above API, I can send the longitude and latitude as parameters via the API key and get relevant information. But in my API key, I cannot see such a way to send a 'StationID' as a parameter.
Can somebody please help me to modify my following code to send the 'stationID' as a variable and get data dynamically based on the station ID please?
Following is my code for getting API data send them to the .xaml front end.
private async void GetTideInfo()
{
var url = $"https://api.tidesandcurrents.noaa.gov/api/prod/datagetter?date=latest&station=8518750&product=air_temperature&datum=MTL&time_zone=gmt&units=metric&format=json";
var result = await ApiCaller.Get(url);
if (result.Successful)
{
var tidalInfo = JsonConvert.DeserializeObject<TidleRoot>(result.Response);
meanTideTxt.Text = tidalInfo.data[0].v + " m";
}
else
{
await DisplayAlert("Tidal data", "No tidal data found", "OK");
}
}
Thanks in advance for everybody who volunteer to solve my problem.
just insert the StationID value into the url
var stationId = 8518750;
var url = $"https://api.tidesandcurrents.noaa.gov/api/prod/datagetterdate=latest&station={stationId}&product=air_temperature&datum=MTL&time_zone=gmt&units=metric&format=json";

How to acquire the response body from Apache HttpClient5's HttpResponse?

Getting the status code and response body was this easy in version 4:
StringEntity entity = new StringEntity(jsonData.toString());
HttpResponse r = org.apache.http.client.fluent.Request.Post(uri)
.connectTimeout(10*1000)
.socketTimeout(10*1000)
.addHeader("Content-Type", "application/json; charset=utf-8")
.body(entity)
.execute()
.returnResponse();
int status = r.getStatusLine().getStatusCode();
String body = EntityUtils.toString(r.getEntity(), "UTF-8");
return new CoolResponse(status, body);
But now in httpclient5 for some reason it isn't possible to get anything relating to the response body from an HttpResponse. Very confused by this. If I follow example 3 in their quickstart (https://hc.apache.org/httpcomponents-client-5.0.x/quickstart.html) it proposes I create an CloseableHttpClient, an HttpGet and a CloseableHttpResponse, but none of those allow you to set a connection timeout. Trying to find the best of both worlds but the options seem kind of scrambled here.
It's not mentioned in the quickstart, but in the fluent API you can follow up execute() with handleResponse() and pass it a lambda.
I wound up finding a much better article than the quickstart here:
https://ok2c.github.io/httpclient-migration-guide/migration-to-classic.html
Edit: that link is down, there is now an equivalent guide on apache's site
https://hc.apache.org/httpcomponents-client-5.2.x/migration-guide/migration-to-classic.html

Soundcloud API /stream endpoint giving 401 error

I'm trying to write a react native app which will stream some tracks from Soundcloud. As a test, I've been playing with the API using python, and I'm able to make requests to resolve the url, pull the playlists/tracks, and everything else I need.
With that said, when making a request to the stream_url of any given track, I get a 401 error.
The current url in question is:
https://api.soundcloud.com/tracks/699691660/stream?client_id=PGBAyVqBYXvDBjeaz3kSsHAMnr1fndq1
I've tried it without the ?client_id..., I have tried replacing the ? with &, I've tried getting another client_id, I've tried it with allow_redirects as both true and false, but nothing seems to work. Any help would be greatly appreciated.
The streamable property of every track is True, so it shouldn't be a permissions issue.
Edit:
After doing a bit of research, I've found a semi-successful workaround. The /stream endpoint of the API is still not working, but if you change your destination endpoint to http://feeds.soundcloud.com/users/soundcloud:users:/sounds.rss, it'll give you an RSS feed that's (mostly) the same as what you'd get by using the tracks or playlists API endpoint.
The link contained therein can be streamed.
Okay, I think I have found a generalized solution that will work for most people. I wish it were easier, but it's the simplest thing I've found yet.
Use API to pull tracks from user. You can use linked_partitioning and the next_href property to gather everything because there's a maximum limit of 200 tracks per call.
Using the data pulled down in the JSON, you can use the permalink_url key to get the same thing you would type into the browser.
Make a request to the permalink_url and access the HTML. You'll need to do some parsing, but the url you'll want will be something to the effect of:
"https://api-v2.soundcloud.com/media/soundcloud:tracks:488625309/c0d9b93d-4a34-4ccf-8e16-7a87cfaa9f79/stream/progressive"
You could probably use a regex to parse this out simply.
Make a request to this url adding ?client_id=... and it'll give you YET ANOTHER url in its return json.
Using the url returned from the previous step, you can link directly to that in the browser, and it'll take you to your track content. I checked on VLC by inputting the link and it streams correctly.
Hopefully this helps some of you out with your developing.
Since I have the same problem, the answer from #Default motivated me to look for a solution. But I did not understand the workaround with the permalink_url in the steps 2 and 3. The easier solution could be:
Fetch for example user track likes using api-v2 endpoint like this:
https://api-v2.soundcloud.com/users/<user_id>/track_likes?client_id=<client_id>
In the response we can finde the needed URL like mentioned from #Default in his answer:
collection: [
{
track: {
media: {
transcodings:[
...
{
url: "https://api-v2.soundcloud.com/media/soundcloud:tracks:713339251/0ab1d60e-e417-4918-b10f-81d572b862dd/stream/progressive"
...
}
]
}
}
...
]
Make request to this URL with client_id as a query param and you get another URL with that you can stream/download the track
Note that the api-v2 is still not public and the request from your client probably will be blocked by CORS.
As mentioned by #user208685 the solution can be a bit simpler by using the SoundCloud API v2:
Obtain the track ID (e.g. using the public API at https://developers.soundcloud.com/docs)
Get JSON from https://api-v2.soundcloud.com/tracks/TRACK_ID?client_id=CLIENT_ID
From JSON parse MP3 progressive stream URL
From stream URL get MP3 file URL
Play media from MP3 file URL
Note: This link is only valid for a limited amount of time and can be regenerated by repeating steps 3. to 5.
Example in node (with node-fetch):
const clientId = 'YOUR_CLIENT_ID';
(async () => {
let response = await fetch(`https://api.soundcloud.com/resolve?url=https://soundcloud.com/d-o-lestrade/gabriel-ananda-maceo-plex-solitary-daze-original-mix&client_id=${clientId}`);
const track = await response.json();
const trackId = track.id;
response = await fetch(`https://api-v2.soundcloud.com/tracks/${trackId}?client_id=${clientId}`);
const trackV2 = await response.json();
const streamUrl = trackV2.media.transcodings.filter(
transcoding => transcoding.format.protocol === 'progressive'
)[0].url;
response = await fetch(`${streamUrl}?client_id=${clientId}`);
const stream = await response.json();
const mp3Url = stream.url;
console.log(mp3Url);
})();
For a similar solution in Python, check this GitHub issue: https://github.com/soundcloud/soundcloud-python/issues/87

Append URL Query Strings to request

I'm trying to send a POST request and format the query string in a specific format. Order doesn't matter aside from the first parameter, but I haven't been successful.
What I need:
localhost/someapp/api/dosomething/5335?save=false&userid=66462
What some of my attempts have spit out:
http://localhost/someapp/api/dosomething/?Id=29455&save=false&userId=797979
http://localhost/someapp/api/dosomething/?save=false&userId=797979
How I formatted the request:
request.AddQueryParameter("Id", "29455");
request.AddQueryParameter("save", "false");
request.AddQueryParameter("user", "4563533245");
If I try AddParameterfor Id it doesn't get appended on the query string (I'm thinking because it's a POST and not a GET), so that won't work. The API isn't expecting a form, it's expecting :
(string id, List<Dictionary<string,string>>)
I could use a StringBuilder, but that feels wrong. I'm not sure if UrlSegment is the best way to go either, since I would basically be hacking the query string. Is there a way to format my request in the format I need using RestSharp's API?
What I ended up using is UrlSegment and then kept the .AddQueryParameter methods, so the final code block looks like :
var url = new RestClient(localhost/someapp/api/dosomething/{id});
var request = new RestRequest(Method.POST);
request.AddParameter("Id", "5335", ParameterType.UrlSegment);
request.AddQueryParameter("save", "true");
request.AddQueryParameter("UserId", "5355234");
Which produced the URI I needed.
The easiest coding process for using RestSharp or any other API client library would be to use Postman to generate if you are unsure of how to code it. Download Postman, do a new request, enter the URL string to send to the API, click on Code, select C# (RestSharp) from the dropdown. Here is the code it generated.
var client = new RestClient("http://localhost/someapp/api/dosomething /5335?save=false&userid=66462");
var request = new RestRequest(Method.POST);
request.AddHeader("Postman-Token", "bd05aa45-f1b9-4665-a3e7-888ad16f2800");
request.AddHeader("cache-control", "no-cache");
IRestResponse response = client.Execute(request);

I am trying to use Yodlee/executeUserSearchRequest as a RESTful request and need an answer on how to call

I am working with the Yodlee services in c# and using the RESTful api. So far I have successfully connected and logged in with my CobrandSession and UserSessionToken in the development environment. I used the sample apps provided in c# and with some advice from shreyans i got an app working. What I got working was
1) Get YodleeAuthentication
2) Get UserAuthentication
3) Get ItemSummaries
I am now trying to get the full transaction details for each of the Items (i.e. collections of accounts that are an Item)
reading the Docs here https://developer.yodlee.com/Indy_FinApp/Aggregation_Services_Guide/REST_API_Reference/executeUserSearchRequest it states that I need to call executeUserSearchRequest and then paginate through the results using the getUserTransactions. So I am stuck at this point. I dont really want a search which has parameters I just want ALL transactions for this account that I can see.
However, I am using the variables as defined in that page :-
var request = new RestRequest("/jsonsdk/TransactionSearchService/executeUserSearchRequest", Method.POST);
request.AddParameter("cobSessionToken", param.CobSessionToken);
request.AddParameter("userSessionToken", param.UserSessionToken);
request.AddParameter("transactionSearchRequest.containerType", param.ContainerType);
request.AddParameter("transactionSearchRequest.higherFetchLimit", param.HigherFetchLimit);
request.AddParameter("transactionSearchRequest.lowerFetchLimit", param.LowerFetchLimit);
request.AddParameter("transactionSearchRequest.resultRange.endNumber", param.EndNumber);
request.AddParameter("transactionSearchRequest.resultRange.startNumber", param.StartNumber);
request.AddParameter("transactionSearchRequest.searchFilter.currencyCode", param.CurrencyCode);
request.AddParameter("transactionSearchRequest.searchFilter.postDateRange.fromDate", param.FromDate);
request.AddParameter("transactionSearchRequest.searchFilter.postDateRange.toDate", param.ToDate);
request.AddParameter("transactionSearchRequest.searchFilter.transactionSplitType.splitType", param.SplitType);
request.AddParameter("transactionSearchRequest.ignoreUserInput", param.IgnoreUserInput);
request.AddParameter("transactionSearchRequest.searchFilter.itemAcctId", param.ItemAcctId);
var response = RestClientUtil.GetBase().Execute(request);
var content = response.Content;
return new YodleeServiceResultDto(content);
As per the response from shreyans in this posting Getting Error "Any one of [**] of transactionSearchFilter cannot be NULL OR Invalid Values I am not putting in the ClientId and the ClientName
The documentation doesn't specify the format of the dates but the example seems to tell me that its american date format. And specifies a parameter saying IgnoreUserinput, but doesnt have a parameter for user input so this is confusing
When I make a call using this format I get an error response
var getSearchResult = yodleeExecuteUserSearchRequest.Go(yodleeExecuteUserSearchRequestDto);
getSearchResult.Result="
{"errorOccured":"true","exceptionType":"Exception Occured","refrenceCode":"_60ecb1d7-a4c4-4914-b3cd-49182518ca5d"}"
But I get no error message in this and I have no idea what I have done wrong or where to look up this error, can somebody who has used Yodlee REST Api point me in the right direction as I need to get this researched quickly....
thanks your your help, advice, corrections and pointers....
Here is the list of parameters which you can try
1) For a specific ItemAccountId all transactions
transactionSearchRequest.containerType=all
transactionSearchRequest.higherFetchLimit=500
transactionSearchRequest.lowerFetchLimit=1
transactionSearchRequest.resultRange.startNumber=1
transactionSearchRequest.resultRange.endNumber=500
transactionSearchRequest.searchClients.clientId=1
transactionSearchRequest.searchClients.clientName=DataSearchService
transactionSearchRequest.searchFilter.currencyCode=USD
transactionSearchRequest.searchClients=DEFAULT_SERVICE_CLIENT
transactionSearchRequest.ignoreUserInput=true
transactionSearchRequest.ignoreManualTransactions=false
transactionSearchRequest.searchFilter.transactionSplitType=ALL_TRANSACTION
transactionSearchRequest.searchFilter.itemAccountId.identifier=10000353
2) For a Specific account (itemAccountId) with start and end dates
transactionSearchRequest.containerType=all
transactionSearchRequest.higherFetchLimit=500
transactionSearchRequest.lowerFetchLimit=1
transactionSearchRequest.resultRange.startNumber=1
transactionSearchRequest.resultRange.endNumber=500
transactionSearchRequest.searchClients.clientId=1
transactionSearchRequest.searchClients.clientName=DataSearchService
transactionSearchRequest.searchFilter.currencyCode=USD
transactionSearchRequest.searchClients=DEFAULT_SERVICE_CLIENT
transactionSearchRequest.ignoreUserInput=true
transactionSearchRequest.ignoreManualTransactions=false
transactionSearchRequest.searchFilter.transactionSplitType=ALL_TRANSACTION
transactionSearchRequest.searchFilter.itemAccountId.identifier=10000353
transactionSearchRequest.searchFilter.postDateRange.fromDate=08-01-2013
transactionSearchRequest.searchFilter.postDateRange.toDate=10-31-2013