0 Comments

Image with red dots - intended to look fancy

Some apps require quite a bit of content which is fairly static but changes over time and then the app should adjust and provide the user with the new content. Let's assume we want an app that provides us with quotes and their authors. We could just add the quotes to our app but whenever we wanted to update the app we would have to redeploy our app to the store(s). This can range from an inconvenience to requiring technical expertise for updating the app for simply correcting such a simple thing as a comma. So it becomes evident that in these cases we would like to separate the content from the app itself.

Hosting content does not require running any logic on the server. We do not need any other service than that of a simple file share. With perhaps one or two additional requirements regarding security etc. but more on that later. And that is exactly what Azure Blob Storage can provide us with.

Setting up the blob storage

You are required to have an Azure Account to create a blob storage, the steps, therefore, you can find here. On Azure create a blob storage, under containers, create a Container if you haven't done so already and then upload your data to it. In this sample, we will upload a single JSON file.

Showing Blobstorage Container with one JSON File

In a real application, we could also provide multiple other files including videos and other static files. But for this simple demo, we will stick to a lonely JSON file. We can access the content by calling the URL:

Sample get request with Postman

Having something on a public server always raises questions about security and the sorts. So let's have a look at them.

Security

So let's start with what you get out of the box. The easiest security is if your data is public. Like on a website but for your app. The default you can limit the anonymous access to your blob storage as follows:

  • read-only container: which will allow everyone to read at the container level i.e. "look at the directory" and list all the blobs within.
  • read-only blob: here the caller will have to know which blob he wants to open and is limited to reading the blob storage itself.
  • no read access for anonymous: this will restrict the access to authenticated parties only.

In our sample, we will stick with anonymous blob access. But if you are interested in adding some extra layers of security be sure to check out the Azure Storage security guide which explains the different methods of authentication from shared keys all the way to using Azure Active Directory (Azure AD) for securing the access of your data. Which in summary means Blob Storage is not only quick and convenient in the beginning but can also be modified to add some serious layers of protection.

The client

AppInAction

On the client, we will want to consume the hosted resource and use it in our app. You can do this rather simply within a .Net Standard library using JSON.Net as follows:

string quotesJson;
using (var httpClient = new HttpClient())
{
    var response = await httpClient.GetAsync("https://gnabberonlinestorage.blob.core.windows.net/alpha/quotes.json");
    quotesJson = await response.Content.ReadAsStringAsync();
}
_quotes = JsonConvert.DeserializeObject<List<QuoteInfo>>(quotesJson);

While the above sample works and will get us our data it is not really smart, it will always pull the entire file even if nothing has changed. Fortunately, Azure Blob Storage supports ETags which allows us to be smarter when creating the call, by adding the If-None-Match header to our request as follows:

public async Task Init()
{
    if (_quote != null) return;

    IsBusy = true;
    string quotesJson;
    using (var httpClient = new HttpClient())
    {
        if(!string.IsNullOrEmpty(CurrentEtagVersion)) httpClient.DefaultRequestHeaders.Add("If-None-Match", CurrentEtagVersion);
        var response = await httpClient.GetAsync("https://gnabberonlinestorage.blob.core.windows.net/alpha/quotes.json");

        quotesJson = response.StatusCode == HttpStatusCode.NotModified
            ? ReadQuotesFromCache()
            : await response.Content.ReadAsStringAsync();

        UpdateLocalCache(response.Headers.ETag, quotesJson);
    }
    _quotes = JsonConvert.DeserializeObject<List<QuoteInfo>>(quotesJson);

    PickAndSetQuote();
    IsBusy = false;
}

If the local and remote ETag match, we will not receive any data with the call leaving us with a very small data footprint for this call. The code handling the caching is shown below. Note that for accessing the preferences Xamarin.Essentials were used:

public string CurrentEtagVersion => Preferences.Get(EtagKey, string.Empty);

private void UpdateLocalCache(EntityTagHeaderValue eTag, string quotesJson)
{
    // Only update the cache if we need to
    if (eTag == null || CurrentEtagVersion == eTag.Tag) return;
    Preferences.Set(EtagKey, eTag.Tag);
    File.WriteAllText(_quotesFilename, quotesJson);
}

