Moving IIS sites using AppCmd

Backup Process

%windir%\System32\inetsrv>appcmd list apppool /config /xml >C:\temp\apppools.xml
%windir%\System32\inetsrv>appcmd list sites /config /xml >C:\temp\sites.xml
… And all your website files

Zip up all these files, and move them to the destination server.

Restore Process

… Restore all your website files from the zip file.

Then Edit the apppools.xml file, and comment out any appPools that are already present in the destination server, for example
“DefaultAppPool” etc.

Then … Import App Pools using:

%windir%\system32\inetsrv\appcmd add apppool /in < c:\apppools.xml

Step 2.
Edit the Sites.xml file, and comment out any websites that are already present in the destination server, for example “Default website” etc

Edit the sites.xml file, and change the Site.ID=”<number>” and ID=”<number>” attributes so that they are larger than the largest Site ID in IIS.

Important: If you import a site with the same site ID as an existing site, then the entire server will crash

%windir%\system32\inetsrv\appcmd add site /in < c:\sites.xml

Categories: Uncategorized

no xaml was found at the location ‘/mainpage.xaml’

After upgrading a WP7 app to WP8 (VS 2013 RC), I got this very annoying error when trying to run the app in the emulator. “no xaml was found at the location ‘/mainpage.xaml'”.

I came across a conversation on twitter, regarding this, and saw that someone had the same problem, but said “Found it!!! Your application MUST have Invariant Language ticked as a supported language. Blog post to come :-)”

So, that narrowed my search, and I discovered a one line fix; In the AssemblyInfo.cs file, you have to change the line:

[assembly: NeutralResourcesLanguage(“en”, UltimateResourceFallbackLocation.Satellite)]

To

[assembly: NeutralResourcesLanguage(“en”)]

One line fix!. Pity the error message is not helpful at all.

Categories: Uncategorized

Saving files locally using PhoneGap

One of the quintessential differences between an application and a web page is that applications are trusted to read and write to the hard drive on the machine it is running on. With the exception of limited space given under certain circumstances for Isolated storage (Silverlight), Cookies and Localstorage (5Mb ~ or effectively 2.5 Mb of text), web pages aren’t trusted enough to read and write to your hard drive, and rightly so.

With Apps, there is an elevated level of trust, so you can read and write files within your application “Sandbox”, i.e. space devoted to your app, and no-one else’s.  With smartphones coming now with up to 64 GB of storage, this gives plenty of opportunity to download images, video and content for offline use.

I just learned this morning how to use PhoneGap’s File API, – This example applies specifically to version 2.9.0 on iOS, but it should be equally applicable to other versions, and Android.

First off, you need to get a handle to the local file system, which you can do on the device ready event like so:

var fileSystem = null;

document.addEventListener(“deviceready”, onDeviceReady, false);

function onDeviceReady()
{
console.log(“Device Ready”);
window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, function gotFS(fs)
{
console.log(“Got File System Reference”);
fileSystem = fs;
}, fail);
}

Here the variable fileSystem is declared with global scope, and I have selected Temporary storage. Temporary storage is not designed for “mission critical” or user generated content, just things that can be downloaded again, if need be. Ideal for short-term caching.

Then, I have written a handy function to store this data onto disk:

function createFileWithContent(filename, content)
{
fileSystem.root.getFile(
filename,
{create: true, exclusive: false},
function gotFileEntry(fileEntry) {
console.log(“Got File Entry Reference”);
console.log(fileEntry.toURL());
fileEntry.createWriter(
function gotFileWriter(writer) {
writer.onwriteend = function(evt) {
console.log(writer.fileName);};
writer.write(content);
}, fail);
}, fail);
}

This function writes text content to a file. You don’t worry about the path, since this is dictated by the operating system.

To read this back in, you can use simple ajax, as you would read a local file off disk.

The fail function is omitted here, but it can be a simple console.log, or something more advanced, depending on how you wish the app to respond to errors in the process of saving data.

 

Categories: Uncategorized

The Search API for Shopping has been shut down

As of this morning, Google shut down its Shopping API (As was forewarned). Now, if you try to call it, https://www.googleapis.com/shopping/search/v1/public/products?key=…&country=US&q=pogo&alt=json you get the following Error 412 response:

{
“error”: {
“errors”: [
{
“domain”: “global”,
“reason”: “conditionNotMet”,
“message”: “The Search API for Shopping has been shut down”,
“locationType”: “header”,
“location”: “If-Match”
}
],
“code”: 412,
“message”: “The Search API for Shopping has been shut down”
}
}

 

Adieu, le Shopping API.

Categories: Uncategorized

Console.log – Remote

If you have a PhoneGap/Cordova App, then you surely use Console.log statements to help with the debugging of your app while it is running in a simulator, or USB-attached device.

However, if your device cannot be attached to your development machine, or you cannot debug in the normal way, then this simple script lets you see Console.log output on a web browser.

Firstly, you’ll need access to a windows web-server, and upload this script:

<script language="C#" runat="server">

public static System.Collections.Generic.List<LogItem> logList = new 
System.Collections.Generic.List<LogItem>();

protected void Page_Load(object sender, EventArgs e)
{
string strText = Request.QueryString["text"];
if (strText != null)
{
logList.Add(new LogItem(strText));
return;
}
Response.Write("Log Running...<hr>");
Response.Flush();
DateTime startTime = DateTime.UtcNow;

while(DateTime.UtcNow - startTime < TimeSpan.FromMinutes(1))
{

foreach(LogItem logItem in logList)
{
if (!logItem.isRead)
{
Response.Write(logItem.text + "<br>");
Response.Flush();
logItem.isRead = true;
}
}
System.Threading.Thread.Sleep(100);
}
Response.Redirect(Request.RawUrl);
}

public class LogItem
{
public LogItem(string text)
{
this.text = text;
}

public string text = "";

public bool isRead = false;
}
</script>

Let’s imagine that you put this script at http://www.yourserver.com/log.aspx

Then, you need to override the default action of console.log with this piece of javascript (Which requires JQuery)

