How to get redirect from HttpWebResponse? - c#

I am trying to get a redirect from Google Maps using a project that is currently only at .Net Framework 4.0.
Take Microsoft's mailing address as an example:
1 Microsoft Way, Redmond, WA
Format a string that replaces Spaces , Commas , with Plus + signs:
https://www.google.com/maps?daddr=1+microsoft+way+redmond+wa
By the time Google finishes processing the page, the final URL has the Latitude and Longitude:
https://www.google.com/maps/dir//1+Microsoft+Way,+Redmond,+WA+98052/#47.6393095,-122.1327333,16z/data=!3m1!4b1!4m8!4m7!1m0!1m5!1m1!1s0x54906d73f7de150b:0x922499d19305e9a0!2m2!1d-122.1283559!2d47.6393096
I need the Latitude and Longitude from this URL.
I found this article already on SO:
Get a collection of redirected URLs from HttpWebResponse
Using the solution there, I created this very similar looking method:
private String latitude, longitude;
private void GetLatLongFromAddress(String p_street_name, String p_city, String p_state, String p_postal_code)
{
var street_name = String.Format("{0}", p_street_name.Replace(' ', '+')).Trim();
var city = String.Format("{0}", p_city).Trim();
var state = String.Format("{0}", p_state).Trim();
var postal_code = String.Format("{0}", p_postal_code).Trim();
var mapUrl = String.Format("http://maps.google.com/?daddr={0}+{1}+{2}+{3}",
street_name, city, state, postal_code);
var location = String.Copy(mapUrl);
while (!String.IsNullOrEmpty(location))
{
var req1 = (HttpWebRequest)HttpWebRequest.Create(location);
req1.AllowAutoRedirect = false;
// give page time to redirect?
// System.Threading.Thread.Sleep(5000);
using (var resp = (HttpWebResponse)req1.GetResponse())
{
location = resp.GetResponseHeader("Location");
if (!String.IsNullOrEmpty(location))
{
var postalIndex = location.IndexOf(postal_code);
var slashAtIndex = location.IndexOf("/#") + 1;
if ((postalIndex < slashAtIndex) && (slashAtIndex < location.Length))
{
var split = location.Substring(slashAtIndex).Split(',');
latitude = split[0];
longitude = split[1];
}
}
}
}
}
You can see where I format the original URL with this line:
var mapUrl = String.Format("http://maps.google.com/?daddr={0}+{1}+{2}+{3}",
street_name, city, state, postal_code);
The problem is with this line:
location = resp.GetResponseHeader("Location");
Every time I get the response, the returned location value is the same as the mapUrl value that I started with because Google does not redirect it immediately.
I tried adding a Sleep(5000) call, but that did not change anything.
How would I go about getting the final redirect?

Related

Get longitude and latitude from API

