Fritz's Hat Collection Website

Learnings in Blazor Static Web Apps on Azure: Part 1

I’ve been a big fan of Blazor as a framework for web applications and the promise of being able to use my favorite programming language C# in the browser to build with web assembly. When Azure Static Apps released support for Blazor, I was immediately interested and started building a few applications. I’ve learned a few things about adding features to these applications and using other Azure services with a Blazor application and will share some of those tips and tricks in a series of blog posts over the next few weeks.

My first app: Fritz’s Hat Collection

I wanted to make a simple website to get started and learn more about using this application model, so I tackled a long desired website that I wanted to build: a catalog of my hat collection.  Yes, I enjoy a good hat particularly ball-caps and wanted to make a little site that was effectively a little more than an image gallery.  Maybe I would add some metadata and allow visitors to search the site.  The site is currently running at https://hats.csharpfritz.com

The template comes with 3 projects defined:  Client, Api, and Shared.

  • Client is the Blazor web assembly application that is completed downloaded by your visitors and runs in the browser
  • Api is an Azure Functions application that will handle your server-interaction logic
  • Shared contains classes that you want to serialize back and forth between the Azure function and the Blazor application

The source code to this site is available on my GitHub.  Here are some of the basic features of Azure Static Apps I’m using with this site.

The Template is .NET Standard 2.1 and .NET Core 3.1

The Blazor Static App template runs with Azure Functions, and the current version of the Azure Function runtime supports up to .NET Core 3.1.  I wanted to take advantage of C# 9 features including advanced pattern matching and record types.  As of January 2021, we can’t use C# 9 in our Azure functions.

I did try updating my Blazor application to .NET 5 and C# 9, and this does work properly with the Azure functions on .NET Core 3.1.  For simplicity, in this application I left it as .NET Standard 2.1.

The Api project in the template contains a simple class with a static method to generate some fake weather reports.  The only triggers supported by static websites are HttpTriggers, so that means we can expose an Http-based API for Blazor to query.  I updated this function to fetch my collection of hat records from my database:

[FunctionName("GetHats")]
public static async Task GetHats(
  [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req,
  ILogger log)
{
  
  var hats = await Repository.GetHats();
  return new OkObjectResult(hats);

}

It’s too simple:  connect to the repository, get the hats data and return it. 

In my Client project, Blazor will load this with a Json Deserializer and it will expand into Hat objects that can be displayed on the page.

Hats = await Http.GetFromJsonAsync<Hat[]>("/api/GetHats");

Azure Storage is your friend

The application is deployed to Azure where there is no server executing content.  Everything is handed to the browser for interactions.  The Azure functions can get data from a database for us, but we would really like to minimize those requests to the functions.

In my case, I added Azure storage as a repository for the images in the application.  The blob storage service can serve files to the web and can be configured with an expires header so visitors aren’t reloading the same images over and over.  I can configure the blob storage to have the same base-domain name as my application to make it appear as a single domain and eliminate using the Azure default domain name.

You can add a CNAME record to your DNS provider with the prefix “asverify.” to verify that you own the domain name, and then add your real domain name.  I could add some domain names like this to configure my storage account in Azure:

asverify.hatimages.csharpfritz.com
hatimages.csharpfritz.com

Also:  don’t forget to configure CORS for your blob storage so that we can protect folks in their browser from loading Fritz hat images from a different website.

Summary

This is just the first app I tinkered with as I was learned to use more Azure services with Blazor Static Websites.  In the next post, I’m going to start discussing the architecture of my most complex app: KlipTok.  We’ll see how extra functions apps, Azure Search, and database choices were made to allow the application to grow.