private string ReadQuotesFromCache()
{
    if (!File.Exists(_quotesFilename)) return string.Empty;
    return File.ReadAllText(_quotesFilename);
}

I will leave it there with this sample but since we are already storing the data in a local cache we could also consider making this app fully Offline capable. With Xamarin Essentials, which we are already using, we can check if we have a network connection and what kind of connection. This information allows us to decide if we want/can access the remote storage or rather load the data from the initial cache.

You can find the entire client sample code on GitHub.

Conclusion

In this post, we saw how you can use Azure Blob storage as a backend service to host the content of your app without having to implement any web server. You can add security layers to the storage. Tracking changes on the backend are provided out of the box via HTTP ETags.

But how much will this cost me? Probably less than you would think but check out the Blob Storage pricing to get your exact number.

0 Comments

When working with a mobile app you will often work with a backend, which if you are working with C# might very probably be a Web API backend. In this blog we will look at how we can consume and write to a Web API Controller that we can host on Azure. Why Azure? Because it is the easiest way of hosting a web service straight out of Visual Studio and if you happen to have a MSDN subscription you can do this all for free. For the client we will be using a Windows 10 Universal App which allows us to write a client for Desktop, Tablet and Phone.

The app we will be building will add the capability to read a list of people from a service and add a person to the existing. So we will see how we can read and write to a HTTP service.

The client

As a client we will be targeting Windows Phone (soon to be Windows Mobile again), Android and iOS. Our implementation of integrating with the backend we will perform in the Portable Class Library (PCL) which provides us the unique advantage of only having to write our backend service integration once.

PCL integration

In the PCL we will require the following NuGet packages:

Armed with the capabilities of now being able to communicate to a HTTP backend and serializing i.e. deserializing objects to and from JSON we can start implementing our communication layer by creating a HTTP client in the constructor. We usually only need one instance of the HTTP client as it will handle multiple requests and only spawn as many active connections as are reasonable over HTTP:

public class PersonService : IPersonService
{
    private HttpClient _httpClient;

    public PersonService()
    {
        _httpClient = new HttpClient();
    }

    // ... Person Service implementation
}

For reading over HTTP we should use the GET keyword which is provided by the HTTP client and is implemented as follows:

public async Task<IEnumerable<Person>> GetPeople()
{
    var result = await _httpClient.GetAsync(BASE_URI);
    var peopleJson = await result.Content.ReadAsStringAsync();

    return JsonConvert.DeserializeObject<IEnumerable<Person>>(peopleJson);
}

Note that if you are using a free website on Azure you can choose to run communications over SSL, the only thing you have to change for this is adding an s in the URI after http i.e. resulting in an https URI.

Writing to a HTTP service depends on the action we want to perform. Creating something new e.g. adding a new person to the existing person list, should be performed over a HTTP POST.  Implementing the post can be done as follows:

public async Task<bool> CreatePerson(Person person)
{
    var personJson = JsonConvert.SerializeObject(person);
    var content = new StringContent(personJson, Encoding.UTF8, "application/json");
    var result = await _httpClient.PostAsync(BASE_URI, content);

    return result.IsSuccessStatusCode;
}

The StringContent method has additional parameters to indicate to the server how the content can be interpreted. This is required to inform the backend service that the data we are sending is serialized as JSON. Not doing so would end in false information in the header which would prevent Web API to automatically deserialize the body.

Updating an existing person usually is done via PUT, which is similar to the CreatePerson method but contains an ID in the URI which usually corresponds with the ID from the Person which is set on the backend.

public async Task<bool> UpdatePerson(int id, Person person)
{
    var uri = Path.Combine(BASE_URI, id.ToString());

    var personJson = JsonConvert.SerializeObject(person);
    var content = new StringContent(personJson, Encoding.UTF8, "application/json");

    var result = await _httpClient.PutAsync(uri, content);

    return result.IsSuccessStatusCode;
}

As you can see implementing a Web service is quite straight forward with the HTTP Client and allows to easily create a backend integration for native clients that can be shared across platforms.

The UI

On the client side we now can invoke our portable service and display a list of people.