console = {};
console.log = function(text)
{
$.get(“http://www.yourserver.com/log.aspx?text=&#8221; + encodeURIComponent(text) + “&nocache=” + Math.random());
}

This, then means that instead of writing to the console output, it makes an AJAX call to the logging script. Visiting the logging script webpage will display the text passed to console.log.

There are some limitations, such that it is only suitable for one-app-one-developer type environments, and you have to remember to remove the override for console.log before submitting the app to Google / Apple / BlackBerry …

Categories: Uncategorized

Exceeding the Maximum size for Google static Maps

The table below shows the maximum allowable values for the size parameter at each scale value.

API scale=1 scale=2 scale=4
Free 640x640 640x640 (returns 1280×1280 pixels) Not available.
Google Maps API for Business 2048x2048 1024x1024 (returns 2048×2048 pixels) 512x512 (returns 2048×2048 pixels)

– As per Google’s documentation, this is the largest size images you can get from the Google Static Maps API

However, there is a work-around that allows for larger images to be returned from the Google static maps API. But it requires quite a bit of work. Basically, you need to find the adjacent tile to the requested tile.

For this, you need to flatten your longitude and latitudes into a flat x / y grid. Once you have X/Y coordinates, then you can use simple maths to pick up the next tile, then with these new x/y positions, you have to re-map this to the spherical projection of the world, to give you back longitude and latitude values.

Flattening and projecting latitude/longitude coordinates to x/y grid coordinates is done using the Mercator projection. Here is a modified version of Mercator.js, that you can include in your project.

var MERCATOR_RANGE = 256;

function bound(value, opt_min, opt_max) {
if (opt_min != null) value = Math.max(value, opt_min);
if (opt_max != null) value = Math.min(value, opt_max);
return value;
}

function degreesToRadians(deg) {
return deg * (Math.PI / 180);
}

function radiansToDegrees(rad) {
return rad / (Math.PI / 180);
}

function MercatorProjection() {
this.pixelOrigin_ = {x: MERCATOR_RANGE / 2, y: MERCATOR_RANGE / 2};
this.pixelsPerLonDegree_ = MERCATOR_RANGE / 360;
this.pixelsPerLonRadian_ = MERCATOR_RANGE / (2 * Math.PI);
};

MercatorProjection.prototype.fromLatLngToPoint = function(latLng) {
var me = this;

var point = {x:0,y:0};

var origin = me.pixelOrigin_;
point.x = origin.x + latLng.lng * me.pixelsPerLonDegree_;
// NOTE(appleton): Truncating to 0.9999 effectively limits latitude to
// 89.189. This is about a third of a tile past the edge of the world tile.
var siny = bound(Math.sin(degreesToRadians(latLng.lat)), -0.9999, 0.9999);
point.y = origin.y + 0.5 * Math.log((1 + siny) / (1 – siny)) * -me.pixelsPerLonRadian_;
return point;
};

MercatorProjection.prototype.fromPointToLatLng = function(point) {
var me = this;
var origin = me.pixelOrigin_;
var lng = (point.x – origin.x) / me.pixelsPerLonDegree_;
var latRadians = (point.y – origin.y) / -me.pixelsPerLonRadian_;
var lat = radiansToDegrees(2 * Math.atan(Math.exp(latRadians)) – Math.PI / 2);
return {lat:lat, lng:lng};
};

Let’s just quickly have a look at how the Google static maps API works.

function renderMap(image, LatLng)
{
image.attr(“src”,”http://maps.googleapis.com/maps/api/staticmap?center=&#8221; + LatLng.lat + “,” + LatLng.lng + “&zoom=10&size=400×400&sensor=false”);
}

This displays a map of a specified latitude and longitude  at zoom level 10, and a 400×400 size image. The image parameter is a jquery collection object referring to a HTML IMG tag.

Now, to display a map at 55,-7 you’d call:

renderMap($(“#img11”),{lat:55,lng:-7});

Now, to apply some magic to this, and display the map tile immediately eastward of this map location, then I use this function:

function GetTileDelta(center,zoom,mapWidth,mapHeight,delta){
var proj = new MercatorProjection();
var scale = Math.pow(2,zoom);
var centerPx = proj.fromLatLngToPoint(center);
var DeltaPx = {
x: (centerPx.x + ((mapWidth / scale) * delta.x)) ,
y: (centerPx.y + ((mapHeight/ scale) * delta.y))
};
var DeltaLatLon = proj.fromPointToLatLng(DeltaPx);
return DeltaLatLon;
}

Which is called as follows:

var RightLatLng = GetTileDelta({lat:55,lng:-7},10,400,400,{x:+1,y:0});
renderMap($(“#img12”),RightLatLng);

How this works, is by “flattening” the globe using the mercator projection, using simple maths to shift the x position the width of the map over to the right (eastward), then folding the x/y coordinates over the globe using the mercator projecion again, to provide the lat/lon coordinates.

By extension, you can then use this to obtain any size map required.

Categories: Uncategorized

Translation API without an API Key

Over the last few days, I’ve been on the hunt for a good unlimited , free translation API. I’ve stumbled upon Glosbe.com, which does not require an API key, although they do mention it may be limited by request per IP to prevent abuse, and I’ll test that out on Monday.

But, as always, here is the C# code required to access this translation API:

First, we get the JSON data from their API as follows:

string strUrl = “http://glosbe.com/gapi/translate?from=eng&dest={1}&format=json&phrase={0}&pretty=true&tm=false”;
strUrl = string.Format(strUrl, word, language);
WebClient wc = new WebClient();
wc.Encoding = Encoding.UTF8;
var strJson = wc.DownloadString(strUrl);

The JSON object returned contains much more than just one word, it provides some sample usage, sentences, alternative translations, etc. But I’ll just assume the first translation is valid;

Here is the a sample translation of “cat” into italian

{
  "result" : "ok",
  "authors" : {
    "1" : {
      "U" : "http://en.wiktionary.org",
      "id" : 1,
      "N" : "en.wiktionary.org"
    },
    "86" : {
      "U" : null,
      "id" : 86,
      "N" : "wiki"
    },
    "25018" : {
      "U" : "http://glosbe.com",
      "id" : 25018,
      "N" : "GlosbeResearch"
    },
    "2695" : {
      "U" : "http://dumps.wikimedia.org/enwiktionary/latest/enwiktionary-latest-pages-articles.xml.bz2",
      "id" : 2695,
      "N" : "Wiktionary"
    },
    "2771" : {
      "U" : "http://dizionario.dejudicibus.it/",
      "id" : 2771,
      "N" : "Dizionario-generale-Inglese"
    }
  },
  "dest" : "ita",
  "phrase" : "cat",
  "tuc" : [ {
    "authors" : [ 1 ],
    "meaningId" : -2324632015665027181,
    "meanings" : [ {
      "text" : "domestic species",
      "language" : "eng"
    }, {
      "text" : "Mammifero carnivoro, felino di taglia media dal muso corto, domestico o allo stato selvatico (Felis Silvestris)",
      "language" : "ita"
    }, {
      "text" : "A common four-legged animal (Felis silvestris) that is often kept as a household pet.",
      "language" : "eng"
    } ],
    "phrase" : {
      "text" : "gatto",
      "language" : "ita"
    }
  }, {
    "authors" : [ 1 ],
    "meaningId" : 3792577973885107081,
    "meanings" : [ {
      "text" : "domestic species",
      "language" : "eng"
    } ],
    "phrase" : {
      "text" : "gatta",
      "language" : "ita"
    }
  }, {
    "authors" : [ 1 ],
    "meaningId" : -8655742666001237549,
    "meanings" : [ {
      "text" : "domestic species",
      "language" : "eng"
    }, {
      "text" : "Mammifero carnivoro, felino di taglia media dal muso corto, domestico o allo stato selvatico (Felis Silvestris)",
      "language" : "ita"
    }, {
      "text" : "A common four-legged animal (Felis silvestris) that is often kept as a household pet.",
      "language" : "eng"
    } ],
    "phrase" : {
      "text" : "micio",
      "language" : "ita"
    }
  }, {
    "authors" : [ 1 ],
    "meaningId" : 7605985072771688493,
    "meanings" : [ {
      "text" : "domestic species",
      "language" : "eng"
    } ],
    "phrase" : {
      "text" : "micia",
      "language" : "ita"
    }
  }, {
    "authors" : [ 1 ],
    "meaningId" : 4835673442782652847,
    "meanings" : [ {
      "text" : "member of '''Felidae'''",
      "language" : "eng"
    } ],
    "phrase" : {
      "text" : "felina",
      "language" : "ita"
    }
  }, {
    "authors" : [ 1 ],
    "meaningId" : -797550926637310842,
    "meanings" : [ {
      "text" : "member of '''Felidae'''",
      "language" : "eng"
    } ],
    "phrase" : {
      "text" : "felino",
      "language" : "ita"
    }
  }, {
    "authors" : [ 1 ],
    "meaningId" : -1699184890059243019,
    "meanings" : [ {
      "text" : "raise anchor to cathead",
      "language" : "eng"
    } ],
    "phrase" : {
      "text" : "caponare",
      "language" : "ita"
    }
  }, {
    "authors" : [ 2771 ],
    "meaningId" : 3378167150074910555,
    "phrase" : {
      "text" : "caponare l’ancor",
      "language" : "ita"
    }
  }, {
    "authors" : [ 2771 ],
    "meaningId" : -6368320918367433051,
    "phrase" : {
      "text" : "capone",
      "language" : "ita"
    }
  }, {
    "authors" : [ 2771 ],
    "meaningId" : -6436875142752376744,
    "phrase" : {
      "text" : "doppio tripode",
      "language" : "ita"
    }
  }, {
    "authors" : [ 86 ],
    "meaningId" : 6190890005020929990,
    "phrase" : {
      "text" : "felis silvestris catus",
      "language" : "ita"
    }
  }, {
    "authors" : [ 2771 ],
    "meaningId" : 4594590012605235113,
    "phrase" : {
      "text" : "flagellare",
      "language" : "ita"
    }
  }, {
    "authors" : [ 2771 ],
    "meaningId" : -3077370652934689664,
    "phrase" : {
      "text" : "frustare",
      "language" : "ita"
    }
  }, {
    "authors" : [ 2771 ],
    "meaningId" : 6355132814983896932,
    "phrase" : {
      "text" : "fustigare",
      "language" : "ita"
    }
  }, {
    "authors" : [ 25018 ],
    "meaningId" : -8207633928534718191,
    "phrase" : {
      "text" : "gatto selvatico",
      "language" : "ita"
    }
  }, {
    "authors" : [ 2771 ],
    "meaningId" : 2464893808723829126,
    "phrase" : {
      "text" : "lippa",
      "language" : "ita"
    }
  }, {
    "authors" : [ 2695 ],
    "meaningId" : -599611544161509388,
    "phrase" : {
      "text" : "micio micia",
      "language" : "ita"
    }
  }, {
    "authors" : [ 2771 ],
    "meaningId" : 9131410793497437392,
    "phrase" : {
      "text" : "ragazza maliziosa",
      "language" : "ita"
    }
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "An enthusiast or player of jazz.",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "(computing) A &lsquo;catenate&rsquo; program and command in Unix that reads one or more files and directs their content to an output device.",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "(slang, vulgar, African American Vernacular) A vagina; female external genitalia",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "(slang) To vomit something.",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "(Irish, informal) terrible, disastrous.",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "(archaic, uncountable) The game of &quot;trap and ball&quot; (also called &quot;cat and dog&quot;).",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "(slang) Any of a variety of earth-moving machines. (from their manufacturer Caterpillar Inc.)",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "(nautical) To flog with a cat-o'-nine-tails.",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "vomit",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "(archaic) A sturdy merchant sailing vessel (now only in &quot;catboat&quot;).",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "(slang) Prostitute. [from at least early 15th c.]",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "Any similar animal of the family Felidae, which includes lions, tigers, etc.",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "(nautical) Contraction of cat-o'-nine-tails.",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "guy, fellow",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "(archaic, uncountable) The trap of the game of &quot;trap and ball&quot;.",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "(slang) A person (usually male).",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "(nautical) To hoist (the anchor) by its ring so that it hangs at the cathead.",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "(computing slang) To dump large amounts of data on (an unprepared target) usually with no intention of browsing it carefully.",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "(derogatory) A spiteful or angry woman. [from earlier 13th c.]",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "A catfish.",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "A domesticated subspecies (Felis silvestris catus) of feline animal, commonly kept as a house pet. [from 8th c.]",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "(nautical) A strong tackle used to hoist an anchor to the cathead of a ship.",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "(computing) To apply the <b>cat</b> command to (a file).",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "strong tackle used to hoist an anchor to the cathead of a ship",
      "language" : "eng"
    } ]
  }, {
    "authors" : [ 1 ],
    "meaningId" : null,
    "meanings" : [ {
      "text" : "A catamaran.",
      "language" : "eng"
    } ]
  } ],
  "from" : "eng"
}

So, using this JSON, I created a C# class, omitting the “Authors” section that didn’t convert well, and I didn’t need anyway;

 

public class Meaning
{
public string text { get; set; }
public string language { get; set; }
}

public class Phrase
{
public string text { get; set; }
public string language { get; set; }
}

public class Tuc
{
public List<int> authors { get; set; }
public object meaningId { get; set; }
public List<Meaning> meanings { get; set; }
public Phrase phrase { get; set; }
}

public class RootObject
{
public string result { get; set; }
public string dest { get; set; }
public string phrase { get; set; }
public List<Tuc> tuc { get; set; }
public string from { get; set; }
}

and finally, de-serializing it, and returning the one word I need;

System.Web.Script.Serialization.JavaScriptSerializer js = new System.Web.Script.Serialization.JavaScriptSerializer();
RootObject ro = js.Deserialize<RootObject>(strJson);
return ro.tuc[0].phrase.text;

 

Categories: Uncategorized

Yandex Translation in C#

Ever since Google started charging for it’s Translation API, and Microsoft put a 2 Million character limit on their free translation API, then you have to start looking outside of the USA for a free translation service. That’s when I discovered the Russian translation service provided by Yandex. They also do plenty of other languages, (Albanian Armenian Azerbaijani Belarusian Bulgarian Catalan Croatian Czech Danish Dutch Estonian Finnish French German Greek Hungarian Italian Latvian Lithuanian Macedonian Norwegian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swedish Turkish Ukrainian)

So, the first step is to go to http://api.yandex.com/translate/ and sign up for a Yandex Passport, and get an API key.

Then, I created a C# class with a static method to do the translation from code:

public static string Translate(string word, string language)
{
string strUrl = “https://translate.yandex.net/api/v1.5/tr.json/translate?&#8221;;
strUrl += “key=trnsl.1.1……..”;
strUrl += “&lang=en-” + language;
strUrl += “&text=” + word;
WebClient wc = new WebClient();
wc.Encoding = Encoding.UTF8;
string strJson = wc.DownloadString(strUrl);
….
}

This returns a JSON string in the format:

{
“code”: 200,
“lang”: “en-ru”,
“text”: [
“Быть или не быть?”,
“Вот в чем вопрос.”
]
}

So, to de-serialize this to a C# object, I used a class generated from http://json2csharp.com/ as follows:

public class RootObject
{
public int code { get; set; }
public string lang { get; set; }
public List<string> text { get; set; }
}

Then the de-serialization can take place at the end of the translate method:

System.Web.Script.Serialization.JavaScriptSerializer js = new System.Web.Script.Serialization.JavaScriptSerializer();
RootObject ro = js.Deserialize<RootObject>(strJson);
return ro.text[0];

A quirk I noticed when doing this as a console app, was that the console could not write our Cyrillic characters. There is a way around this by using the Windows API, but I just used a MessageBox.

Categories: Uncategorized

Offline Geolocation

cell-tower

Offline Geolocation is an Android Library that can be used to determine the location of an Android phone when both GPS positioning and an Internet connection are unavailable.

This project is completely open source, you can download the source code for the Android App, and import it into your eclipse workspace. All we ask is that you tell us who you are and what you plan to do with the code before downloading it. You can then use the code freely, without any license restrictions, although we’d love it if you can give us credit in your final product.

How this App works, is it detects nearby cell towers, and compares the cell id, MCC, MNC and LAC codes against a SQLLite database of over 2 million known cell towers worldwide. It is designed to give you the best answer it can, although, the data is not exhaustive. This data will never be as accurate as GPS or Online Geolocation, but it serves as a good failover, whenever an Internet connection is unavailable.

Please read more at www.offlinegeolocation.com 

 

master_1600x1200

Categories: Uncategorized

Hello World, OAUTH

OAuth

OAUTH is an authentication system used by companies such as Google, Twitter, Vimeo, Linked in etc, and it is much more complex than basic authentication, but it really is just about exchanging data between your server and the authentication provider.

This is meant to be a “Hello World” example, showing an easy way to implement OAuth 2, without using any third party frameworks.

The example uses C# (ASPX), and Google API. I will be demonstrating a call to Google Analytics API, but any Google API works similarly. I can’t say the same for Twitter / Vimeo / LinkedIn, but the flow of data should be the same.

Prerequisites:

  • Some windows hosting to host the callback page
  • Sign up through the Google API Console to the Google Analytics API, and set up a client ID for Web Applications

Flow of actions overview:

The reason why OAuth is popular, is because it means that API consumers (i.e. you), don’t get to see user’s Google credentials.  You never ask the user for their username and password, you send them to Google and Google enter their username and password on Google’s page. Google will then send you back “proof” that the username and password were correct, but will never tell you what the username and password was.

The first step, therefore is to send a user to google using a special link. A simple link like this does:

<a href=”https://accounts.google.com/o/oauth2/auth?state=%2Fprofile&redirect_uri=http%3A%2F%2Fdananos.brinkster.net%2Foauth%2Fcallback.aspx&response_type=code&client_id=540622200787-bdm94elvkgshgl12inm99qug33jav38b.apps.googleusercontent.com&approval_prompt=force&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fanalytics”&gt;
Login</a>

Let’s break down that link:

https://accounts.google.com/o/oauth2/auth?state=%2Fprofile
&redirect_uri=http%3A%2F%2Fdananos.brinkster.net%2Foauth%2Fcallback.aspx
&response_type=code
&client_id=540622200787-bdm94elvkgshgl12inm99qug33jav38b.apps.googleusercontent.com
&approval_prompt=force
&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fanalytics

The important bits are:

client_id – You get this from your Google API Console

redirect_uri – You set this in your Google API, and it tells Google where to send the user after they have logged in.

scope – This sets which APIs you would like to use, In my case, Google Analytics.

Once the user signs into Google, then it’s up to some server-side code to interpret the response from Google, and use it to access Google’s APIs using the user’s credentials. This is where the callback script comes in, which is simply an ASPX page that is hosted on your server.

The steps that this script must do is:

  • 1. Exchange the authorisation code provided by Google into a access token
  • 2. Use the access token when calling Google’s API methods.

Let’s deal with the first step, the exchange of the authorisation code.

Google will redirect back to your URL with extra parameters, like this:

callback.aspx?state=/profile&code=4/l_QKG8_zbhRi-hi9yhRXEyoUqHc8.wrb2xyoo0IQfOl05ti8ZT3bDNXF_gQI

The code value needs to be sent to https://accounts.google.com/o/oauth2/token,  with the following POST data:

  • code – taken from the querystring sent back from google
  • redirect_uri – from your Google API console
  • client_id – from  your Google API console
  • scope –  empty
  • client_secret – from your Google API console
  • grant_type – set to authorization_code

This is the C# code I used to make this request  (My Access credentials removed)

string strToken = Request.QueryString[“code”];
System.Net.WebClient wc = new System.Net.WebClient();
string strExchange = “code={0}”;
strExchange += “&redirect_uri=…”;
strExchange += “&client_id=….”;
strExchange += “&scope=&”;
strExchange += “client_secret=….&grant_type=authorization_code”;
strExchange = string.Format(strExchange,strToken);
string strUrl = “https://accounts.google.com/o/oauth2/token&#8221;;
wc.Headers[System.Net.HttpRequestHeader.ContentType] = “application/x-www-form-urlencoded”;
string strHtml = wc.UploadString(strUrl, strExchange);

Returned, is a small piece of JSON in this format:

{ “access_token” : “ya29.AHES6ZTBNv8wBJFPnn7rMPvrHZseG6EUUvfYuiPFTx3TUT_zpYVEIQ”, “token_type” : “Bearer”, “expires_in” : 3600 }

One of the best ways to parse this JSON is to use the JavaScriptSerializer object built into .NET, this requires you to define a class that matches the JSON schema, like this:

public class RootObject
{
public string access_token { get; set; }
public string token_type { get; set; }
public int expires_in { get; set; }
public string id_token { get; set; }
}

Then using the following code to convert the JSON into a “RootObject” object;

System.Web.Script.Serialization.JavaScriptSerializer js = new System.Web.Script.Serialization.JavaScriptSerializer();
RootObject ro = js.Deserialize<RootObject>(strHtml);

Once we have our RootObject, we can use the access_token to call Google APIs like so:

System.Net.WebClient wc2 = new System.Net.WebClient();
strUrl = “https://www.googleapis.com/analytics/v3/management/accounts&#8221;;
wc2.Headers.Add(“Authorization”,”Bearer ” + ro.access_token);
strHtml = wc2.DownloadString(strUrl);

This then returns the Google Analytics accounts associated with the authenticated Google user, in my case it is:

{
  "kind": "analytics#accounts",
  "username": "xxxx.xxxx@gmail.com",
  "totalResults": 1,
  "startIndex": 1,
  "itemsPerPage": 1000,
  "items": [
    {
      "id": "3658396",
      "kind": "analytics#account",
      "selfLink": "https:\/\/www.googleapis.com\/analytics\/v3\/management\/accounts\/3658396",
      "name": "www.outsourcetranslation.com",
      "created": "2008-02-17T13:58:09.000Z",
      "updated": "2011-07-07T22:34:55.677Z",
      "childLink": {
        "type": "analytics#webproperties",
        "href": "https:\/\/www.googleapis.com\/analytics\/v3\/management\/accounts\/3658396\/webproperties"
      }
    }
  ]
}

And there you have it, we’ve successfully used OAuth to authenticate a user against a Google API.

Categories: Uncategorized