APIMASH GeoNames Wikipedia API Walkthrough

Having a hard time getting your Windows 8 apps jumpstarted? Wouldn't it be nice to have some templates out there that allow you to easily integrate in data from various sources? Good news for you who are wanting a jumpstart accessing various internet APIs!

DPE East has put together a series of APIMASH templates. The templates provide base application functionality. Each templates call at least one external API, providing "call code" in a format you can reuse.  I would love to hear some success stories in building Windows 8 apps ( or down the road Windows Phone, watch for more on this ) using the templates for published applications. To see the complete collection go to https://bit.ly/apimash. If you want more info on APIMASH or other particulars, see my resources link at the end of this post.

During this blog post I'll cover how you can "wireup" the GeoNames Wikipedia data sources. Note if you don't want to do all these steps, you can simply run the sample project from the APIMASH download and see how it works there. These steps are to show you its just not all that hard to put it into your own solution.

GeoNames is a geographical database for all countries, covering over eight million placenames that can be downloaded and integrated free of charge.  GeoNames provides an open, free, API to query their application.  The free version of their API is limited to 2 calls per second, 5000 calls per day.  If you need more than that  you can scale up to their professional level.  See the resources section below for signup info.

GeoNames Wikipedia web services gives access to the geotagged articles on Wikipedia. Full text summaries are available for most entries as well. The GeoNames API exposes three separate APIs we have bundled into our starter kit. They are:

  • Find nearby Wikipedia entries - pass a lat long or a postalcode or placename
  • Fulltext search - pass in a placename and get back entries that mention it
  • Bounding Box - pull all the entries in a latitude / longitude bounding box

During this session we're giong to show how to wire up and basically just dump the output from the GeoNames API calls to a text box. Work along with me and you'll have your own working baseline GeoNames wikipedia app at the end.

STEP 1 - JSON.NET
The starter kits require JSON.NET for JSON parsing.  We are going to download JSON.NET locally and reference it from there. If you wish to use NUGET to pull down JSON.NET, see Bob Familiar's article which shows you how at https://theundocumentedapi.com/index.php/apimash-chuck-norris-starter-kit  .  Honestly, NUGET is an easier option, but here's how you do it the 'old school' way, pre NUGET.   If you've already have JSON.NET down, don't worry about the steps in the next section.

  1. Download JSON.NET from https://json.codeplex.com
  2. Extract out all the contents to your hard drive into a JSON folder of your choosing
  3. Open the Newtonsoft.Json project in your JSON folder using Visual Studio 2012
  4. Switch the build mode from Debug to Release
  5. Click Build, Rebuild Solution to build the JSON binaries we will link our APIMASH project to

STEP 2 - PULL DOWN THE KIT

  1. Browse to https://bit.ly/apimash
  2. Click on the .zip option and download the .zip to your hard drive
  3. Extract out all the contents to your hard drive into an APIMASH folder

CHECK APIMASH WORKS
In this step, we're going to make sure the APIMASH libs and sample GeoNames project work as they should.

  1. Open up the APIMASH_WikiPedia_StarterKit.sln solution file in Visual Studio 2012 from the directory you extracted APIMASH to
  2. Build => Rebuild All inside Visual Studio. You should get an error about the project not being able to find the JSON libraries
  3. Locate the APIMASHLib project in Visual Studio Solution Explorer
  4. Reference the Bin\WinRT\Newtonsoft.Json.dll library into the APIMASHLib project
  5. Change the build environment from Debug to Release
  6. Build=>Rebuild All to compile the project
  7. Run the application. It should work at this point

CREATE OUR OWN SHELL APP MARKUP
We're going to create a simple shell app as a starter for our very own custom app. Our goal is to eventually have this app call the GeoNames APIMASH library for us. It won't be a wonder of UI art, but it will be functional.

  1. Create a new Visual C# => Windows Store Application named "MyGeoNamesExplorer"
  2. Open up MainPage.xaml, modify the Grid and modify it to look like MainPage.xaml Grid Markup below

MainPage.xaml Grid Markup

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal">
<Button x:Name="Button_FullText" Grid.Row="0" FontSize="40" Height="80" Content="FullText"/>
<Button x:Name="Button_FindNearby" Grid.Row="0" FontSize="40" Height="80" Content="Find Nearby"/>
<Button x:Name="Button_BoundingBox" Grid.Row="0" FontSize="40" Height="80" Content="Bounding Box"/>
</StackPanel>
<TextBlock x:Name="TextBlock_Results" Grid.Row="1" Text="... results go here ..." FontSize="30"/>
</Grid>

CREATE STUB METHODS FOR OUR BUTTON HANDLERS

  1. In the Visual IDE, double-click on each button to setup a button handler.  The XAML will change and you will see a Click="Button_Name_Click" handler setup for each button, where "Name" is the button's x:Name
  2. Open MainPage.xaml.cs
  3. In Button_BoundingBox_Click, add the code "InvokeBoundingBox();"
  4. In Button_FindNearby_Click, add the code "InvokeFindNearby();"
  5. In Button_FullText_Click, add the code "InvokeFullText();"
  6. [right-mouse] on each InvokeXXX method. Click Generate=>Method Stub to create empty method stubs
  7. The code should now resemble the code in the MainPage.xaml.cs After Button Handlers block below.  We have buttons wired up, but nothing happens.  Now we begin integrating the APIMASH Library