<Page
    x:Class="HttpClientSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:HttpClientSample"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    DataContext="{Binding Main, Source={StaticResource Locator}}"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <GridView ItemsSource="{Binding People}" SelectedItem="{Binding SelectedPerson, Mode=TwoWay}"></GridView>

        <AppBar VerticalAlignment="Bottom">
            <AppBarButton Icon="Add" Label="Add" Command="{Binding AddNewPerson}" />
        </AppBar>
    </Grid>
</Page>

In the ViewModel we can invoke the backend service to provide the data.

public class MainViewModel:ViewModelBase
{
    private readonly IPersonService _personService;
    private ObservableCollection<Person> _people;
    private Person _selectedPerson;

    public MainViewModel(IPersonService personService)
    {
        if (personService == null) throw new ArgumentNullException(nameof(personService));
        _personService = personService;
        _people = new ObservableCollection<Person>();
        ShowPerson = person => { };
        AddNewPerson = new RelayCommand(() => ShowPerson(0));
    }

    public ObservableCollection<Person> People => _people;
    public Action<int> ShowPerson { get; set; }

    public Person SelectedPerson
    {
        get { return _selectedPerson; }
        set
        {
            if (_selectedPerson == value) return;
            _selectedPerson = value;
            RaisePropertyChanged(nameof(SelectedPerson));
            if (_selectedPerson != null) ShowPerson(_people.IndexOf(_selectedPerson));
        }
    }

    public ICommand AddNewPerson { get; private set; }

    public async Task Init()
    {
        var people = await _personService.GetPeople();

        _people.Clear();

        foreach (var person in people)
        {
            _people.Add(person);
        }
    }
}

Adding a person means we have to add a further page to our client application that provides us with a form to enter the name and first name of a person. To keep things simple we will just use the same UI and identify via the navigation parameter if we have to create or update the person on the backend.

<Page
    x:Class="HttpClientSample.PersonDetail"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:HttpClientSample"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    DataContext="{Binding Person, Source={StaticResource Locator}}"
    Loaded="PersonDetail_OnLoaded"
    mc:Ignorable="d">

    <StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <TextBox Header="Firstname" Text="{Binding Firstname, Mode=TwoWay}"/>
        <TextBox Header="Lastname" Text="{Binding Lastname, Mode=TwoWay}"/>
        <Button Content="Save" Command="{Binding StoreCommand, Mode=TwoWay}" IsEnabled="{Binding HasPendingChanges}" HorizontalAlignment="Center" Margin="0,10"/>
    </StackPanel>
</Page>

The ViewModel is handling the integration with the PersonService from the PCL library:

public class PersonViewModel:ViewModelBase
{
    private readonly IPersonService _personService;
    private int _id;
    private string _firstname;
    private string _lastname;
    private bool _hasPendingChanges;

    public PersonViewModel(IPersonService personService)
    {
        if (personService == null) throw new ArgumentNullException(nameof(personService));
        _personService = personService;

        StoreCommand = new RelayCommand(StorePerson, () => true);
        HasPendingChanges = false;
    }

    public bool HasPendingChanges
    {
        get { return _hasPendingChanges; }
        set
        {
            if (value == _hasPendingChanges) return;
            _hasPendingChanges = value;
            RaisePropertyChanged(nameof(HasPendingChanges));
        }
    }

    public string Firstname
    {
        get { return _firstname; }
        set
        {
            if (value == _firstname) return;
            _firstname = value;
            HasPendingChanges = true;
            RaisePropertyChanged(nameof(Firstname));
        }
    }

    public string Lastname
    {
        get { return _lastname; }
        set
        {
            if (_lastname == value) return;
            _lastname = value;
            HasPendingChanges = true;
            RaisePropertyChanged(nameof(Lastname));
        }
    }

    public ICommand StoreCommand { get; set; }

    public async Task Init(int id)
    {
        _id = id;
        var person = id > 0 ? (await _personService.GetPeople()).ToList()[id] : new Person("", "");
        Firstname = person.FirstName;
        Lastname = person.LastName;
        HasPendingChanges = false;
    }

    private async void StorePerson()
    {
        HasPendingChanges = false;

        var person = new Person(Firstname, Lastname);

        if (_id > 0)
        {
            await _personService.UpdatePerson(_id, person);
        }
        else
        {
            await _personService.CreatePerson(person);
        }

        HasPendingChanges = false;
    }
}