I have searched on Google and here on Stack Overflow, but due to my limited expertise in C# and SSIS I have some troubles getting through.
My steps in this SSIS package is as follows:
I have a SQL task connected to a for loop which only specifies how many times I should iterate in Forloop container which is =1
Inside Forloop container have a dataflow task
In dataflow task, I use an OLEDB source to get addresses from a SQL table
I connect those OLEDB source to a Script task from which the following script "Should" return my XML answer from which I want to return Latitude and longitude. It does not return the answer that I want.
Example address is - Beihinger Strasse 160 DE-71726 BENNINGEN GERMANY
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
string url = "http://dev.virtualearth.net/REST/v1/Locations?addressLine={0}&output=xml&key={1}";
var Address = Row.Address;
var wGet = WebRequest.Create(String.Format(url, Address, Variables.APIkey));
wGet.Method = WebRequestMethods.Http.Get;
var response = wGet.GetResponse();
var status = ((HttpWebResponse)response).StatusDescription;
Console.WriteLine("Input: " + Address);
if (status == "OK")
{
StreamReader reader = new StreamReader(response.GetResponseStream());
string responseFromServer = reader.ReadToEnd();
reader.Close();
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(responseFromServer);
var nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("Point", "http://schemas.microsoft.com/search/local/ws/rest/v1");
var latNode = xmlDoc.DocumentElement.SelectSingleNode("/ResourceSets/ResourceSet/Resources/Location/Point/Latitude", nsmgr);
var lngNode = xmlDoc.DocumentElement.SelectSingleNode("/ResourceSets/ResourceSet/Resources/Location/Point/Longitude", nsmgr);
if (latNode != null && lngNode != null)
{
var numberFormatInfo = new NumberFormatInfo { NumberDecimalSeparator = "." };
Row.Latitude = decimal.Parse(latNode.InnerText, numberFormatInfo);
Row.Longitude = decimal.Parse(lngNode.InnerText, numberFormatInfo);
Row.FullResponse = responseFromServer.ToString();
}
else
{
//Set to null
Row.Latitude_IsNull = true;
Row.Longitude_IsNull = true;
Row.FullResponse = responseFromServer.ToString();
}
}
else
{
//Set to null
Row.Latitude_IsNull = true;
Row.Longitude_IsNull = true;
Row.FullResponse_IsNull = true;
}
response.Close();
}
}
The response I get is:
<?xml version="1.0" encoding="utf-8"?><Response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/search/local/ws/rest/v1"><Copyright>Copyright © 2020 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.</Copyright><BrandLogoUri>http://dev.virtualearth.net/Branding/logo_powered_by.png</BrandLogoUri><StatusCode>200</StatusCode><StatusDescription>OK</StatusDescription><AuthenticationResultCode>ValidCredentials</AuthenticationResultCode><TraceId>b9a94b411dc246ea82d161dae5e7a0c3|DU00000D73|0.0.0.1|Ref A: ACDD23537F6649F6B2F66333BB6D6D01 Ref B: DB3EDGE0918 Ref C: 2020-02-12T11:25:05Z</TraceId><ResourceSets><ResourceSet><EstimatedTotal>0</EstimatedTotal><Resources /></ResourceSet></ResourceSets></Response>
I want a correct call as I get when using URL so I can get Longitude and Latitude- http://dev.virtualearth.net/REST/v1/Locations?addressLine=Beihinger%20Strasse%20160%20DE-71726%20BENNINGEN%20GERMANY&output=xml&key={APIkey}
Any help would be greatly appreciated to what I am missing?

Xamarin c# for Android : creating a json string?