MainPage.xaml.cs After Button Handlers

 private void Button_BoundingBox_Click(object sender, RoutedEventArgs e)
{
    InvokeBoundingBox();
}
private void Button_FindNearby_Click(object sender, RoutedEventArgs e)
{
    InvokeFindNearby();
}
private void Button_FullText_Click(object sender, RoutedEventArgs e)
{
    InvokeFullTextClick();
}
private void InvokeFullTextClick()
{
    throw new NotImplementedException();
}
private void InvokeBoundingBox()
{
    throw new NotImplementedException();
}
private void InvokeFindNearby()
{
    throw new NotImplementedException();
}

REFERENCE THE APIMASH GeoNames Libraries

  1. Open Solution Exploreer in Visual Studio
  2. [right-mouse] the MyGeoNamesExplorer project and click Add Reference
  3. Click Browse as we are going to have to navigate to our libraries
  4. Navigate in to the bin directory for the release mode of the GeoNames project we built earlier. For instance, on my machine it is C:\dev\apimash\APIMASH_WikiPedia_StarterKit\APIMASH_WikiPedia_StarterKit\bin\Release
  5. Add a reference to both APIMASH_WikiPediaLib.dll as well as APIMASHLib.dll. Use [ctrl+click] to select multiples. Click Add. Then click Ok .

ADD IN SOME HELPER FUNCTIONS
We're going to add a SearchResults property, an Invoker for the APIMASH search tasks, and a response handler that will work for all three of our GeoNames functions.

  1. Open up MainPage.xaml.cs
  2. Add the code shown below

Helper Functions

         APIMASH_WikiPediaLib.APIMASH_geonamesCollection m_SearchResults;
        APIMASH_WikiPediaLib.APIMASH_geonamesCollection SearchResults
        {
            get
            {
                if ( m_SearchResults==null)
                {
                    m_SearchResults = new APIMASH_WikiPediaLib.APIMASH_geonamesCollection();
                }
                return m_SearchResults;
            }
        }
        private APIMASHLib.APIMASHInvoke m_apimashInvoke;
        private APIMASHLib.APIMASHInvoke InvokeSearch
        {
            get
            {
                if (m_apimashInvoke == null)
                {
                    m_apimashInvoke = new APIMASHLib.APIMASHInvoke();
                    m_apimashInvoke.OnResponse += InvokeSearch_OnResponse;
                }
                return m_apimashInvoke;
            }
        }
        void InvokeSearch_OnResponse(object sender, APIMASHLib.APIMASHEvent e)
        {
            TextBlock_Results.Text = "";
            APIMASH_WikiPediaLib.APIMASH_OM _response = (APIMASH_WikiPediaLib.APIMASH_OM)e.Object;
            if ( e.Status == APIMASHLib.APIMASHStatus.SUCCESS )
            {
                SearchResults.Copy(_response);
                if ( _response.geonames == null )
                {
                    System.Diagnostics.Debug.WriteLine("ooops", "no results returned");
                    return;
                }

                System.Text.StringBuilder _sb = new System.Text.StringBuilder(1024);

                foreach ( APIMASH_WikiPediaLib.geoname _gn in _response.geonames )
                {
                    _sb.AppendLine( _gn.ToNearbyPlaceString() );
                }
                TextBlock_Results.Text = _sb.ToString();
            }
            else
            {
                System.Diagnostics.Debug.WriteLine( "ooops", e.Message );
            }
        }

WIRE UP THE GEONAMES CALLS

  1. Open up MainPage.xaml.cs
  2. Locate the InvokeXXX functions and mark them up to match the code below

Helper Functions

 private void InvokeFullTextClick()
{
    string _username = "YOUR GEONAMES ID GOES HERE";
    APIMASH_WikiPediaLib.geonamesHelpers.WikipediaSearchHelper _apihelper = new APIMASH_WikiPediaLib.geonamesHelpers.WikipediaSearchHelper(_username, "Tampa", 50);
    InvokeSearch.Invoke<APIMASH_WikiPediaLib.APIMASH_OM>(_apihelper.TargetURL);
}

private void InvokeFindNearby()
{
    string _username = "YOUR GEONAMES ID GOES HERE";
    APIMASH_WikiPediaLib.geonamesHelpers.FindNearbyWikipediaHelper _apihelper = new APIMASH_WikiPediaLib.geonamesHelpers.FindNearbyWikipediaHelper( 33702, "US", 10, _username );
    InvokeSearch.Invoke<APIMASH_WikiPediaLib.APIMASH_OM>(_apihelper.TargetURL);
}

private void InvokeBoundingBox()
{
    string _username = "YOUR GEONAMES ID GOES HERE";
    APIMASH_WikiPediaLib.geonamesHelpers.WikipediaBoundingBoxHelper _apihelper = new APIMASH_WikiPediaLib.geonamesHelpers.WikipediaBoundingBoxHelper(_username, 31, 30, -85, -84 );
    InvokeSearch.Invoke<APIMASH_WikiPediaLib.APIMASH_OM>(_apihelper.TargetURL);
}

TEST IT - Run the program, click the buttons. You should see output similar to the following. No, its not pretty, but we'll leave that and variable input as an exercise for the coder. Enjoy!

FullText FindNearby BoundingBox

Don't forget to check out the "Keep the Cash Rewards" offer to see how you can get $100 for publishing your app(s) in the Windows Store and/or Windows Phone Store. Publish your app before June 30, 2013 and you can get a $100 virtual Visa card for every qualified app you enter (up to $2000). Learn more at https://blogs.msdn.com/b/devfish/archive/2013/05/13/keepthecash-for-win8-or-winphone-apps-until-june-30.aspx

If you have questions on this API, or looking for some other enhancements to the GeoNames Wikipedia starter kit, feel free to post up some comments. Enjoy!

RESOURCES: