It's the holiday season, and you know what that means... supposedly Santa will be dropping by your house to leave gifts for all the good boys and girls.
But ... how exactly do you tell if you've been good or not?
I mean, wouldn't it be nice if there was a way you could write a little note to Santa beforehand and find out what he thinks of you? That way you could buy yourself some gifts if the big guy cheaps out?
Luckily there is! It installs on your mobile phone and uses all of your favorite Azure and Xamarin services. Azure Functions, Cognitive Services, and Xamarin.Forms.
This article is going to walk you through some best practices on putting together a mobile app that calls a serverless backend which provides some machine learning smarts.
What We're Going To Build
We're going to build an app that lets you figure out if you've been naughty or nice by sending a note to Santa.
The text in that note will be analyzed to figure out the sentiment behind it, and Santa will let you know if you're going to get a gift or not.
Oh, and it doesn't matter which language you write to Santa in. He knows all. And he's always watching.
The Xamarin.Forms App
The app itself is pretty straight-forward. It's a Xamarin.Forms app and consists of 2 pages, the first lets you enter your name and a note to Santa.
The second displays whether or not Santa is going to bring you any gifts based off the sentiment found in your note. We're going to use the MVVM pattern with plenty of data binding. And to design that cool looking UI - we'll use snppts from a great community member, Steven Thewissen.
But how do we figure out that sentiment?
By using the Text Analytics portion of Microsoft Cognitive Services. Text Analytics can do a lot of very interesting things.
You send in a string of text, and it can tell you key phrases within that text - or the important parts. It'll identify any named entities - like "north pole" that it finds - and it'll include relevant links to wikipedia pages.
But what we're going to use it for is language detection - send in text from any language - and Text Analytics will tell you which one it is.
And we'll use the Sentiment Analysis feature too. This feature tells us if the text sent in is positive, negative, or somewhere along the line between the two.
Ok great - but how does the Xamarin app call out to Text Analytics? Directly? Some other way?
We're going to use Azure Functions to serve as the conduit between the Xamarin app and Text Analytics. Functions provide the ideal backend for mobile applications.
As a quick overview, the code that you write inside a Function is invoked in response to certain events.
So a Function could run in response to an HTTP request (like we'll do in our app). Or it could run in response to a BLOB being put into storage. Or an elapsed timer. Or any other number of events.
The other really cool thing about Functions are bindings. Bindings allow you to get direct access into other services - like Azure Storage or Azure Cosmos DB - but without you having to maintain the connections. The Functions runtime will do it all for you. (We're not going to use bindings here, but I still wanted to mention them because they're so useful.)
OK - so we're going to write an Azure Function that response to an HTTP request.
Once it starts to run, it will make a call out to the Text Analytics Cognitive Service. Then it'll return the sentiment and detected language back.
Let's put this app together!
Putting the Pieces Together
First things first - we'll start off with creating the Text Analytics Cognitive Service. Then we'll call the Text Analytics from the Function, then finally consume it all in the Xamarin app.
Create the Text Analytics Cognitive Service
Open up the Azure portal - and create a new Resource Group.
If you want, you could do this from the Azure Cloud Shell (start it up by clicking on the button on the top toolbar of the portal which looks like a command prompt) with the following command:
az group create -g SantaTalk -l westus2
That resource group is like a folder which will hold the Text Analytics service. Which we'll create right now.
The big things to notice are the
--resource-group which needs to be the same name as the resource group you created above. The
--sku F0 which indicates the free tier. And
--name where you'll need to enter a unique value for your service.
Then that's it. It'll be created. Once it's done, you'll need to grab the URL and Keys from the overview page and make a note of those, because you're going to use those in the Function.
Creating the Azure Function
First off, you may be wondering why we're invoking Text Analytics from the Function instead of directly from the Xamarin app. There are two reasons for that.
- We don't want the Text Analytics key to be on device. If we ever have to regenerate that key, then we'd have to redeploy the app. Also, having a key on device is inherently insecure. It's always possible for somebody to decompile an app.
- The Azure Function will have some business logic in it. And since it's triggered by an HTTP call, we could in theory call it from a mobile app or a web app. So it makes sense to have that centralized.
Alright, so let's talk about invoking the Text Analytics from the Function.
Download the code from GitHub here. This will work in either Visual Studio 2019 or Visual Studio for Mac and is the easiest way to get up and going.
Note that the Function project has
Microsoft.Azure.CognitiveServices.Languages.TextAnalytics NuGet package installed.
That wraps up all the calls to the Text Analytics service for us.
TextAnalytics client withing that SDK. That's the class which will do all the work of communicating to the Text Analytics Cognitive Service for us.
Here's the Function's implementation:
It's getting passed in a
SantaLetter object that has the text of the letter to Santa in a property.
The first thing then that happens is we figure out the language the letter is written in using the
It's possible that Text Analytics may return a couple of different options - after all there are words that exist in more than a single language. Text Analytics will score each, with the higher number representing more confidence. So I'm going to take the highest confidence result.
Then we call
SentimentAsync which scores the feeling of the text. One thing to notice is that we are passing in the language code we received above. This will help Cognitive Services out when it's scoring the sentiment.
After that, we're packaging everything up in a
SantaResults object and returning it.
You do not have to deploy the Function to Azure to run it. You can just hit debug in Visual Studio and you'll be able to run it locally!
Make sure you update the
local.settings.json file to include 2 keys:
APIKeys value will be the key for Text Analytics and the
APIEndpoint is the endpoints URL. Here's an example.
A Note About Model Classes
Before diving in to the Xamarin.Forms app, you'll note that we're using two model classes in the Function.
Because this is Xamarin, and C#, and .NET - we'll be able to reuse those exact same classes in both the Xamarin and the Functions project! Code reuse FTW!
Check out how I have the physical file structure setup on how best to set this up. By doing it this way, you'll be able to run the Function and the Xamarin app at the same time (though in 2 different instances of Visual Studio) and make changes to the models and have them reflected in both immediately.
The Xamarin App
The Xamarin application is the most fun (in my opinion).
I mean, look how great it looks!
OK - so the key to the app is using MVVM. On the first page I have the two entry boxes bound to two properties in my view model. And then a single command which will display the second, results page.
That results page is calling out to 2 services.
The first service
LetterDeliveryService is what invokes the Azure Function. Take a look at the code. Essentially invoking an Azure Function is the same as calling any web service.
The only thing that you'll need to change is the
santaUrl variable, depending on where you're running the Function from.
There's another service called
SantasCommentsService that takes the sentiment score from the Function and makes some snarky comment about it. This is all local, no Function involved here.
Other than that - it's all data binding and styles and custom fonts in the application to give it that custom look.
Take a good look at the UI code for a great example on how a custom UI look and feel can be done from a Xamarin.Forms app.
Summing Up and Learn More
So there you have it. A mobile Xamarin.Forms app that calls out to an Azure Function, which in turn invokes a Microsoft Cognitive Service.
The main point to remember is that never embed the Cognitive Services key within a client side app (even a web app). And you can / should reuse model classes between the Function app and the Xamarin app as much as your business logic dictates.
And that's all you need to tell you if you've been naughty or nice this year!
If you want to learn more about Xamarin, Text Analytics or Function development, there are a ton of great resources for you!