Azure Functions in Late 2022

I’ve been catching up with Azure Functions recently, and one thing I learned is that setting up your development environment, project structure and Azure DevOps pipeline is not as straightforward as I’d expect. The goal of this article is to help you with that.

I recommend that you first read the guidelines for running C# Azure Functions in an isolated process – the linked article is a good starting point, but it’s not perfect; specifically it doesn’t mention the packages required to use the provided code snippets.

This article assumes version 4.x of Functions and .NET 6.0 Out-of-process (isolated). You can read more about the different hosting models here.

Runtime VersionIn-ProcessOut-of-process
Functions 4.x.NET 6.0.NET 6.0
.NET 7.0 (preview)
.NET Framework 4.8
Functions 3.x.NET Core 3.1
Functions 2.x.NET Core 2.1
Functions 1.x.NET Framework 4.8
This article assumes version 4.x and .NET 6.0 Out-of-process (isolated)

Setting Up the Local Development Environment

Packages

The first thing I recommend you do is update all packages to the newest versions – it took me good two hours of googling to realize that my project wasn’t working only because the Rider template came with some outdated packages. Hopefully you can learn from my mistake and save yourself some time.

Visual Studio vs Rider Considerations

In both Visual Studio and JetBrains Rider, creating a new Azure Functions isolated project is almost a no-brainer. Almost. By default Rider prompted me to install the legacy Azure Storage Emulator (ASE), even though it came with the new Azurite emulator meant to replace its legacy predecessor. When I uninstalled ASE, it took me a while to figure out why my TimerTrigger (which I mention later) didn’t work in Rider – interestingly my HttpTrigger worked just fine. As it turns out, in Rider you have to start Azurite manually if you want to run functions in localhost (Tools > Azure > Start Azurite), while Visual Studio does this for you automatically.

Host Builder

Take a look at my host builder and the description that follows.

Application Insights

You will need to use the package Microsoft.Azure.Functions.Worker.ApplicationInsights which doesn’t yet have an official release. I am using 1.0.0-preview2 and it’s the only one that comes closest to supporting the full spectrum of AppInsights features – at least for out-of-process functions.

Local Settings

Local settings such as connection strings are kept in the local.settings.json file. You DO NOT commit that file to git or you use it for your CI/CD pipelines (I describe deployment is later). This file follows the same convention as the well-known appsettings.json file.

Please keep in mind that the second parameter to AddJsonFile is both optional and is called optional. Now, if you set it to false, the azure will fail to start the worker process. If that confuses you, you’re not the only one. It doesn’t make much sense, given you’re not supposed to commit local.settings.json. So, always set it to true.

Database Setup

No tricks were required for this. It works the same for both in- and out-of-process functions.

Dependency Injection

If you’re coming from the world of ASP.NET Core apps, the dependency injection model for out-of-process functions works and feels the same as you’re used to in ASP.NET Core. However, it is different for in-process functions–one reason you don’t want to go that way.

First Run

Once you have your Azurite running (remember: VS runs it for you) you can go ahead and run your functions. You should see something similar to the following:

HttpTrigger and TimerTrigger I used, were generated by Rider, and they do nothing special other than logging. I do feel inclined to tell you however, that Azure Functions use the Spring cron format which is 6 figures long, not the 5 figure format of the typical Linux cron you might be more familiar with.

Setting Up Azure DevOps Pipelines

Build Pipeline

The build pipeline that I used came directly from the DevOps template (you can generate it there). I have changed the vmImageName to windows-2022 and disabled the Deploy stage as I wanted to setup a separate release pipeline.

trigger:
- main

variables:
  # Azure Resource Manager connection created during pipeline creation
  azureSubscription: '████████-████-████-████-████████████'

  # Function app name
  functionAppName: 'ShantiNewFunctionApp'

  # Agent VM image name
  vmImageName: 'windows-2022'


  # Working Directory
  workingDirectory: '$(System.DefaultWorkingDirectory)/AF.API'

stages:
- stage: Build
  displayName: Build stage

  jobs:
  - job: Build
    displayName: Build
    pool:
      vmImage: $(vmImageName)

    steps:
    - task: DotNetCoreCLI@2
      displayName: Build
      inputs:
        command: 'build'
        projects: |
          $(workingDirectory)/*.csproj
        arguments: --output $(System.DefaultWorkingDirectory)/publish_output --configuration Release

    - task: ArchiveFiles@2
      displayName: 'Archive files'
      inputs:
        rootFolderOrFile: '$(System.DefaultWorkingDirectory)/publish_output'
        includeRootFolder: false
        archiveType: zip
        archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
        replaceExistingArchive: true

    - publish: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
      artifact: drop

Release Pipeline

The release pipeline is incredibly simple, you only need two steps. Please notice that in the second task I am injecting a connection string that is using DefaultConnection variable – you might need one if you intend to use a database as well.

- task: AzureFunctionApp@1
  displayName: 'Deploy Azure Function App'
  inputs:
    azureSubscription: '$(Parameters.AzureSubscription)'
    appType: '$(Parameters.AppType)'
    appName: '$(Parameters.AppName)'
- task: AzureAppServiceSettings@1
  displayName: 'Azure App Service Settings: <name>'
  inputs:
    azureSubscription: '<subscription>'
    appName: <appName>
    resourceGroupName: functions
    connectionStrings: |
     [
     	{
     		"name": "DefaultConnection",
     		"value": "$(DefaultConnection)",
     		"type": "SQLAzure",
     		"slotSetting": false
     	}
     ]

Summary

I hope some of my discoveries help save you some time getting started with Azure Functions in its current state today.

It is clear that the out-of-process model of Azure Functions is where Microsoft is going, hence I recommend you choose it if at all possible. You might encounter a problem with packages and will have to accept the way new functions are configured (local.settings.json) but overall it’s very similar to ASP.NET Core, so the learning curve isn’t too difficult.

Related Blog Posts

We hope you’ve found this to be helpful and are walking away with some new, useful insights. If you want to learn more, here are a couple of related articles that others also usually find to be interesting:

Our Gear Is Packed and We're Excited to Explore With You

Ready to come with us? 

Together, we can map your company’s software journey and start down the right trails. If you’re set to take the first step, simply fill out our contact form. We’ll be in touch quickly – and you’ll have a partner who is ready to help your company take the next step on its software journey. 

We can’t wait to hear from you! 

Main Contact

This field is for validation purposes and should be left unchanged.

Together, we can map your company’s tech journey and start down the trails. If you’re set to take the first step, simply fill out the form below. We’ll be in touch – and you’ll have a partner who cares about you and your company. 

We can’t wait to hear from you! 

Montage Portal

Montage Furniture Services provides furniture protection plans and claims processing services to a wide selection of furniture retailers and consumers.

Project Background

Montage was looking to build a new web portal for both Retailers and Consumers, which would integrate with Dynamics CRM and other legacy systems. The portal needed to be multi tenant and support branding and configuration for different Retailers. Trailhead architected the new Montage Platform, including the Portal and all of it’s back end integrations, did the UI/UX and then delivered the new system, along with enhancements to DevOps and processes.

Logistics

We’ve logged countless miles exploring the tech world. In doing so, we gained the experience that enables us to deliver your unique software and systems architecture needs. Our team of seasoned tech vets can provide you with:

Custom App and Software Development

We collaborate with you throughout the entire process because your customized tech should fit your needs, not just those of other clients.

Cloud and Mobile Applications

The modern world demands versatile technology, and this is exactly what your mobile and cloud-based apps will give you.

User Experience and Interface (UX/UI) Design

We want your end users to have optimal experiences with tech that is highly intuitive and responsive.

DevOps

This combination of Agile software development and IT operations provides you with high-quality software at reduced cost, time, and risk.

Trailhead stepped into a challenging project – building our new web architecture and redeveloping our portals at the same time the business was migrating from a legacy system to our new CRM solution. They were able to not only significantly improve our web development architecture but our development and deployment processes as well as the functionality and performance of our portals. The feedback from customers has been overwhelmingly positive. Trailhead has proven themselves to be a valuable partner.

– BOB DOERKSEN, Vice President of Technology Services
at Montage Furniture Services

Technologies Used

When you hit the trails, it is essential to bring appropriate gear. The same holds true for your digital technology needs. That’s why Trailhead builds custom solutions on trusted platforms like .NET, Angular, React, and Xamarin.

Expertise

We partner with businesses who need intuitive custom software, responsive mobile applications, and advanced cloud technologies. And our extensive experience in the tech field allows us to help you map out the right path for all your digital technology needs.

  • Project Management
  • Architecture
  • Web App Development
  • Cloud Development
  • DevOps
  • Process Improvements
  • Legacy System Integration
  • UI Design
  • Manual QA
  • Back end/API/Database development

We partner with businesses who need intuitive custom software, responsive mobile applications, and advanced cloud technologies. And our extensive experience in the tech field allows us to help you map out the right path for all your digital technology needs.

Our Gear Is Packed and We're Excited to Explore with You

Ready to come with us? 

Together, we can map your company’s tech journey and start down the trails. If you’re set to take the first step, simply fill out the contact form. We’ll be in touch – and you’ll have a partner who cares about you and your company. 

We can’t wait to hear from you! 

Thank you for reaching out.

You’ll be getting an email from our team shortly. If you need immediate assistance, please call (616) 371-1037.