Getting a user's Gravatar data using Azure Functions

Copenhagen based cloud developer. Love to code and to make complex solutions simple!
Search for a command to run...

Copenhagen based cloud developer. Love to code and to make complex solutions simple!
No comments yet. Be the first to comment.
This series will cover lots of practical and hard learned experiences developing Azure Functions. Read about how to design your microservice setup, how to implement the functions using triggers.
We have started to use SonarQube, an awesome tool for static code analysis, and due to several reason we have to use the on-prem version and not the cloud version. Now that we use SonarQube we want maximum visibility of the metrics that SonarQube pr...
And examples for .NET projects also

...and why Windows is not going to sleep when left idle

TL;DR Keep trying the firmware update - after around 30 attempts doing the same thing, it just worked 🤯🎉🪅 Awesome Ultrawide Monitor, not only for gaming For once I'm going to write an article which is not directly related to programming, but if yo...

When using GitHub actions it's pretty neat that you can use the hosted GitHub runners. However, this can get costly if you use a lot of runners and they are not always that fast at running the actions. Luckily you can also host your own runners and w...

...and some SonarCloud code analysis!

Years back I created a Gravatar library for C# to use in some projects where I needed some basic user profile information. You can read more about that in an article I wrote about that subject.
The library has around 6K downloads on Nuget and recently I decided to update it to 2021 standards mainly because people are actually using it and also because I wanted to use it in an Azure Function.
The overall idea with this is that whenever a user signs up in our system, we want to enrich that user profile with as much data as possible, with as little interaction needed from the user as possible. This is where Gravatar comes into play, because you can query their service, just providing them with an email address, and they will return whatever user profile info they have. Since we want as much profile information as possible, we also want to query other services for information but that has nothing to do with the data we get from Gravatar. Therefore, by splitting the logic into several small micro services that query each different external service, we will make a more robust, more scalable and hopefully also easier to maintain solution. Azure Functions is the perfect match in this kind of scenario, as we can have several Functions triggered when a user is created in our system.
So here's the high-level idea:
Since grabbing data from different external services could take some time, perhaps not minutes, but definitely several seconds, we don't want the user to wait for that, so we run those in the background using Azure Functions.
We are going to create a new Azure Function with a QueueTrigger, this will ensure that our front-end system can quickly add a queue message and don't have to let the user wait for process to run. We could also have chosen a HttpTrigger, but then our front-end would have to wait for the function to return, which is what we want to avoid.
So to get started, fire up Visual Studio, create a new Azure Function project and when you get to the New Azure Function dialog, select the Queue trigger:

Once this is done, we need to setup a storage connection so that our Function can read queue messages and persist the Gravatar images to a blob.
Azure Functions uses a storage account to handle it's internal workings, like the triggers, state, etc. Microsoft recommends to use a separate storage account for your own code, for instance if you need to write to a blob, then use a separate storage account to store those blobs. Read more about that here
Here are the steps:

Remember, for production scenarios the storage account used internally by the function should be separate from this storage account.
local.settings.json{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"StorageConnectionString": "DefaultEndpointsProtocol=https;AccountName=...",
"FUNCTIONS_WORKER_RUNTIME": "dotnet"
}
}
You then need to reference that connection string in your function trigger, like this:
[FunctionName("Function1")]
public async Task Run([QueueTrigger("gravatar-queue", Connection = "StorageConnectionString")]string email, ILogger log)
{
...
}
All we need to do now is to grab the Nuget, call Gravatar through that Nuget and persist the data into our storage account:
Install-Package GravatarSharp.Core -Version 0.9.0.2
Setup up an output binding on the function to allow the function code to send the Gravatar image to our blob storage, this is done by adding an attribute to our function signature:
[Blob("gravatar-images", Connection = "StorageConnectionString")] CloudBlobContainer outputContainer
gravatar-images is a blob container that you need to create in the storage account that the StorageConnectionString points to.
Putting the pieces together here is how our entire function class should look like:
public static class Function1
{
[FunctionName("Function1")]
public static async Task Run(
[QueueTrigger("gravatar-queue", Connection = "StorageConnectionString")]string email,
[Blob("gravatar-images", Connection = "StorageConnectionString")] CloudBlobContainer outputContainer,
ILogger log)
{
// The initialization of the GravatarController is only for demo purposes, in real life you would inject the controller and the HttpClient using DI
var gravatar = new GravatarController(new HttpClient());
var result = await gravatar.GetProfile(email);
// You probably don't want to do this in a production scenario as it makes a request against the storage account
await outputContainer.CreateIfNotExistsAsync();
var cloudBlockBlob = outputContainer.GetBlockBlobReference(result.Profile.Id);
await cloudBlockBlob.UploadFromStreamAsync(await new HttpClient().GetStreamAsync(result.Profile.ImageThumbUrl));
}
}
Please take note of the comments in the code, especially the first on about using dependency injection, the above code is just a simple demo, in real life you should not create new objects like this. I have written an article about dependency injection and another one specifically about using HttpClient correctly in Azure Functions.
With the above in place, let's take a look at how it all works out. First, run your function project. Then, add an item to the queue (I use Azure Storage Explorer, more on that in the bottom of this article):

Then hit OK and your function should be executed shortly after. Once executed, you should find a file in the blob container, like here:

That should cover it all, here is what we have accomplished:
Thanks for reading and please feel free to reach out to me in the comments if you have any questions, feedback or anything else. I will be happy to hear about how you use Azure Functions or if you are planning to use Gravatar or the library mentioned.
Here are some relevant links about the stuff we have discussed in this article.
Azure Storage Explorer - a great tool for everything related to Azure Storage