Azure WebJobs in .NET Core 2 (with DI and configuration)

I recently needed to migrate some azure webjobs to .NET core 2.0. This is something that's not massively documented (probably because the .net libraries were only ported to core recently), so here's my write-up of how I set this all up.

My setup

My solution is an asp.net core 2.0 web app and a shared class library. I needed some console apps to that solution to run azure web jobs. The requirements of my webjobs are thusly:

  • Trigger methods via scheduled timers ([TimerTrigger])
  • Trigger methods via queue items ([QueueTrigger])
  • Use the same DI mechanism as the web app
  • Use the same config setup as the web app

Here's how I got all this working:

The webjob core bits

This was pretty simple, I created a .net core console app (if you're using VS, at the time of writing there are no templates for creating a webjob project, like there are for 'classic' .NET). Once I've done that I need 2 packages:

dotnet add package Microsoft.Azure.WebJobs
dotnet add package Microsoft.Azure.WebJobs.Extensions

The first contains the azure webjobs SDK and allows us to wire things up. The second allows us to create timer triggers, so methods can run on a schedule - useful eh!

So now we're ready to configure DI, and um, configure configuration ;)

DI and Configuration

My web app uses the standard vanilla DI container that ships with asp.net core. I was mildly worried about getting this to work in a console app, but it was simple..

First of all, some packages:

dotnet add package Microsoft.Extensions.DependencyInjection
dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.Json
dotnet add package Microsoft.Extensions.Options.ConfigurationExtensions

That gives you everything you need for working with the DI container, and for setting up the configuration.

Then, you need to setup the DI container. In asp.net core you have a ConfigureServices method in your startup.cs where you do this. So, we can follow that pattern in our console app:

We create a serviceCollection, and pass it into ConfigureServices, where we configure our services. In my example, I'm setting up SomeUsefulClass as a dependency for our webjob, and then I'm setting up the class that contains the actual webjob methods - WebJobsMethods (naming things is hard).

I also wanted to hook in my appsettings.json configuration for my webjobs - you can see in my ConfigureServices method I'm adding the ConfigurationBuilder, telling it about my json file, and finally adding a configuration class called MySettings to the DI container. Any class that "depends" on MySettings will receive a fully populated class from my JSON now - perfect.

Also worth mentioning is the 2 lines that tell Azure what the storage account connection strings are - needed by the sdk for hooking up with your Queues, and for writing web jobs logs / stats.

JobHostConfiguration

The other thing you'll see in that code above is I need to configure the web job. Most of this is standard stuff, but notice I added a JobActivator - I'm pointing it to a class called CustomJobActivator - here it is:

So that simple resolver class just stores the DI container (service), and is then used by the web job to instantiate all classes needed, which it does simply by delegating to the DI container, hooray.

The web job methods

So now we need the actual web job methods - this bit is nice and easy now :)

See how the class that contains the web jobs methods can now just use DI - we have a CTOR that sets up the dependencies for that class. Then, in our methods, we can make full use of them. Awesome eh?

Comments powered by Disqus