Having problems with this code ..
GlodalVariables.SoftID = "55";
WebClient client = new WebClient ();
Uri uri = new Uri ("http://www.example.com/CreateEntry.php");
string folder = System.Environment.GetFolderPath (System.Environment.SpecialFolder.Personal);
Android.Content.Context myContext = Android.App.Application.Context;
try{
string smsUri = System.IO.Path.Combine (folder, "SL.db");
string myjson = "";
SQLiteDatabase Mydb = SQLiteDatabase.OpenDatabase(smsUri , null, DatabaseOpenFlags.OpenReadwrite );
ICursor SMScursor = Mydb.Query ("MySMSLog", null,null, null,null, null ,"TheDate ASC");
MySMSLog test = new MySMSLog() ;
if (SMScursor.MoveToFirst ()) {
while (!SMScursor.IsAfterLast){
string number = SMScursor.GetString(SMScursor.GetColumnIndex("TheNumber"));
string name = SMScursor.GetString(SMScursor.GetColumnIndex("TheName"));
string date = SMScursor.GetString(SMScursor.GetColumnIndex("TheDate"));
string direction = SMScursor.GetString(SMScursor.GetColumnIndex("TheDirection"));
string text = SMScursor.GetString(SMScursor.GetColumnIndex("TheText"));
string id = SMScursor.GetString(SMScursor.GetColumnIndex("Id"));
test.Id = int.Parse(id);
test.TheDate = date;
test.TheDirection = direction ;
test.TheName = name;
test.TheNumber = number;
test.TheText = text;
string output = Newtonsoft.Json.JsonConvert.SerializeObject (test);
myjson = myjson + output + " ";
SMScursor.MoveToNext ();
}
}
System.Console.WriteLine (myjson );
System.Console.WriteLine();
SMScursor.Close ();
When i Copy the complete json string into a json test site (http://jsonlint.com/)
It tells me the sting is invalid ...
I'm getting all the record rows and putting them into a single json string before pushing them over to the server..
Shouldn't you get the result in an array form? So the final json should look like :
[{json1},{json2}..]
Probably if you have just {json1} {json2} this is not a valid object.
Could an alternative solution be to build a collection of "MySMSLog" objects, then serialise the collection throught JSonConvert? That way you don't need to worry about getting the structure correct through your own string manipulation.
This would most likely also future proof your code on the ridiculously outlandish chance that JSON standards change, as the NewtonSoft library would be updated as well.

Google Currency Converter

I had used this code in the last years however google seemed to have changed some of their links. For some reason I am getting this error message:
"Input string was not in a correct format."
in following line:
decimal rate = System.Convert.ToDecimal(match.Groups[1].Value);
My code:
try
{
WebClient web = new WebClient();
string url = string.Format("https://www.google.com/finance/converter?a={2}&from={0}&to={1}", fromCurrency.ToUpper(), toCurrency.ToUpper(), amount);
string response = web.DownloadString(url);
Regex regex = new Regex("rhs: \\\"(\\d*.\\d*)");
Match match = regex.Match(response);
decimal rate = System.Convert.ToDecimal(match.Groups[1].Value);
return rate;
}
catch
{
return 0;
}
You may not like this approach but it get's the job done.
WebClient web = new WebClient();
string url = string.Format("https://www.google.com/finance/converter?a={2}&from={0}&to={1}", fromCurrency.ToUpper(), toCurrency.ToUpper(), amount);
string response = web.DownloadString(url);
var split = response.Split((new string[] { "<span class=bld>"}),StringSplitOptions.None);
var value = split[1].Split(' ')[0];
decimal rate = decimal.Parse(value,CultureInfo.InvariantCulture);

How to access a key named with asterisk?

There is a method in Wikimedia API that gives a localized title.
Examples:
Cloud:
http://en.wikipedia.org/w/api.php?format=json&action=query&titles=Cloud&prop=langlinks&lllimit=500&lllang=ru&continue=
Rain: http://en.wikipedia.org/w/api.php?format=json&action=query&titles=Rain&prop=langlinks&lllimit=500&lllang=ru&continue=
Cloud response:
{
"batchcomplete":"",
"query":{
"pages":{
"47515":{
"pageid":47515,
"ns":0,
"title":"Cloud",
"langlinks":[
{
"lang":"ru",
"*":"\u041e\u0431\u043b\u0430\u043a\u0430"
}
]
}
}
}
}
Rain response:
{
"batchcomplete":"",
"query":{
"pages":{
"19009110":{
"pageid":19009110,
"ns":0,
"title":"Rain",
"langlinks":[
{
"lang":"ru",
"*":"Дождь"
}
]
}
}
}
}
Important note: integer container under pages (e.g. 19009110) is always different, because it equals page id.
C# code:
dynamic datacontainer_RUname2 = JObject.Parse(cleanJson_string_RUname);
String localizedName = datacontainer_RUname.[HERE SHOULD BE *];
How can I access a key named with asterisk '*'?
string content;
using (var webClient = new WebClient())
{
const string url = "http://en.wikipedia.org/w/api.php?format=json&action=query&titles=Cloud&prop=langlinks&lllimit=500&lllang=ru&continue=";
content = webClient.DownloadString(url);
}
var obj = JObject.Parse(content);
var query = obj["query"];
var pages = query["pages"].Value<JObject>();
var page = pages.PropertyValues().First();
var langLinks = page["langlinks"].Values<JObject>();
var firstLangLink = langLinks.First();
var localizedName = firstLangLink["*"];
See a working demo with live data.
Just use the normal indexing on the object.
string localizedName = obj["*"];
In your case... to get to your object, you can do this query in both cases. To collect all links returned from the query:
var allLinks =
from page in response.SelectToken("query.pages").Values()
from link in page["langlinks"]
select (string)link["*"];

How to use hostip.info service in c#?

I have a method named getIP() which returns the clients ip as a string.
How do I use this IP to get the location of the client using this service.
This is how i show the clients IP address.
string IP = getIP();
lblIPAddress.Text = "IP " + IP;
How do i include the clients location in ?
i.e. lblIPAddress.Text = "IP " + IP+ "location" ;)
Below you can find a very simple snippet which I was using to get data from XML endpoint of that API some time ago (I believe there was no changes to the API so it still should work):
string city;
string country;
string countryCode;
decimal longitude;
decimal latitude;
XmlTextReader hostIPInfoReader = new XmlTextReader("http://api.hostip.info/?ip=" + IP);
while (hostIPInfoReader.Read()) {
if (hostIPInfoReader.IsStartElement()) {
if (hostIPInfoReader.Name == "gml:name")
city = hostIPInfoReader.ReadString();
if (hostIPInfoReader.Name == "countryName")
country = hostIPInfoReader.ReadString();
if (hostIPInfoReader.Name == "countryAbbrev")
countryCode = hostIPInfoReader.ReadString();
if (hostIPInfoReader.Name == "gml:coordinates") {
string[] coordinates = hostIPInfoReader.ReadString().Split(new char[] { ',' });
longitude = decimal.Parse(coordinates[0]);
latitude = decimal.Parse(coordinates[1]);
}
}
}
This code can be of course improved but I believe it`s a good starting point for you.

Categories

Resources