Again integrating a PCL library is not difficult and requires no additional hoops to jump through. What we gain by putting our logic into the PCL is that we can reuse the code across multiple platforms.

The Controller

We will focus on the client part during this post but for getting an understanding of the bigger picture here is the controller we will be communicating with.

public class PersonController : ApiController
{
    private readonly static Lazy<IList<Person>> _people = new Lazy<IList<Person>>(() => new PersonService().GeneratePeople(1000), LazyThreadSafetyMode.PublicationOnly);
    // GET: api/Person
    public IEnumerable<Person> Get()
    {
        return _people.Value;
    }

    // GET: api/Person/5
    public Person Get(int id)
    {
        if (id < 0 || _people.Value.Count < id) return null;
        return _people.Value[id];
    }

    // POST: api/Person
    [HttpPost]
    public IHttpActionResult Post(Person value)
    {
        if (value == null) return BadRequest();

        _people.Value.Add(value);

        return CreatedAtRoute("DefaultApi", new { id = _people.Value.IndexOf(value) }, _people.Value.Last());
    }

    // PUT: api/Person/5
    [HttpPut]
    public IHttpActionResult Put(int id, [FromBody]Person value)
    {
        if (id < 0 || id >= _people.Value.Count()) return BadRequest();

        _people.Value[id] = value;

        return Ok(value);
    }

    // DELETE: api/Person/5
    public IHttpActionResult Delete(int id)
    {
        if (id < 0 || id >= _people.Value.Count()) return BadRequest();

        _people.Value.RemoveAt(id);

        return StatusCode(System.Net.HttpStatusCode.NoContent);
    }
}

internal class PersonService
{
    public IList<Person> GeneratePeople(int count)
    {
        var firstNames = new List<string>(count);
        var lastNames = new List<string>(count);

        for (int i = 0; i < count; ++i)
        {
            firstNames.Add(NameGenerator.GenRandomFirstName());
            lastNames.Add(NameGenerator.GenRandomLastName());
        }

        return firstNames.Zip(lastNames, (firstName, lastName) => new Person(firstName, lastName)).ToList();
    }
}

As you can see it is rather basic and through the static variable we have some sort of poor mans database. Do not use this way of storing data in a production environment!

Conclusion

In this post we saw how we can integrate a ASP.Net Web API server in a PCL. Thereby seeing how to read and write objects to a web service. Further we saw how we can display and enter the data on a Windows 10 client. The entire sample could have been written for Xamarin.iOS, Xamarin.Android or WPF which is exactly the sweet spot of writing your business logic in the PCL it does not matter what client you are intending to write now or in the future as long as the PCL allows you to integrate multiple client platforms.

You can find the entire sample project on NuGet.

0 Comments

In this post I want to look at how to create a Web API project with F# and host it on Azure. This will part of a blog series on how to create a mobile application (incl. the backend) based on F#. The blog post assumes that you the reader has a basic understanding of how to create a Web API web service.

F# is a functional programming language based on the .Net Framework which contrary to many other functional programming languages also makes it a general purpose language. In my endeavor to explore a functional programming language I chose F# as it will allow me to create not only .Net applications but also Xamarin based cross platform apps.

To deploy to Azure you will need a valid Azure account. Alternatively you can run the App on your local machine.

Setting up the project

I’ll be using Visual Studio 2015 RC for this setup but you can follow along on VS 2013 just as well. Create a new project then go to Online projects, Select Visual F# and then select F# MVC 5. This only has to be done during the first setup. From now on you will find the project template under the Installedproject templates.

NewProjectFromOnlineTemplate

Having a look at the solution

If you are familiar with a Web API solution you will find yourself right at home.

WebApiSolution

Under Controllers you find the expected definitions, as well as under models. The Global.asax.fs also has a familiar ring to it:

namespace FSharpWebSample

open System
open System.Net.Http
open System.Web
open System.Web.Http
open System.Web.Routing

type HttpRoute = {
    controller : string
    id : RouteParameter }

