I derived/adapted the following code from Adam Freeman's book "Metro Revealed: Building Windows 8 apps with XAML and C#" to get the Address when the Coordinates are known:
public static async Task<string> GetAddressForCoordinates(double latitude, double longitude)
{
HttpClient httpClient = new HttpClient {BaseAddress = new Uri("http://nominatim.openstreetmap.org")};
HttpResponseMessage httpResult = await httpClient.GetAsync(
String.Format("reverse?format=json&lat={0}&lon={1}", latitude, longitude));
JsonObject jsonObject = JsonObject.Parse(await httpResult.Content.ReadAsStringAsync());
return jsonObject.GetNamedObject("address").GetNamedString("road");
}
How can I get the opposite (the Coordinates if the Address is known)?
UPDATE
I'm adding a bounty to this; what I've got already (shown above) is the reverse geocoding (getting the address for the coordinates); what I need is geocoding (getting the coordinates for the address).
Based on my reverse geocoding code above, I'm guessing it might be something like this:
public static async Task<string> GetCoordinatesForAddress(string address)
{
HttpClient httpClient = new HttpClient {BaseAddress = new Uri("http://nominatim.openstreetmap.org")};
HttpResponseMessage httpResult = await httpClient.GetAsync(
String.Format("format=json&address={0}", address));
JsonObject jsonObject = JsonObject.Parse(await httpResult.Content.ReadAsStringAsync());
return jsonObject.GetNamedObject("address").GetNamedString("lat"); // <-- what about "lon"?
}
...but I don't know how to combine the two coordinate (longitude and latitude) values (assuming this is correct, or close to being correct). Can anybody verify this, clean it up, or provide a better example (either using nominatim or otherwise)?
UPDATE 2
To answer Peter Ritchie's question/comment below:
In the original (reverse geocoding code), I've got:
return jsonObject.GetNamedObject("address").GetNamedString("road");
It simply returns the road; so something like "157 Riverside Avenue" I assume.
But for geocoding (needing two values, a longitude and a latitude), I've got this pseudocode:
return jsonObject.GetNamedObject("address").GetNamedString("lat"); // <-- what about "lon"?
So I don't know if I need to change the return value from Task<string> to Task<List and call (verbose pseudocode) [Note: I'm having a hard time escaping the angle brackets for Task with a List of string]:
var latitude jsonObject.GetNamedObject("address").GetNamedString("lat");
var longitude jsonObject.GetNamedObject("address").GetNamedString("lat");
List<string> listCoordinates = new List<string>();
listCoordinates.Add(latitude);
listCoordinates.Add(longitude);
return listCoordinates;
...or like so:
string latitude jsonObject.GetNamedObject("address").GetNamedString("lat");
string longtude jsonObject.GetNamedObject("address").GetNamedString("long");
return string.Format("{0};{1}", latitude, longitude);
...or ???
UPDATE 3
In response to the proffered Json code for geocoding:
Based on the original reverse geocode code, shouldn't the call be more like this:
HttpClient httpClient = new HttpClient { BaseAddress = new Uri("http://nominatim.openstreetmap.org/") };
var httpResult = await httpClient.GetAsync(
String.Format("search?format=json&addressdetails={0}", address);
...but at any rate:
The JArray type is not recognized, though JsonArray is.
The JValue type is not recognized, though JsonValue is.
The JsonConverter type is not recognized; perhaps part of Json.Net?
The closest I can come to getting the proferred code to compile is:
var result = await httpResult.Content.ReadAsStringAsync();
var r = (JsonArray)JsonConverter.DeserializeObject(result);//<-- JsonConvert[er] not recognized; part of Json.NET?
var latString = ((JsonValue)r[0]["lat"]).ValueType as string;
var longString = ((JsonValue)r[0]["lon"]).ValueType as string;
...but even with this (close but no Bob Seger), JsonConvert as well as JsonConverter are not recognized.
UPDATE 4
After slogging more concertedly through the documentation at http://wiki.openstreetmap.org/wiki/Nominatim#Search, I think my original (reverse geocode) method might be better as:
public static async Task`<string`> GetAddressForCoordinates(double latitude, double longitude)
{
HttpClient httpClient = new HttpClient {BaseAddress = new Uri("http://nominatim.openstreetmap.org/")};
HttpResponseMessage httpResult = await httpClient.GetAsync(
String.Format("reverse?format=json&lat={0}&lon={1}", latitude, longitude));
JsonObject jsonObject = JsonObject.Parse(await httpResult.Content.ReadAsStringAsync());
string house = jsonObject.GetNamedObject("addressparts").GetNamedString("house");
string road = jsonObject.GetNamedObject("addressparts").GetNamedString("road");
string city = jsonObject.GetNamedObject("addressparts").GetNamedString("city");
string state = jsonObject.GetNamedObject("addressparts").GetNamedString("state");
string postcode = jsonObject.GetNamedObject("addressparts").GetNamedString("postcode");
string country = jsonObject.GetNamedObject("addressparts").GetNamedString("country");
return string.Format("{0} {1}, {2}, {3} {4} ({5})", house, road, city, state, postcode, country);
}
This would return, for the corresponding coordinate args passed in, something like: "157 Riverside Avenue, Champaign, IL 55555 (USA)"
What I find odd about the documentation is there is no "state" element among the address parts; if that is really true, and not just a documentation oversight, my code above would fail on the call to GetNamedString("state").
I'm still not sure what the right syntax, etc., should be for the opposite (geocode) method, getting coordinates back after passing in an address.
UPDATE 5
Okay, I downloaded Json.NET and got it compiling. I haven't tested yet, but I've marked Peter Ritchie's as THE (50-point) answer.
This is the code I'm using:
public static async Task<string> GetCoordinatesForAddress(string address)
{
HttpClient httpClient = new HttpClient { BaseAddress = new Uri("http://nominatim.openstreetmap.org/") };
HttpResponseMessage httpResult = await httpClient.GetAsync(
String.Format("search?q={0}&format=json&addressdetails=1", Pluggify(address))); // In my Pluggify() method, I replace spaces with + and then lowercase it all
var result = await httpResult.Content.ReadAsStringAsync();
var r = (JArray)JsonConvert.DeserializeObject(result);
var latString = ((JValue)r[0]["lat"]).Value as string;
var longString = ((JValue)r[0]["lon"]).Value as string;
return string.Format("{0};{1}", latString, longString);
}
Also:
A funny thing happened on the way back to this forum: while installing Json.NET via NuGet, I also saw ".NET's fastest JSON Serializer by ServiceStack" which claims to be 3X faster than Json.NET. FIWW, it has been updated more recently than Json.NET. Thoughts/reaction?
UPDATE 6
I have this code to implement this (app id and code have been changed to protect the semi-innocent
(me)):
// If address has not been explicitly entered, try to suss it out:
address = textBoxAddress1.Text.Trim();
lat = textBoxLatitude1.Text.Trim();
lng = textBoxLongitude1.Text.Trim();
if (string.IsNullOrWhiteSpace(address))
{
address = await SOs_Classes.SOs_Utils.GetAddressForCoordinates(lat, lng);
}
. . .
public async static Task<string> GetAddressForCoordinates(string latitude, string longitude)
{
string currentgeoLoc = string.Format("{0},{1}", latitude, longitude);
string queryString = string.Empty;
string nokiaAppID = "j;dsfj;fasdkdf";
object nokiaAppCode = "-14-14-1-7-47-178-78-4";
var hereNetUrl = string.Format(
"http://demo.places.nlp.nokia.com/places/v1/discover/search?at={0}&q={1}&app_id={2}
&app_code={3}&accept=application/json",
currentgeoLoc, queryString, nokiaAppID, nokiaAppCode);
// get data from HERE.net REST API
var httpClient = new HttpClient();
var hereNetResponse = await httpClient.GetStringAsync(hereNetUrl);
// deseralize JSON from Here.net
using (var tr = new StringReader(hereNetResponse))
using (var jr = new JsonTextReader(tr))
{
var rootObjectResponse = new JsonSerializer
().Deserialize<JsonDOTNetHelperClasses.RootObject>(jr);
var firstplace = rootObjectResponse.results.items.First();
return HtmlUtilities.ConvertToText(firstplace.vicinity);
// NOTE: There is also a title (such as "Donut Shop", "Fire stations", etc.?) and type (such as "residence" or "business", etc.?)
}
}
...but on this line in GetAddressForCoordinates():
var firstplace = rootObjectResponse.results.items.First();
...I get this err msg: "*System.InvalidOperationException was unhandled by user code
HResult=-2146233079
Message=Sequence contains no elements
Source=System.Core
StackTrace:
at System.Linq.Enumerable.First[TSource](IEnumerable`1 source)
at SpaceOverlays.SOs_Classes.SOs_Utils.d__12.MoveNext() in c:...*"
The value of hereNetResponse is:
{"results":{"items":[]},"search":{"context":{"location":{"position":[38.804967,-90.113183],"address":
{"postalCode":"62048","city":"Hartford","stateCode":"IL","county":"Madison","countryCode":"USA","country":"
USA","text":"Hartford IL 62048
USA"}},"type":"urn:nlp-types:place","href":"http://demo.places.nlp.nokia.com/places/v1/places/loc-
dmVyc2lvbj0xO3RpdGxlPUhhcnRmb3JkO2xhdD0zOC44MDQ5Njc7bG9uPS05MC4xMTMxODM7Y2l0eT1IY
XJ0Zm9yZDtwb3N0YWxDb2RlPTYyMDQ4O2NvdW50cnk9VVNBO3N0YXRlQ29kZT1JTDtjb3VudHk9TWFka
XNvbjtjYXRlZ29yeUlkPWNpdHktdG93bi12aWxsYWdl;context=Zmxvdy1pZD02YmUzZDM4Yi0wNGVhLTUyM
jgtOWZmNy1kNWNkZGM0ODI5OThfMTM1NzQyMDI1NTg1M18wXzE2MA?
app_id=F6zpNc3TjnkiCLwl_Xmh&app_code=QoAM_5BaVDZvkE2jRvc0mw"}}}
...so it would appear that there is valid info inside there, such as should return "Hartford, IL"
And at any rate, a blank return value shouldn't throw an exception, I would think...
What you're asking about is simply "geocoding". If you want to use Nominatim specifically, they call this "Search". This is, to a certain extent, address validation; but part of the "validation" is including coordinates (bounding box, lat/long, etc.; depending on what is searched for and what the type of result). There's lots of details about the results, too much to simply post here; but this detail can be found here: http://wiki.openstreetmap.org/wiki/Nominatim#Search (including examles).
You'll have to parse the results (XML, JSON, or HTML) to get the fields you're interested it.
Update 1:
As to what to do with the actual values: it depends. If you want to view the coordinates in a form, you can simply put the lat and long strings into individual controls. If you want to put it in a single control, could use string.Format("{0}, {1}", latString, longString). If you want to use the coords with various methods/types for a Windows Store app, you might need to use the Microsoft.Maps.MapControl.Location class. For example:
Double latNumber;
Double longNumber;
if(false == Double.TryParse(latString, out latNumber)) throw new InvalidOperationException();
if(false == Double.TryParse(longString, out longNumber)) throw new InvalidOperationException();
var location = new Location(latNumber, longNumber);
The above assumes you've extracted the lat and long from the response and put them in latString, longString respectively.
Some interfaces may require lat/long as separate double values, in which case just use latNumber and longNumber above.
Over and above that, it really depends specifically on the interfaces you want to use. But, the above should give you enough to use most interfaces.
Update 2:
If the question isn't "how to get coordinates" but "how to parse json objects" then I'd recommend using JSon.Net to get at the lat/long strings in the json result. For example:
var httpClient = new HttpClient();
var httpResult = await httpClient.GetAsync(
"http://nominatim.openstreetmap.org/search?q=135+pilkington+avenue,+birmingham&format=json&polygon=1&addressdetails=1");
var result = await httpResult.Content.ReadAsStringAsync();
var r = (JArray) JsonConvert.DeserializeObject(result);
var latString = ((JValue) r[0]["lat"]).Value as string;
var longString = ((JValue)r[0]["lon"]).Value as string;
...see above w.r.t. what to do with latString and longString
If your looking for google maps geocoding, you can find it here:
https://developers.google.com/maps/documentation/geocoding/
and an example use is:
http://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=false
convert to Json, and take the Geometry object.
in regards to how to, basically, return two values from a function, in C# you have 4 options:
convert both objects into a single object of the same type (in case of strings, you just separate them by a delimiter, like you did) and then parse both out afterwards.
return a list - in this case a Task (or array).
create a new class/object that contains both (in this case you can call it Geometry for instance).
return one or both of the objects by requiring them to be passed as a reference to the function. In an async function, this is bound to be very tricky, but depending on who calls the function and who processes the result, it might be possible.
Microsoft Mappoint also contaisn an API you could make use of. It is able to return geocoordinates.
Related
I am coming to a problem where I have a guid style schema in my firebase database, which I want to display a text that is DisplayText, but for some reason my code is not working. I am using a FirebaseDatabase.Net Wrapper. How can I map it in order to read from the database properly using a guid way schema? thanks for the help.
Code:
private async Task ShowQuestion()
{
var firebase = new
FirebaseClient("https://PROJECT_URL.firebaseio.com/");
var dinos = await firebase
.Child("Questions")
.OrderByKey()
.StartAt("DisplayText")
.LimitToFirst(1)
.OnceAsync<GameController>();
foreach (var dino in dinos)
{
Console.WriteLine(dinos);
}
I tried doing:
string page = "https://PROJECT_URL.firebaseio.com/Questions/DisplayText.json?orderBy"DisplayText"&limitToFirst=1";
using (HttpClient client = new HttpClient())
using (HttpResponseMessage response = await client.GetAsync(page))
using (HttpContent content = response.Content)
{
// Reading the string.
string result = await content.ReadAsStringAsync();
Console.WriteLine(result);
// Getting a reference to the text component.
questionDisplayText = GetComponent<Text>();
questionDisplayText.text = result.ToString();
questionDisplayText.text = result.Trim(new char[] {'"'});
}
Firebase queries take a two-step approach:
You order the child nodes on their key, their value, or the value of a property.
You then filter on values of the thing you ordered on.
Since you order by key, the filtering operations like StartAt() compare the key to the value you passed. And since there is no key DisplayText, there are no results.
If you want to read the first question, you shouldn't use a startAt().
FirebaseClient("https://PROJECT_URL.firebaseio.com/");
var dinos = await firebase
.Child("Questions")
.OrderByKey()
.LimitToFirst(1)
If you want to return the results ordered by the value of their DisplayText property, it'd be something like this:
FirebaseClient("https://PROJECT_URL.firebaseio.com/");
var dinos = await firebase
.Child("Questions")
.OrderByChild("DisplayText")
.LimitToFirst(1)
Since you indicated that you want to use the REST API, here's an example of how to do that:
https://stackoverflow.firebaseio.com/59384124.json?orderBy="DisplayText"&startAt="How"
If you want to embed this string in your code, you have a few options. The main ones:
string page = "https://PROJECT_URL.firebaseio.com/Questions/DisplayText.json?orderBy=\"DisplayText\"&startAt=\"How\"&limitToFirst=1";
Or
string page = #"https://PROJECT_URL.firebaseio.com/Questions/DisplayText.json?orderBy=""DisplayText""&startAt=""How""&limitToFirst=1";
And don't forget: in order to be able to filter on the server, you'll need to define an index in your security rules. In my case I did so with:
"59384124": { ".indexOn": "DisplayText" },
Also see:
The documentation for the Firebase REST API
This blog post on embedding quotes in C# strings
I am new to Google APIs. I want to know how to call Google Dialogflow API in C# to get intent form the input text. But I can't find any example to call Dialogflow using C#.
Please provide some example to call Dialogflow from C#.
If I understand your question correctly you want to call the DialogFlow API from within a C# application (rather than writing fulfillment endpoint(s) that are called from DialogFlow. If that's the case here's a sample for making that call:
using Google.Cloud.Dialogflow.V2;
...
...
var query = new QueryInput
{
Text = new TextInput
{
Text = "Something you want to ask a DF agent",
LanguageCode = "en-us"
}
};
var sessionId = "SomeUniqueId";
var agent = "MyAgentName";
var creds = GoogleCredential.FromJson("{ json google credentials file)");
var channel = new Grpc.Core.Channel(SessionsClient.DefaultEndpoint.Host,
creds.ToChannelCredentials());
var client = SessionsClient.Create(channel);
var dialogFlow = client.DetectIntent(
new SessionName(agent, sessionId),
query
);
channel.ShutdownAsync();
In an earlier version of the DialogFlowAPI I was running into file locking issues when trying to re-deploy a web api project which the channel.ShutDownAsync() seemed to solve. I think this has been fixed in a recent release.
This is the simplest version of a DF request I've used. There is a more complicated version that passes in an input context in this post:
Making DialogFlow v2 DetectIntent Calls w/ C# (including input context)
(Nitpicking: I assume you know DialogFlow will call your code as specified/registered in the action at DialogFlow? So your code can only respond to DialogFlow, and not call it.)
Short answer/redirect:
Don't use Google.Apis.Dialogflow.v2 (with GoogleCloudDialogflowV2WebhookRequest and GoogleCloudDialogflowV2WebhookResponse) but use Google.Cloud.Dialogflow.v2 (with WebhookRequest and WebhookResponse) - see this eTag-error. I will also mention some other alternatives underneath.
Google.Cloud.Dialogflow.v2
Using Google.Cloud.Dialogflow.v2 NuGet (Edit: FWIW: this code was written for the beta-preview):
[HttpPost]
public dynamic PostWithCloudResponse([FromBody] WebhookRequest dialogflowRequest)
{
var intentName = dialogflowRequest.QueryResult.Intent.DisplayName;
var actualQuestion = dialogflowRequest.QueryResult.QueryText;
var testAnswer = $"Dialogflow Request for intent '{intentName}' and question '{actualQuestion}'";
var dialogflowResponse = new WebhookResponse
{
FulfillmentText = testAnswer,
FulfillmentMessages =
{ new Intent.Types.Message
{ SimpleResponses = new Intent.Types.Message.Types.SimpleResponses
{ SimpleResponses_ =
{ new Intent.Types.Message.Types.SimpleResponse
{
DisplayText = testAnswer,
TextToSpeech = testAnswer,
//Ssml = $"<speak>{testAnswer}</speak>"
}
}
}
}
}
};
var jsonResponse = dialogflowResponse.ToString();
return new ContentResult { Content = jsonResponse, ContentType = "application/json" }; ;
}
Edit: It turns out that the model binding may not bind all properties from the 'ProtoBuf-json' correctly (e.g. WebhookRequest.outputContexts[N].parameters),
so one should probably use the Google.Protobuf.JsonParser (e.g. see this documentation).
This parser may trip over unknown fields, so one probably also wants to ignore that. So now I use this code (I may one day make the generic method more generic and thus useful, by making HttpContext.Request.InputStream a parameter):
public ActionResult PostWithCloudResponse()
{
var dialogflowRequest = ParseProtobufRequest<WebhookRequest>();
...
var jsonResponse = dialogflowResponse.ToString();
return new ContentResult { Content = jsonResponse, ContentType = "application/json" }; ;
}
private T ParseProtobufRequest<T>() where T : Google.Protobuf.IMessage, new()
{
// parse ProtoBuf (not 'normal' json) with unknown fields, else it may not bind ProtoBuf correctly
// https://github.com/googleapis/google-cloud-dotnet/issues/2425 "ask the Protobuf code to parse the result"
string requestBody;
using (var reader = new StreamReader(HttpContext.Request.InputStream))
{
requestBody = reader.ReadToEnd();
}
var parser = new Google.Protobuf.JsonParser(JsonParser.Settings.Default.WithIgnoreUnknownFields(true));
var typedRequest = parser.Parse<T>(requestBody);
return typedRequest;
}
BTW: This 'ProtoBuf-json' is also the reason to use WebhookResponse.ToString() which in turn uses Google.Protobuf.JsonFormatter.ToDiagnosticString.
Microsoft's BotBuilder
Microsoft's BotBuilder packages and Visual Studio template.
I havent't used it yet, but expect approximately the same code?
Hand written proprietary code
A simple example of incoming request code (called an NLU-Response by Google) is provided by Madoka Chiyoda (Chomado) at Github. The incoming call is simply parsed to her DialogFlowResponseModel:
public static async Task<HttpResponseMessage> Run([...]HttpRequestMessage req, [...]CloudBlockBlob mp3Out, TraceWriter log)
...
var data = await req.Content.ReadAsAsync<Models.DialogFlowResponseModel>();
Gactions
If you plan to work without DialogFlow later on, please note that the interface for Gactions differs significantly from the interface with DialogFlow.
The json-parameters and return-values have some overlap, but nothing gaining you any programming time (probably loosing some time by starting 'over').
However, starting with DialogFlow may gain you some quick dialog-experience (e.g. question & answer design/prototyping).
And the DialogFlow-API does have a NuGet package, where the Gactions-interface does not have a NuGet-package just yet.
I'm trying to get latitude and longitude from address text using google map api.
Here is code, that I have tried.
First:
var locationService = new GoogleLocationService();
var point = locationService.GetLatLongFromAddress(business.Address2);
var latitude = point.Latitude;
var longitude = point.Longitude;
Second:
IGeocoder geocoder = new GoogleGeocoder() { };
Address[] addresses = geocoder.Geocode(business.Address2).ToArray();
foreach (Address adrs in addresses)
{
var test = adrs.Coordinates;
}
Third:
public RootObject GetLatLongByAddress(string address)
{
var root = new RootObject();
var url =string.Format(
"http://maps.googleapis.com/maps/api/geocode/json?address={0}&sensor=true_or_false", address);
var req = (HttpWebRequest)WebRequest.Create(url);
var res = (HttpWebResponse)req.GetResponse();
using (var streamreader = new StreamReader(res.GetResponseStream()))
{
var result = streamreader.ReadToEnd();
if (!string.IsNullOrWhiteSpace(result))
{
root = JsonConvert.DeserializeObject<RootObject>(result);
}
}
return root;
}
And my address string is "Ground Floor, Nishika Avenue, Swastik Char Rasta, Navrangpura, Opposite Narnarayan Complex, Ahmadabad"
I've tried with all though, but it not gives me latitude and longitude anyway.
When I remove first part of my address string (i.e Navrangpura, Opposite Narnarayan Complex, Ahmadabad) and try, it's give me lat/long.
But when I search with full address on Google Map it shows the result.
Why this is so? Am i missing something?
The address 'Ground Floor, Nishika Avenue, Swastik Char Rasta, Navrangpura, Opposite Narnarayan Complex, Ahmadabad' cannot be found at maps.google.com as well
The API cannot find something that doesn't exist. You should add this place via maps.google.com or format your address string better following the
https://developers.google.com/maps/faq#geocoder_queryformat
Hope it helps!
Using this query api how to get the nearby places in to our mapcontrol in windows phone 8.1. When I placed the code from the above link it shows the 404 error (i.e resource not found).
I got bing maps key. But how to place the access id. How the data source are named. Please help me.
string BingMapsKey = "MY_BING_MAPS_KEY";
string DataSourceID = "20181f26d9e94c81acdf9496133d4f23";
string dataSourceName = "petrolbunk";
string dataEntityName = "petrolbunk";
string accessId = DataSourceID;
string bingMapsKey = BingMapsKey;
double SearchLatitude = 47.63674;
double SearchLongitude = -122.30413;
double Radius = 3;
string requestUrl1 = string.Format("http://spatial.virtualearth.net/REST/v1/data/{0}/{1}/{2}" + "?spatialFilter=nearby({3},{4},{5})&key={6}", accessId, dataSourceName,
dataEntityName, SearchLatitude, SearchLongitude, Radius, bingMapsKey);
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(requestUrl1);
if (response.IsSuccessStatusCode)
{
var data = response.Content.ReadAsStringAsync();
Is the above url layout is correct. How to display them in our map control.
The following code listing uses NAVTEQEUDataSource for searching nearby. You can take it for example
internal class NAVTEQEUDataSource : INAVTEQEUDataSource
{
public async Task<IList<Geopoint>> SearchNearBy(double latitude, double longitude, double radius, int entityTypeId, int maxResult, string bingMapKey)
{
const string spatialBaseUrl = "http://spatial.virtualearth.net/REST/v1/data/";
string url =
"c2ae584bbccc4916a0acf75d1e6947b4/NavteqEU/NavteqPOIs?spatialFilter=nearby({0},{1},{2})&$filter=EntityTypeID%20eq%20'{3}'&$select=EntityID,DisplayName,Latitude,Longitude,__Distance&$top={4}&key={5}";
HttpClient httpClient = new HttpClient { BaseAddress = new Uri(spatialBaseUrl) };
url = string.Format(url, latitude, longitude, radius, entityTypeId, maxResult, bingMapKey);
string response = await httpClient.GetStringAsync(url);
XmlUtil xmlUtil = new XmlUtil(response);
IList<XElement> properties = xmlUtil.GetElements("entry").ToList();
IList<Geopoint> result = new List<Geopoint>();
foreach (var property in properties)
{
BasicGeoposition basicGeoposition = new BasicGeoposition();
double temp;
if (double.TryParse(xmlUtil.GetRelativeElement(property, "content.properties.Latitude").Value, out temp))
basicGeoposition.Latitude = temp;
if (double.TryParse(xmlUtil.GetRelativeElement(property, "content.properties.Longitude").Value, out temp))
basicGeoposition.Longitude = temp;
result.Add(new Geopoint(basicGeoposition));
}
return result;
}
}
How it works you can read more at this post. The code listing uses some other util classes to handle response so I think you should read that post directly.
Taking a look into your account it doesn't look like there is any data source that can be accessed at
http://spatial.virtualearth.net/REST/v1/data/20181f26d9e94c81acdf9496133d4f23/petrolbunk/petrolbunk
Have you created a data source? If you have, in the Bing Maps portal, go to Data Sources -> View Data source information. Find the data source you want to access and copy the complete URL (you don't need to break it up into pieces i.e. accessId, data source name, entity name).
If you want to access one of the point of interest data sources in Bing Maps, then take a look at the NAVTEQNA data source: https://msdn.microsoft.com/en-us/library/hh478192.aspx
Given an absolute URI/URL, I want to get a URI/URL which doesn't contain the leaf portion. For example: given http://foo.com/bar/baz.html, I should get http://foo.com/bar/.
The code which I could come up with seems a bit lengthy, so I'm wondering if there is a better way.
static string GetParentUriString(Uri uri)
{
StringBuilder parentName = new StringBuilder();
// Append the scheme: http, ftp etc.
parentName.Append(uri.Scheme);
// Appned the '://' after the http, ftp etc.
parentName.Append("://");
// Append the host name www.foo.com
parentName.Append(uri.Host);
// Append each segment except the last one. The last one is the
// leaf and we will ignore it.
for (int i = 0; i < uri.Segments.Length - 1; i++)
{
parentName.Append(uri.Segments[i]);
}
return parentName.ToString();
}
One would use the function something like this:
static void Main(string[] args)
{
Uri uri = new Uri("http://foo.com/bar/baz.html");
// Should return http://foo.com/bar/
string parentName = GetParentUriString(uri);
}
Thanks,
Rohit
Did you try this? Seems simple enough.
Uri parent = new Uri(uri, "..");
This is the shortest I can come up with:
static string GetParentUriString(Uri uri)
{
return uri.AbsoluteUri.Remove(uri.AbsoluteUri.Length - uri.Segments.Last().Length);
}
If you want to use the Last() method, you will have to include System.Linq.
There must be an easier way to do this with the built in uri methods but here is my twist on #unknown (yahoo)'s suggestion.
In this version you don't need System.Linq and it also handles URIs with query strings:
private static string GetParentUriString(Uri uri)
{
return uri.AbsoluteUri.Remove(uri.AbsoluteUri.Length - uri.Segments[uri.Segments.Length -1].Length - uri.Query.Length);
}
Quick and dirty
int pos = uriString.LastIndexOf('/');
if (pos > 0) { uriString = uriString.Substring(0, pos); }
Shortest way I found:
static Uri GetParent(Uri uri) {
return new Uri(uri, Path.GetDirectoryName(uri.LocalPath) + "/");
}
PapyRef's answer is incorrect, UriPartial.Path includes the filename.
new Uri(uri, ".").ToString()
seems to be cleanest/simplest implementation of the function requested.
I read many answers here but didn't find one that I liked because they break in some cases.
So, I am using this:
public Uri GetParentUri(Uri uri) {
var withoutQuery = new Uri(uri.GetComponents(UriComponents.Scheme |
UriComponents.UserInfo |
UriComponents.Host |
UriComponents.Port |
UriComponents.Path, UriFormat.UriEscaped));
var trimmed = new Uri(withoutQuery.AbsoluteUri.TrimEnd('/'));
var result = new Uri(trimmed, ".");
return result;
}
Note: It removes the Query and the Fragment intentionally.
new Uri(uri.AbsoluteUri + "/../")
Get segmenation of url
url="http://localhost:9572/School/Common/Admin/Default.aspx"
Dim name() As String = HttpContext.Current.Request.Url.Segments
now simply using for loop or by index, get parent directory name
code = name(2).Remove(name(2).IndexOf("/"))
This returns me, "Common"
Thought I'd chime in; despite it being almost 10 years, with the advent of the cloud, getting the parent Uri is a fairly common (and IMO more valuable) scenario, so combining some of the answers here you would simply use (extended) Uri semantics:
public static Uri Parent(this Uri uri)
{
return new Uri(uri.AbsoluteUri.Remove(uri.AbsoluteUri.Length - uri.Segments.Last().Length - uri.Query.Length).TrimEnd('/'));
}
var source = new Uri("https://foo.azure.com/bar/source/baz.html?q=1");
var parent = source.Parent(); // https://foo.azure.com/bar/source
var folder = parent.Segments.Last(); // source
I can't say I've tested every scenario, so caution advised.