Writing Azure Functions with Rider

Writing Azure Functions with Rider

·

5 min read

With the release of Rider 2019.1, there's now support for Azure Functions in the form of a plugin. Let's find out how easy it is to run a Function locally.

The first step is to install the plugin that will enable support for Azure Functions. Go to the Settings (ctrl+alt+s) > Plugins tab and search for "Azure Toolkit for Rider" and install it. I think it's a very popular plugin, or Jetbrains seriously wants to promote it, because it was the first plugin even when I hadn't installed it yet. Could be alphabetical too, not sure.

The settings page for Plugins

After a quick Rider restart, there is a new option in the Settings > Tools tab: "Azure". Select the Functions subsection, and install the latest version of the Azure Functions Core Tools. There is a link that will install the latest version automatically. Rider then downloads and installs or updates the Azure Functions Core Tools via NPM.

The settings page for Azure Functions

After another Rider restart (because restarting is what IT people do best), there is a new project template and several new class templates.

Create new project for Azure Functions

New Azure class templates

For this example, I create a Timer Trigger (because that will force me to set up the Azure Storage Emulator). This adds a class with the correct attributes and method signature for a timed Function. I looked up that the default CRON expression (0 */5 * * * *) runs every 5 minutes. Code Hollow has a convenient cheat sheet, be sure to check that out if you are creating a custom schedule.

Now that the code seems OK, I want to run this little "hello world" program. The build stops me dead in my tracks, however.

Build error: Metadata generation failed

The fix is not obvious, but fortunately, it's easy. In the projects .csproj file, the target framework is set to netcoreapp2.1 by default. This should be changed to netstandard2.0 (or whatever the latest and greatest version my dear reader is using). I know that at the time of writing dotnet core 3 just came out, but the template from Rider defaults to netcoreapp2.1, so I'm using the closest netstandard. There is either a little bug in the Rider template or there is something wrong with my setup.

<PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

Aah, a building Functions project. Now let's run it...

The build warning

The next problem surfaces quite quickly. One of the debug outputs already warned me for it, but it becomes painfully clear that there is no AzureWebJobsStorage setup for local development.

The run fail

The AzureWebJobStorage needs a local instance of the Azure Storage Emulator or an actual web storage endpoint. What was not immediately clear for me, is that the Azure Storage Emulator needs a SQL LocalDB instance. To get the LocalDB installer, download the SQL Express database. Select Download Media and in the next screen, select the LocalDB option.

Download media

Select LocalDB

The download location will open automatically. There will be an .msi installer to easily install the LocalDB database. I have accidentally installed SQL Server 2017 as well, which gave me problems while initialising the LocalDB. To circumvent those problems, install the latest Cumulative Update for SQL Server 2017. The problem was that the Azure Storage Explorer didn't work properly because it could not connect properly to the LocalDB. That prevented the Azure Storage explorer form creating a database with all the tables it needs. By the way, some articles told me to manually create the AzureStorageEmulatorDb## database. That won't solve the problem, it will just mask the problem as the database won't have the necessary tables.

Once that's all done, verify that the LocalDB installed correctly by running this command SQLLocalDB.exe i. It should print out MSSQLLocalDB. Don't forget to start the database with the command SqlLocalDB.exe s MSSQLLocalDB. Now, the Storage Emulator should work, right? Wrong!

There is no database with the specific name AzureStorageEmulatorDb59. I found this out after I tried starting the Storage Emulator and seeing that the initialisation of the emulator crashed. So, I tried running the command:

> AzureStorageEmulator.exe init  
Windows Azure Storage Emulator 5.9.0.0 command line tool  
 Found SQL Instance (localdb)\\MSSQLLocalDB.  
 Creating database AzureStorageEmulatorDb59 on SQL instance '(localdb)\\MSSQLLocalDB'.  
 Cannot create database 'AzureStorageEmulatorDb59' : The database 'AzureStorageEmulatorDb59' does not exist. Supply a valid database name. To see available databases, use sys.databases..  
 One or more initialization actions have failed. Resolve these errors before attempting to run the storage emulator again.  
 Error: Cannot create database 'AzureStorageEmulatorDb59' : The database 'AzureStorageEmulatorDb59' does not exist. Supply a valid database name. To see available databases, use sys.databases..

To remedy this, open SQL Server Management Studio, connect to the LocalDB instance and create a database with the name AzureStorageEmulatorDb59. I tried doing this in Rider with the built in DataGrip tools, but I got an error. I've reported this, so it will get fixed in the future. See earlier remark about the Cumulative Update! That should prevent this error from happening. I'm keeping it in as I think others will run into the same problem.

Now that the database is set up, I can finally start the storage emulator. All I have to do is fill in the AzureWebJobsStorage with UseDevelopmentStorage=true. All set, lets run the function. Unfortunately, the output still complains that the AzureWebJobsStorage still isn't filled in. After some checking in the config and the place where the function runs, it appears that the local.settings.json file is not being copied. So, I change the Copy to output directory setting in the file properties to Copy Always. Now the Azure function starts up and a minute later, the breakpoint in my function is hit.

To make my life easier, I should add some "Before launch" external tools arguments in the Run/Debug Configuration so the LocalDB and Azure Storage Emulator start before each run. I think I'll set that up later.

Now everything is set up correctly. I can run and debug Azure Functions with Rider. It's not as transparent process as I'd hoped it would be, but it was a good learning experience for me.