How to implement the SongKick service to display an artist’s concert calendar


By Andrej Radinger

Welcome! This article will be about creating a Universal Windows app that displays artists and concerts of the user’s preference using the Songkick service.
This article will show you all required aspects of Universal App creation using App Studio, following these steps:

1. Create the Universal app using App Studio – create all required pages, layouts and app environment
2. Download the App Studio generated source code
3. Modify App Studio generated code in Visual Studio and Integrate with Songkick API
4. Finalize the app and generate publish packages

Before we start – if you are new to App Studio, I suggest you study the great beginners guide to App Studio here.

Create the Universal app using App Studio – create all required pages, layouts and app environment

 

Let’s start by creating a project in App Studio. Go to http://appstudio.windows.com  and login with your Microsoft Account. Click on “Start New Project”. From the list of Templates select “Empty Template”.


 
This will start a new template for Universal App. Once selected, a new, empty Universal App is created.
Let’s start creating an app structure. We want our application to have pages for:

- Artists – list of selected artists for the logged user
- Concerts – list of selected concerts for the logged user
- Songkick Facebook – posts from official Songkick Facebook page

In App Studio we will add two “Collection” sections from advanced sections and “Facebook” from Basic sections.


 

When selecting any section element, you will be presented with the choices to make. For Collections, you will be asked to choose:

- Section Name
- Data Configuration – it can be static (static data in the app) or dynamic (data in the cloud)

For more information on data options and selections, please refer to the Beginners guide, mentioned earlier.


 
For our Songkick app it is not important, since we will be adding to a Songkick API later in Visual Studio and retrieve data from there. For now, select “Dynamic resources”, name section “Concerts” and create the following data fields:

Name

ColumnType

Date

Text

Picture

Image

Name

Text

Location

Text

After we defined the data source, let’s bind fields from data source to page elements. Click on the “Pages” tab to switch from data source to page design. We will have 2 pages for both, concerts and artists (we’ll add artists later) – one page for list of all concerts / artists and another one to show details for selected item.


 
Select “List page”, and desired layout. Now, let’s make bindings.


 
Next, select the “Detail page” and bind page fields to appropriate data source columns


 

Make sure to click the “SAVE” button after you made your selections.
Next, repeat the above steps for Artists. Data source should have the following structure:

Name

ColumnType

Picture

Image

Name

Text

Description

multiline

The Last page we want to add for this demo application is Facebook page, from Basic section. On adding the Facebook page, you will be prompted to give it a name and Facebook page link


 
Bindings will be added automatically for you.
Now, all required pages are added. We just want to add the “App title“and app logo. The Final layout looks like the following:


 

Next, we need to adjust application environment, based on your preferences. Select “Themes” tab to adjust app colours and Styles.


 
Next, select Tiles – template and images, as well as text, and Splash & Lock screen images – for both WP8.1 and Windows 8.1


 

Download the App Studio generated source code

We are now ready to finalize the base app creation in App Studio. Press Finish to go to finalize screen. From there, you can press the “Generate” button to create publishing packages for stores. But our application is not finished yet, so we just need an auto-generated source code to continue working on the app in Visual Studio. So press “Download Source Code” button and then the hyperlink “Visual Studio 2013 Universal Project you will need update 2” to download the source code.


 
Your App Studio generated source code will be downloaded as a single zip file. Download it, unzip it and open the solution in Visual Studio 2013. Make sure you have Visual Studio 2013 Update 2 or later installed

Modify App Studio generated code in Visual Studio and Integrate with Songkick API

Before we dig into Visual Studio, let’s review Songkick API integration requirements.

1. API documentation is here.
2. From the above link, you will also need to apply for an API key. You will need it to access SongKick services from the 3rd party app


3. Read API terms of use to make sure you comply with SongKick policies.
4. Integrate SongKick API in App Studio generated solution (keep reading to see how)

When you open App Studio generated solution in Visual Studio 2013, it looks like a regular VS 2013 Universal Application, with some additional stuff.


 

Additional staff is what we actually need to alter to integrate with SongKick API:
- Songkick.Data project (at the bottom)
- SongkickAPI – added manually to reference required objects (artists and concerts)

Solution also contains AppStudio.Common.dll, which is not a regular part of the Universal App, but is required for App Studio apps.
NOTE: SongKick.Data project in this sample is originally named AppStudio.Data, when using unchanged App Studio generated solution for the first time

Apps created with App Studio are already well structured, “by the book” – shared project, data bindings, view models, views, etc, so there are very little changes we need to make to integrate with SongKick API to replace our generated data source. Classes we need to make changes to, are located in SongKick.Data project, in DataSources folder: ArtistsDataSources.cs, ConcertsDataSource.cs and in DataProviders folder: ServiceDataProvider.cs.   We also need to add two new classes that we put in SongKickAPI: Artist.cs, Concerts.cs.


 

ArtistsDataSource.cs

In this class, we will make a reference to Songkick API. You need to replace existing Task method with the following two overloaded methods:
        public async override Task<IEnumerable<ArtistsSchema>> LoadDataAsync(string username)
        {
            try
            {
                string url = string.Format("http://api.songkick.com/api/3.0/users/{0}/artists/tracked.json?apikey={1}", username, ServiceDataProvider.SONGKICK_API_KEY);
                Uri uri = new Uri(url, UriKind.Absolute);
                var serviceDataProvider = new ServiceDataProvider(uri);

                ArtistsRootObject root = await serviceDataProvider.LoadJSON<ArtistsRootObject>();

                List<ArtistsSchema> artists = new List<ArtistsSchema>();
                foreach (var item in root.resultsPage.results.artist)
                {
                    ArtistsSchema artist = new ArtistsSchema();

                    artist.Id = item.id.ToString();
                    artist.Name = item.displayName;
                    //artist.Description = item.uri;

                    string imageUrl = string.Format("https://assets.sk-static.com/images/media/profile_images/artists/{0}/huge_avatar", item.id);
                    //if (await CheckUrlExistence(imageUrl))
                    //{
                        artist.Picture = imageUrl;
                    //}
                    //else
                    //{
                    //    artist.Picture = "/Assets/FlipSquareTile.jpg";
                    //}

                    artists.Add(artist);
                }

                return artists;
            }
            catch (Exception ex)
            {
                AppLogs.WriteError("ArtistsDataSource.LoadData", ex.ToString());
                return new ArtistsSchema[0];
            }
        }

        public override Task<IEnumerable<ArtistsSchema>> LoadDataAsync()
        {
            return null;
        }

ConcertsDataSource.cs

In this class, we will make a reference to Songkick API. You need to replace existing Task method with the following two overloaded methods:
        public async override Task<IEnumerable<ConcertsSchema>> LoadDataAsync(string username)
        {
            try
            {
                string url = string.Format("http://api.songkick.com/api/3.0/users/{0}/gigography.json?reason=tracked_artist&apikey={1}", username, ServiceDataProvider.SONGKICK_API_KEY);
                Uri uri = new Uri(url, UriKind.Absolute);
                var serviceDataProvider = new ServiceDataProvider(uri);

                ConcertsRootObject root = await serviceDataProvider.LoadJSON<ConcertsRootObject>();

                List<ConcertsSchema> concerts = new List<ConcertsSchema>();
                foreach (var item in root.resultsPage.results.events)
                {
                    ConcertsSchema concert = new ConcertsSchema();

                    concert.Id = item.id.ToString();
                    concert.Name = item.displayName;
                    concert.Location = item.location.city;
                    concert.Picture = string.Format("http://www1.sk-static.com/images/media/profile_images/artists/{0}/huge_avatar", item.performance.FirstOrDefault().artist.id);

                    try
                    {
                        string date = DateTime.Parse(item.start.datetime).ToString("g", CultureInfo.CurrentUICulture);
                        concert.Date = date;
                    }
                    catch (Exception)
                    {
                        concert.Date = "no date or time";
                    }

                    concerts.Add(concert);
                }

                return concerts;
            }
            catch (Exception ex)
            {
                AppLogs.WriteError("ConcertsDataSource.LoadData", ex.ToString());
                return null;
            }
        }

        public override Task<IEnumerable<ConcertsSchema>> LoadDataAsync()
        {
            return null;
        }

ServiceDataProvider.cs

You need to make the following changes in this class:
1. Create object that will hold the SonkKick API key (used in classes created previously)
        public const string SONGKICK_API_KEY = "key_received_from_Songkick";

2. Add the following overloaded Task method:
        public async Task<T> LoadJSON<T>()
        {
            try
            {
                string data = await DownloadAsync(_uri);
                T record = JsonConvert.DeserializeObject<T>(data);
                return record;
            }
            catch (Exception ex)
            {
                AppLogs.WriteError("ServiceDataProvider.Load", ex);
                return default(T);
            }
        }

Artists.cs
Create the following class in SongkickAPI folder (which you need to create yourself). This class will be used to hold collection of artists returned by the API call.
using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Songkick.Data.SongkickAPI
{
    public class Artist
    {
        public List<object> identifier { get; set; }
        public string onTourUntil { get; set; }
        public string uri { get; set; }
        public int id { get; set; }
        public string displayName { get; set; }
    }

    public class ArtistResults
    {
        public List<Artist> artist { get; set; }
    }

    public class ArtistResultsPage
    {
        public string status { get; set; }
        public ArtistResults results { get; set; }
        public int perPage { get; set; }
        public int page { get; set; }
        public int totalEntries { get; set; }
    }

    public class ArtistsRootObject
    {
        public ArtistResultsPage resultsPage { get; set; }
    }
}

Concerts.cs
Create the following class in SongkickAPI folder (which you need to create yourself). This class will be used to hold collection of concerts returned by the API call.
using Newtonsoft.Json;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Songkick.Data.SongkickAPI
{
    public class Start
    {
        public string time { get; set; }
        public string date { get; set; }
        public string datetime { get; set; }
    }

    public class Identifier
    {
        public string href { get; set; }
        public string mbid { get; set; }
    }

    public class Performance
    {
        public string billing { get; set; }
        public int billingIndex { get; set; }
        public int id { get; set; }
        public Artist artist { get; set; }
        public string displayName { get; set; }
    }

    public class ConcertCountry
    {
        public string displayName { get; set; }
    }

    public class ConcertMetroArea
    {
        public ConcertCountry country { get; set; }
        public string uri { get; set; }
        public int id { get; set; }
        public string displayName { get; set; }
    }

    public class ConcertVenue
    {
        public object lat { get; set; }
        public ConcertMetroArea metroArea { get; set; }
        public object lng { get; set; }
        public string uri { get; set; }
        public int id { get; set; }
        public string displayName { get; set; }
    }

    public class ConcertLocation
    {
        public string city { get; set; }
        public double lat { get; set; }
        public double lng { get; set; }
    }

    public class ConcertEvent
    {
        public string type { get; set; }
        public object ageRestriction { get; set; }
        public string status { get; set; }
        public Start start { get; set; }
        public List<Performance> performance { get; set; }
        public ConcertVenue venue { get; set; }
        public ConcertLocation location { get; set; }
        public string uri { get; set; }
        public double popularity { get; set; }
        public int id { get; set; }
        public string displayName { get; set; }
    }

    public class ConcertsResults
    {
        [JsonProperty("event")]
        public List<ConcertEvent> events { get; set; }
    }

    public class ConcertsResultsPage
    {
        public string status { get; set; }
        public ConcertsResults results { get; set; }
        public int perPage { get; set; }
        public int page { get; set; }
        public int totalEntries { get; set; }
    }

    public class ConcertsRootObject
    {
        public ConcertsResultsPage resultsPage { get; set; }
    }
}

That is it. We added basic set of functionality from Songkick API to retrieve and present artists and concerts. As required, you can add additional functionality and search. If necessary, fix missing or broken references – refresh them or install using Nuget.

Finalize the app and generate publish packages

You are now ready to build and publish your applications.

Final solution described in this document can be found and downloaded here.

songkick_logo.jpg


Skip to main content