type Global() =
    inherit System.Web.HttpApplication() 

    static member RegisterWebApi(config: HttpConfiguration) =
        // Configure routing
        config.MapHttpAttributeRoutes()
        config.Routes.MapHttpRoute(
            "DefaultApi", // Route name
            "api/{controller}/{id}", // URL with parameters
            { controller = "{controller}"; id = RouteParameter.Optional } // Parameter defaults
        ) |> ignore

        // Configure serialization
        config.Formatters.XmlFormatter.UseXmlSerializer <- true
        config.Formatters.JsonFormatter.SerializerSettings.ContractResolver <- Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()

        // Additional Web API settings

    member x.Application_Start() =
        GlobalConfiguration.Configure(Action<_> Global.RegisterWebApi)

Extending the Controller

When we look at the controller we see that an array of the model is created and there is on method that will return the list. Let’s extend the controller to return a value requested by it’s Id. So first we have to extend the model Car.fs:

namespace FSharpWebSample.Models

open Newtonsoft.Json

[<CLIMutable>]
type Car = {
    Make : string
    Model : string
    Id : int
}

Now we can extend the CarsController.fs so that we can filter the list and get the according value:

namespace FSharpWebSample.Controllers
open System
open System.Collections.Generic
open System.Linq
open System.Net.Http
open System.Web.Http
open FSharpWebSample.Models

/// Retrieves values.
type CarsController() =
    inherit ApiController()
    
    let values = [ { Make = "Ford"; Model = "Mustang"; Id = 1 }; { Make = "Nissan"; Model = "Titan"; Id = 2 }; { Make = "Audi"; Model = "R8"; Id = 3 } ]
    
    /// Gets all values.
    member x.Get() = values
    
    member x.Get(id:int) = values |> List.filter(fun v -> v.Id = id)

Deploying to Azure

Deploying to azure luckily is luckely the same as it always has been for C#, right click onto the Web API project, select Publish…, Microsoft Azure Web Apps then create a new web app enter a name and finally click on Pubish. Now all that is left is to test the web service so lets do this the manual way.

Testing the controller

Opening the prefered browser of your choice e.g. the new Edge browser enter the path to the azure website and be executing the following URI:

http://fsharpwebsample.azurewebsites.net/api/cars

We receive the entire list:

[{"make":"Ford","model":"Mustang","id":1},{"make":"Nissan","model":"Titan","id":2},{"make":"Audi","model":"R8","id":3}]

When we add a Id parameter:

http://fsharpwebsample.azurewebsites.net/api/cars/3

We only receive the requested record:

[{"make":"Audi","model":"R8","id":3}]

Conclusion

Creating a Web API service with F# is not much different than creating it with C# thanks to Ryan Riley and Daniel Mohl who provide the F# MVC 5 template. Also uploading it to Azure and sending requests are the way one would expect the service to run. Looking forward to go on further down the F# rabbit hole.

You can find the sample on GitHub.

0 Comments

RESTXamarintTitleLogo

Lets have a look at how we can consume a REST based web service in a Xamarin.Forms application. In this blog post we will look at how an ASP.Net WebAPI service that is hosted on Azure and how it can be consumed in the Portable Class Library (PCL) of your Xamarin.Forms application and write a small UI to interact with the REST service. Please note that I used Visual Studio 2013 while creating the example for this project.

 

Creating the backend

An ASP.Net WebAPI can be considered as a headless website, so many of the concepts of ASP.Net MVC apply but we will not be writing any HTML, JavaScript and CSS code for displaying the data as it will simply provide the data through the controller. Per default the controller can return the data serialized to JSON or XML. For this example I have created two controllers, one will just simply return a string and return it as the content of the HTTP package:

public class BasicController : ApiController
{
// GET: api/Basic/5
public string Get(int id)
{
return string.Format("You entered: {0}", id);
}
}

The second one will return a serialized object to the caller. The default settings will request the data to be serialized with JSON but we will come to that later on. The second controller looks as follows:

public class ObjectController : ApiController
{
// GET: api/Object/5
public NumberWrapper Get(int id)
{
return new NumberWrapper{WrappedNumber = string.Format("You entered: {0}", id)};
}
}

And the Plain Old CLR Object (POCO) which is used you can see here:

public class NumberWrapper
{
public string WrappedNumber { get; set; }
}

So all pretty straight forward, now lets look at how we can consume the service once it is running.

Note: You can publish this webservice on Azure which makes it really easy to access it from phones and other Virtual Machines (VMs) as you will not be hassled with firewall settings and therefore can focus at the task at hand.

 

Consuming a REST service in the PCL

For consuming the REST service we will need to install the WebHttpClient NuGet package from Microsoft. So lets open up the package manager by right-clicking on the solution and then searching for WebHttpClient, add the NuGet package to the PCL, Android, iOS and Windows Phone Project. For deserializing the JSON we will use the JSON.Net library from James Newton-King, so search once more for JSON.Net and install it again for all the client projects.

The communication with the backend is created in HttpWrapper.cs, the BasicController simply the Content of the result is read and passed back:

public async Task<string> GetBasicDataAsync(int i)
{
var uri = string.Format("https://xamarinwebapiservice.azurewebsites.net/api/basic/{0}", i);

var result = await _httpClient.GetAsync(uri);

return await result.Content.ReadAsStringAsync();
}

When we call the ObjectController we receive the JSON in the Content of the result and have to deserialize it first:

public async Task<NumberWrapper> GetNumberWrapperDataAsync(int i)
{
var uri = string.Format("{0}object/{1}", BaseUrl, i);

var result = await _httpClient.GetAsync(uri);

var jsonNumberWRapper = await result.Content.ReadAsStringAsync();

return JsonConvert.DeserializeObject<NumberWrapper>(jsonNumberWRapper);
}

So far so good now lets create a small UI to Consume the service and its controllers.

 

The client UI

I’ll be using MVVM Light in the UI for the data binding, on a former post you can find an introduction on how to get started with MVVM Light. The UI lets you pick a number and you can choose the call by selecting the according button:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="WebApiXamarinForms.View.MainPage">
<StackLayout>
<Picker SelectedIndex="{Binding SelectedNumberIndex}" HorizontalOptions="CenterAndExpand" Title="Numbers">
<Picker.Items>
<x:String>1</x:String>
<x:String>2</x:String>
<x:String>3</x:String>
<x:String>4</x:String>
<x:String>5</x:String>
<x:String>6</x:String>
<x:String>7</x:String>
<x:String>8</x:String>
<x:String>9</x:String>
<x:String>10</x:String>
</Picker.Items>
</Picker>
<Button Text="Basic Submit" Command="{Binding BasicSubmitCommand}" HorizontalOptions="CenterAndExpand"></Button>
<Button Text="Object Submit" Command="{Binding ObjectSubmitCommand}" HorizontalOptions="CenterAndExpand"></Button>
<ActivityIndicator IsRunning="{Binding CallingService}"></ActivityIndicator>
<Label Text="{Binding Response}" VerticalOptions="Center" HorizontalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>

Note that the Picker control does not yet support data binding so this is currently the only way how you can set the values.

In the MainViewModel.cs the calls to the service are made during the command invokes and the result is written accordingly to the UI. Here the BasicSubmitCommand:

private async void GetBasicResponseAsync()
{
CanGetBasicResponse = false;
CallingService = true;

Response = await _webService.GetBasicDataAsync(_numbers[SelectedNumberIndex]);

CallingService = false;
CanGetBasicResponse = true;
}

And the ObjectSubmitCommand:

private async void GetObjectResponseAsync()
{
CanGetBasicResponse = false;
CallingService = true;

var numberWrapper = await _webService.GetNumberWrapperDataAsync(_numbers[SelectedNumberIndex]);
Response = numberWrapper.WrappedNumber;

CallingService = false;
CanGetBasicResponse = true;
}

Conclusion

In this blog post we took a quick look at how a WebAPI controller is setup. Further we looked at how HTTP calls are created on the Xamarin.Forms client and how responses can be parsed and used within a program. We also saw how we can consume objects that are received as JSON strings from a web service.

You can find the entire source code on GitHub.

0 Comments

ApplePushOverview

Lets have a look on how we can enable a Xamarin.iOS i.e. Xamarin.Forms app to receive push notifications. I’m using the Azure Notification Hub on the backend which simplifies the integration of the push services on the backend.

Requirements

To implement push notifications on iOS you will need to have:

  1. An apple developer account
  2. An iOS device
  3. An Apple computer you can access
  4. A valid Azure Account

You will need an iOS Device as push notifications can not be tested in the simulator.

Further this blog post will assume that you are using Visual Studio as a development environment.

Setting up the backend

On the backend we will have to do the following steps:

  1. Generate a certificate
  2. Registering your app for push notifications
  3. Configuring the notification portal on Azure

Generating the certificate

For sending push notifications with an apple device we will need to have a Push certificate. The certificate is generated with the Keychain Access tool.

On OSX you can search all the programs by using the finder which you can find at the top right and has the symbol of a magnifying glass.

GenerateCertificate

Select Keychain Access, Certificate Assistantand then Request a Certificate From a Certificate Authority

CertificateDetails

Enter your user Email and common name. And ensure you select save to disk. After selecting continue make give your cert a good name and save it to the desktop.

Registering your app for push notifications

Login to the Apple developer portal, go to the App IDs, select your app and click onto Edit.Create certificate

Select Create Certificate… (for now lets choose the Development SSL Certificate,click onto Continue and under Choose File… select and upload the previously generated certificate.

ConfigurePushNotificaiton

Final step download the generate certificate and double click to import it to your keychain. For Azure we will need to export the cert into a p12 file. So open up Keychain Access. Under Keychainsselect login, then under Category select Keys, now find the Pushcertifiacte (expand it and export the private key) right-click, click Export,choose a good name, select .p12 format and finally click Save.

Make sure that the iOS device you want to use for testing the push notification is added to the app.

Configuring the notification portal on Azure

Now lets first setup the backend so we can send the push notification messages, which will require a valid Azure Account. Log on to Azure and perform the following steps:

  1. Click +NEW
  2. Click APP SERVICES, then SERVICE BUS and then select NOTIFICATION HUB
  3. Enter name, select the region and if you haven't done so already enter your namespace (this option does not appear if you already have created a namespace).

azuremessagehub

After the notification hub is created we will have to configure it for use with Windows Phone Silverlight. Select your notification hub (namespace), which you will find under the SERVICE BUS tab and then select the notification hub you just created.

Under apple notification settings select upload. Upload the p12 file and the password according to what you entered when it was exported. Under Mode select Sandbox for a development certificate or Production for a production certificate. This will depend upon the certificate you upload for the usage.

Setup the client

After setting up the backend we now can connect our app to the push service, as we will be using Azure for the push service we will need to add the Azure Messaging component which you can download by right-clicking on your iOS project then select Get More Components, search for Azure Messaging and add the component to the project.

Registering for notificaitons

Now let’s start wiring up our app to the push service, this is all done in AppDelegate.cs.

First update the FinishedLaunching() method as follows:

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
Forms.Init();

//Register for remote notifications iOS 8 and higher
if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
{
var settings = UIUserNotificationSettings.GetSettingsForTypes(UIUserNotificationType.Sound |
UIUserNotificationType.Alert | UIUserNotificationType.Badge, null);

UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
UIApplication.SharedApplication.RegisterForRemoteNotifications();
}

//Register for remote notifications iOS 7 and bellow
else
{
const UIRemoteNotificationType notificationTypes = UIRemoteNotificationType.Alert
| UIRemoteNotificationType.Badge
| UIRemoteNotificationType.Sound;

UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(notificationTypes);
}

LoadApplication(new App());
return base.FinishedLaunching(app, options);
}

Please note that the registering has changed starting of iOS 8, depending on which version of iOS you are planning on targeting you might only need one of registrations above. If you aren’t using a Xamarin.Forms app it should look as follows:

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
//Register for remote notifications iOS 8 and higher

if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
{
var settings = UIUserNotificationSettings.GetSettingsForTypes(UIUserNotificationType.Sound |
UIUserNotificationType.Alert | UIUserNotificationType.Badge, null);

UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
UIApplication.SharedApplication.RegisterForRemoteNotifications();
}

//Register for remote notifications iOS 7 and lower
else
{
const UIRemoteNotificationType notificationTypes = UIRemoteNotificationType.Alert
| UIRemoteNotificationType.Badge
| UIRemoteNotificationType.Sound;

UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(notificationTypes);
}

return true;
}

To finish of the Registration we add the following member variable within AppDelegate.cs 

private SBNotificationHub Hub { get; set; }

and override the RegisteredForRemoteNotifications() method as follows:

 

