With the recent release of Azure Functions Runtime 2.0, WebJobs SDK 3.0 got released alongside. WebJobs SDK is the backbone of Azure Functions, however it can be also used standalone to power Azure WebJobs which you can host alongside your App Service. SDK 3.0 brings the configuration much closer to ASP.NET Core, runs under both .NET Framework and .NET Core and for example supports Dependency Injection by default.
SDK 3.0 was released a while ago, however there is no changelog available (yet) neither the documentation or the samples were upgraded yet. I decided to upgrade anyways, since the SDK is opensource so if I hit some issue, I can troubleshoot it myself. Luckily, this wasn’t much of a case.
First off, you want to start with upgrading Nuget packages to the latest versions. Then, you will need to modify the Program.cs setup. Like mentioned above, SDK 3.0 brings WebJobs much closer to ASP.NET Core configuration, which is pretty nice. You might want to take a look at the only sample at the time of writing which is included with the SDK’s source.
However, you can notice few things, which I would say should not made it into the sample:
First off, the Envionment is configured statically by UseEnvironment – which I really don’t like. In ASP.NET Core, you can configure Environment by ASPNETCORE_ENVIRONMENT env variable, here this one won’t work. Since ASP.NET Core uses WebHostBuilder and WebJobs use the HostBuilder, there are few differences: In order to specify environment, you need to use environment variable name, just like that.
Next, I really like the concept of User Secrets in ASP.NET Core for development, so why not use those here too? In order to do that, you will need to make two modifications. First, setup the UserSecretsId assembly attribute on the Program class:
Thanks to this, the assembly will now contain the information about User Secrets. In ASP.NET Core, this is defined in .csproj – so far, I haven’t found a way to do this with a WebJob – the build seems to ignore it. I will probably dedicate it a separate article. And then, you need to setup ConfigureHostConfiguration on the HostBuilder like so:
This is going to tell it to use Command Line arguments, Environment Variables and Secrets. Next up is the configuration of all the required triggers which you might be using in ConfigureWebJobs section:
Basically, AddAzureStorageCoreServices makes sure that your WebJob is hooked to a storage account for persisting data, creating logs etc. AddTimers is from WebJobs.Extensions package and allows you to periodically trigger some tasks. You can also use other extensions to connect to Event Grid, Service Bus etc.
Then you should configure logging by ConfigureLogging. In the sample, they don’t check the environment and simple set the debug level to Debug, however since we set the environment previously, we can set it based on the environment:
Then we need to configure the Dependency Injection if needed by ConfigureServices.
Remember to always register your Functions class into services, if you don’t do that, the depedendency injection will not work properly.
Here I have hit a thing which I need to investigate a bit further – the SDK 3.0 seems to support DI by default however, it doesn’t seem to work:
Event tho the runtime registers DefaultJobActivator, it doesn’t seem to resolve the services from the container and you end up with: System.MissingMethodException: No parameterless constructor defined for this object. error, so instead I decided to use my own IJobActivator implementation from SDK 2.0:
You simply register it into the DI and it is going to work fine. I am not quite sure why the default activator doesn’t work for me yet – I will investigate it and update the article if I end up with some results.
Last thing to do is to start using .NET Core logging which basically means, that you replace TextWriter with ILogger and use it just like in an ASP.NET Core app. You can leave TextWriter as is since it will work, however I suggest you switch to ILogger so that you have unified logging across the app. You can optionally add Application Insights if needed – those are part of the sample.