public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
const string notificationHubConnectionString = "Endpoint=sb://mallibone.servicebus.windows.net/;SharedAccessKeyName=DefaultListenSharedAccessSignature;SharedAccessKey=Gn@bb3rTokenString";
const string notificationHubName = "mallibone";

Hub = new SBNotificationHub(notificationHubConnectionString, notificationHubName);

Hub.UnregisterAllAsync(deviceToken, (error) =>
{
if (error != null)
{
Console.WriteLine("Error calling Unregister: {0}", error.ToString());
return;
}

var deviceId = Convert.ToBase64String(deviceToken.ToArray());
var tag = Guid.NewGuid().ToString();
var tags = new List<string> { tag };

Hub.RegisterNativeAsync(deviceToken, new NSSet(tags.ToArray()), (errorCallback) =>
{
if (errorCallback != null)
{
Console.WriteLine("RegisterNativeAsync error: " + errorCallback.ToString());
return;
}
});
});
}

Receiving push notifications

Now lets make our device vibrate the first time a message is received. Therefore we override the ReceivedRemoteNotification in (as you might have already guessed) AppDelegate.cs:

 

public override void ReceivedRemoteNotification(UIApplication application, NSDictionary notificationData)
{
SystemSound.Vibrate.PlaySystemSound();
}

Sending the message

In the server explorer double click on your notification hub which will open a window that allows you to send push notifications and check on your device registrations (all within VS :)). Now under type select Apple (APNS)and then Default. For now we do not have to alter the message so if your app successfully started and is humming beside you just click on Send.

Receiving notifications in the background

In many apps you want to handle waking from a push notification differently then when a notification arrives while the user is using the app e.g. when waking from a push notification we want to navigate directly to where the action originated from, when the app is running we might simply want to notify the user that something happened by vibrating the device.

For handling waking up from a push notification we have to add the RecievedRemoteNotification method as follows:

public override void ReceivedRemoteNotification(UIApplication application, NSDictionary notificationData)
{
if (application.ApplicationState == UIApplicationState.Inactive
|| application.ApplicationState == UIApplicationState.Background)
{
// Handle notification on wake
return;
}

SystemSound.Vibrate.PlaySystemSound();
}

 

Starting the app on a notification

To make thing interesting wake and startup have to handled differently on iOS so to ensure a consistent behaviour between wake and startup we will have to modify the FinishedLaunching method as follows:

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();

if (options != null && options.ContainsKey(UIApplication.LaunchOptionsRemoteNotificationKey))
{
var notificationData = options[UIApplication.LaunchOptionsRemoteNotificationKey] as NSDictionary;
// process notification data
}

LoadApplication(new App());
return base.FinishedLaunching(app, options);
}

If you are using Xamarin Forms be sure that you call LoadApplication after handling the notification.

Adding parameters to the notification

Adding parameters is a great way to pass application specific information to the app that is not intended for the user. Adding parameters to the message can be done easily be extending the message as shown in this sample:

{"aps":{"alert":"Notification Hub test notification"},"parameterOne":"SomeIdentifier","parameterTwo":"1234"}

The parameters parsed in ReceivedRemoteNotification:

public override void ReceivedRemoteNotification(UIApplication application, NSDictionary notificationData)
{
if (application.ApplicationState == UIApplicationState.Inactive
|| application.ApplicationState == UIApplicationState.Background)
{
// Handle notification on wake
return;
}


var parameeterOne = notificationData["parameterOne"].ToString();
var parameterTwo = Convert.ToInt32(notificationData["parameterOne"].ToString());

// Send message i.e. process push notification


SystemSound.Vibrate.PlaySystemSound();
}

And in FinishedLaunching method:

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();

if (options != null && options.ContainsKey(UIApplication.LaunchOptionsRemoteNotificationKey))
{
var notificationData = options[UIApplication.LaunchOptionsRemoteNotificationKey] as NSDictionary;
var parameeterOne = notificationData["parameterOne"].ToString();
var parameterTwo = Convert.ToInt32(notificationData["parameterOne"].ToString());

// Send message i.e. process push notification
// process notification data
}

LoadApplication(new App());
return base.FinishedLaunching(app, options);
}

 

Conclusion

Adding push notifications for a Xamarin.iOS or Xamarin.Forms app is possible and with Azure as the backend will allow you to streamline the integration for other platforms such as Windows Phone or Android.