Getting Setup With C# 8

If you aren’t sure if you are using C# 8, or you know you aren’t and want to know how to access these features. Read this quick guide on getting setup with .NET Core and C# 8.

Introduction To Ranges

Let’s first just show some code and from there, we can iterate on it trying a few different things.

Our starting code looks like :

So essentially we are looking to go from “index” 1 – 3 in our list and output the item. Unsurprisingly when we run this code we get

But let’s say we don’t want to use a for loop, and instead we want to use this new fandangle thing called “ranges”. We could re-write our code like :

And when we run it?

Uh oh… We have one less item than we thought. We’ve ran into our first gotcha when using Ranges. The start of a range is inclusive, but the end of a range is exclusive.

If we change our code to :

Then we get the expected result.

Shortcut Ranges

Using Ranges where it’s “From this index to this index” are pretty handy. But what about “From this index to the end”. Well Ranges have you covered!

From An Index (Inclusive) To The End (Inclusive)

Output :

From The Start (Inclusive) To An Index (Exclusive)

Output :

Entire Range (Inclusive)

Output :

From Index (Inclusive) To X From The End (Inclusive)

This one deserves a quick description. Essentially we have a new operator ^  that is now used to designate “From the end”. I labelled this one as “Inclusive” but it really depends on how you think about “from the end”. In my mind in a list of 5 items ^1  would refer to the 4th item. So if that’s included in the result, it’s inclusive.

Output :

Range As A Type

When we write 1..4, it looks like we are dealing a couple of integers in a new special format, but actually this is almost the initialisation syntax for a range. Similar how we might use {“1”, “2”, “3”} to illustrate us creating an array or list.

We can actually rip out the range from here, and create a new type to be passed around.

This could be handy to pass around into a method or re-use multiple times. I think it’s pretty close to using something like the System.Drawing.Point  object to specify X and Y values rather than having two separate values passed around.

A New Substring

One pretty handy thing about ranges is that they can be used as a faster way to do String.Substring operations. For example :

Would output 234 . Obviously this would be a slight shift in thinking because string.Substring isn’t “From this index to this Index” but instead “From this index count this many characters”.

Who Uses Arrays Anyway? What About List<T>?

So when I first had a play with this. I couldn’t work out what I was doing wrong… As it turns out. It was because I was using a List<T>  instead of an Array. I don’t to be too presumptuous but I would say the majority of times you see a “list” or “set” or data in a business application, it’s going to be of type List<T> . And well.. It’s not available to use Ranges. I also can’t see any talk of it being made either (Possibly because of the linked list nature of List<T> Apparently List<T> is not a linkedlist at all! So then I’m not sure why Ranges are not available). Drop a comment below on your thoughts!

This is part 5 of a series on getting up and running with Azure WebJobs in .NET Core. If you are just joining us, it’s highly recommended you start back on Part 1 as there’s probably some pretty important stuff you’ve missed on the way.


Azure WebJobs In .NET Core

Part 1 – Initial Setup/Zip Deploy
Part 2 – App Configuration and Dependency Injection
Part 3 – Deploying Within A Web Project and Publish Profiles
Part 4 – Scheduled WebJobs
Part 5 – Azure WebJobs SDK


Where Are We Up To?

Thus far, we’ve mostly been playing around with what amounts to a console app and running it in Azure. If anything it’s just been a tidy environment for running little utilities that we don’t want to spin up a whole VM for. But if you’ve used WebJobs using the full .NET Framework before, you know there are actually libraries to get even more out of Web Jobs. Previously this wasn’t available for .NET Core applications, until now!

Installing The WebJob Packages

Go ahead and create stock standard .NET Core console application for us to test things out on.

The first thing we need to do with our new app is install a nuget package from Microsoft that opens up quite a few possibilities.

Note that this needs to be atleast version 3.0.0. At the time of writing this is version 3.0.2 so you shouldn’t have any issues, but just incase you are trying to migrate an old project.

Now something that changed from version 2.X to 3.X of the library is that you now need to reference a second library called “Microsoft.Azure.WebJobs.Extensions”. This is actually pretty infuriating because no where in any documentation does it talk about this. There is this “helpful” message on the official docs :

The instructions tell how to create a WebJobs SDK version 2.x project. The latest version of the WebJobs SDK is 3.x, but it is currently in preview and this article doesn’t have instructions for that version yet.

So it was only through trial and error did I actually get things up and running. So you will want to run :

I honestly have no idea what exactly you could do without this as it seemed like literally every single trigger/webjob function I tried would not work without this library. But alas.

Building Our Minimal Timer WebJob

I just want to stress how different version 3.X of WebJobs is to 2.X. It feels almost like a complete rework, and if you are trying to come from an older version, you may think some of this looks totally funky (And that’s because it is a bit). But just try it out and have a play and see what you think.

First thing we want to do is create a class that holds some of our WebJob logic. My code looks like the following :

So a couple of notes :

  • The Singleton attribute just says that there should only ever be one of this particular WebJob method running at any one time. e.g. If I scale out, it should still only have one instance running.
  • The “TimerTrigger” defines how often this should be run. In my case, once a minute.
  • Then I’m just writing out the current time to see that we are running.

In our Main method of our console application, we want to add a new Host builder object and start our WebJob. The code for that looks like so :

If you’ve used WebJobs before, you’re probably used to using the JobHostConfiguration  class to do all your configuration. That’s now gone and replaced with the HostBuilder . Chaining is all the rage these days in the .NET Core world so it looks like WebJobs have been given the same treatment.

Now you’ll notice that I’ve added a a call to the chain called AddAzureStorageCoreServices()  which probably looks a little weird given we aren’t using anything with Azure at all right? We are just trying to run a hello world on a timer. Well Microsoft says bollox to that and you must use Azure Blob Storage to store logs and a few other things. You see when you use Singleton (Or just in general what you are doing needs to run on a single instance), it uses Azure Blob Storage to create a lock so no other instance can run. It’s smart, but also sort of annoying if you really don’t care and want to throw something up fast. It’s why I always walk people through creating a Web Job *without* this library, because it starts adding a whole heap of things on top that just confuse what you are trying to do.

Anyway, you will need to create an appsettings.json file in the root of your project (Ensure it’s set to Copy Always to your output directory). It should contain (atleast) the following :

For the sake of people banging their heads against the wall with this and searching Google. Here’s something to help them.

If you are getting the following error :

Unhandled Exception: System.InvalidOperationException: Unable to resolve service for type ‘Microsoft.Azure.WebJobs.DistributedLockManagerContainerProvider’ while attempting to activate ‘Microsoft.Azure.WebJobs.Extensions.Timers.StorageScheduleMonitor’.

This means that you haven’t added the call to AddAzureStorageCoreServices()

If you are instead getting the following error :

Unhandled Exception: Microsoft.Azure.WebJobs.Host.Listeners.FunctionListenerException: The listener for function ‘SayHelloWebJob.TimerTick’ was unable to start. —> System.ArgumentNullException: Value cannot be null.
Parameter name: connectionString
at Microsoft.WindowsAzure.Storage.CloudStorageAccount.Parse(String connectionString)

This means that you did add the call to add the services, but it can’t find the appsetting for the connection strings. First check that you have them formatted correctly in your appsettings file, then ensure that your appsettings is actually being output to your publish directory correctly.

Moving on!

In the root of our project, we want to create a run.cmd  file to kick off our WebJob. We went over this in Part 1 of this series, so if you need a reminder feel free to go back.

I’m just going to go ahead and Publish/Zip my project up to Azure (Again, this was covered in Part 1 incase you need help!). And what do you know!

Taking This Further

At this point, so much of this new way of doing WebJobs is simply trial and error. I had to guess and bumble my way through so much just to get to this point. As I talked about earlier, the documentation is way behind this version of the library which is actually pretty damn annoying. Especially when the current release on Nuget is version 3.X, and yet there is no documentation to back it up.

One super handy tool I used was to look at the Github Repo for the Azure Webjobs SDK. Most notably, there is a sample application that you can go and pick pieces of out of to get you moving along.

What’s Next?

To be honest, this was always going to be my final post in this series. Once you reach this point, you should already be pretty knowledgeable about WebJobs, and through the SDK, you can just super power anything you are working on.

But watch this space! I may just throw out a helpful tips post in the future of all the other annoying things I found about the SDK and things I wished I had known sooner!

I came across an interesting problem while developing a monitoring tool recently. It was a simple HTTP check to see if a webpage had a certain piece of text on it. When it didn’t, I was saving the HTML and I had to sift through it at a later date to try and work out what went wrong. At some point, reading HTML (Or loading the HTML without any CSS/JS) become really tiresome so what I really wanted was the ability to take a screenshot of a webpage and save it as an image.

Boy. What a ride that took me on. After hours of searching, It felt like I had two options. Either I could use a dedicated paid library to save HTML to Image, or I could use many HTML to Image command line utilities – I would just have to invoke it from C# code. Neither really appealed a hell of a lot.

While explaining the problem to a friend, the conversation went a bit like this :

Friend : Do you need to manipulate the page in any way? Like click a link or something?
Me : No I just need to do a get request for a page and save the result, that’s it. 
Friend : Oh OK. I was going to say, you could use the Selenium part for clicking around the page if you needed it. Anyway, good luck!

It took a few seconds to register but… Of course… Selenium can take screenshots of webpages! After all it’s just browser automation anyway! Admittedly it’s kinda heavy for just taking screenshots, but for my nice little utility I really didn’t care. And actually the ability to extend the code to be able to then *do* things on the page at a later date probably only makes it more of an attractive option.

Installing Selenium Into Your Project

We’re going to need two packages. The first is mandatory and that is the Selenium.Support package. Run the following from your package manager command line :

Next we want to install the driver for the browser we want to use. So this is going to totally depend on which browser you want to do the browsing. For me I want to use Chrome, but you can also choose to use Firefox or PhantomJS etc so modify the following command for what you need.

Our Selenium Screenshot Code

First I’ll give you the code, then we can talk it through.

Taking it step by step, it’s actually really easy (Almost too easy).

  • Our options with Headless tells chrome that we don’t want to actually see the chrome window. Mostly because it’s annoying having it pop up all the time, but headless also sometimes causes problems with screenshots (More on this later).
  • We create our ChomeDriver with a very specific path, this is because without it, we get this weird error which again, I’ll talk about shortly.
  • Navigate to the page we want
  • Take a screenshot
  • Save it down as a file (We can also get a byte array at this point if we want to instead push it to cloud storage etc).

And that’s literally it. You can now take screenshots of webpages! But now onto the edge cases.

Unable To Find ChromeDriver Exception

So initially I had the following exception :

The chromedriver.exe file does not exist in the current directory or in a directory on the PATH environment variable.

It turned out to be a two pronged fix.

The first is that we need to make sure we have installed the actual ChromeDriver nuget package *and* rebuilt our solution completely. The nuget package command is :

This is actually a little confusing because the ChromeDriver class is available in code, intellisense and all, but it won’t run unless you install that package.

Next for some reason it couldn’t find the ChromeDriver.exe in my applications bin folder still. What seemed to fix it was the fact you can give it a bit of a nudge in the right direction, and so telling it to look in the current application folder (e.g. the Bin folder) got us there.

Screenshot Is Off Screen

While testing this out I noticed that when I swapped to using the headless chrome browser, that sometimes what I wanted to view was just off screen.  While there was actually some nifty libraries to take just a screenshot of a single element in Selenium, I had a cruder (but simpler) solution!

If we can just make the window a reasonable width, but really long, then we can take a screenshot of the “browser window”, and it should capture everything. Obviously this isn’t an exact science and if the length of your page is forever changing, this may not work. But if it’s static content, just a little longer, this works perfectly.

The code looks a bit like :

So now as long as our content is no longer than 2000px long (In my case, it will never be), then we are set. Again, there’s probably more elegant solutions but this works so well for what I need it to do.

Now the title of this post is probably a bit of a mouthful and maybe isn’t what you think. This isn’t about overriding the default settings of JSON.net, it’s about overriding JSON.net *back* to default. That probably doesn’t make a heck of a lot of sense, but hopefully by the end of this post it will!

Returning Enums as Strings In ASP.net Core

If you are returning an enum from an ASP.net Core Web project, by default it’s going to return as the integer representation.

So for example if we have a model that contains an enum that looks like this :

This model will (by default) be serialized looking like so :

Which makes sense. It’s better that we return the integer values in most cases because these become the immutable “key” values, whereas the name of the actual enum can change.

However in some cases, we may want to return a string value. This could be because you have a pesky Javascript/IOS developer who wants string values and won’t budge, or maybe you just prefer it that way! In either case, there is a way to override the model serialization on a per class basis.

All we have to do is decorate our property with a special attribute.

You will require two using statements to go along with this one :

What this does is tell JSON.net (Which as of writing, is the default JSON serializer of .NET Core), to serialize this particular property using the StringEnumConverter. Which among other things, can just use the string representation of an enum. If we serialize this model now, we get :

But the problem we now have is that we have to go and edit every single property that uses an enum and tell it to use the string representation. If we know we want it in every case across the board, then we can actually tell JSON.net to use the StringEnumConverter everytime.

Head over to our startup.cs and find the ConfigureServices method. In there we should already see a call to AddMvc(), and we are just going to tack onto the end of this.

Here we are basically saying that here’s a converter you can use anytime it’s applicable (Which is basically for every Enum), so go ahead and use it.

The Problem (And The Fix)

If we have been humming along serializing enums as strings, we might end up in a position where we actually do want to return an enum as an integer. A prime example of this (At least it was for me), is returning error codes. I want the codes to be represented in C#  as enums as it’s much easier to wrangle, but be serialized out as simple numeric code.

So what we now want to do is override our “new default” of StringEnumConverter, and go back to the old way of doing things. So how do we do that? Well actually we can’t. As crazy as that probably sounds, I couldn’t find any way  to say “Please use the default converter instead of that other one I gave you”.

Thinking that I was going to have to write my own custom converter just to cast back to an int, I came across an interesting little piece of documentation. It came of the form of the “CanWrite” property of a custom converter. The documentation of which is here : https://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_JsonConverter_CanWrite.htm

Note that if this is set to false, it’s saying that the JsonConverter cannot write the JSON. So what is it going to fall back to? As it turns out, the default converter for that type.

So all we need to do is whip up a custom JSON converter that does absolutely nothing :

The NotImplemented methods are ones that I must have when I inherit from the base class. But because I set CanRead and CanWrite to false, they are never actually called.

Now if we decorate our enum property with this converter (Essentially forcing it to use no other custom converters even if they are in the setup list in our startup.cs)

Serializing this model again we get :

Perfect!

This is part 4 of a series on getting up and running with Azure WebJobs in .NET Core. If you are just joining us, it’s highly recommended you start back on Part 1 as there’s probably some pretty important stuff you’ve missed on the way.


Azure WebJobs In .NET Core

Part 1 – Initial Setup/Zip Deploy
Part 2 – App Configuration and Dependency Injection
Part 3 – Deploying Within A Web Project and Publish Profiles
Part 4 – Scheduled WebJobs
Part 5 – Azure WebJobs SDK


WebJob Scheduling For .NET Core?

So in this part of our tutorial on Web Jobs, we are going to be looking at how we can set WebJobs on schedules for .NET Core. Now I just want to emphasize that this part really isn’t really too .NET Core specific, infact you can use these exact steps to run any executable as a Web Job on a schedule. I just felt like when I was getting up and running, that it was sort of helpful to understand how I could get small little “batch” jobs to run on a schedule in the simplest way possible.

If you feel like you already know all there is about scheduling jobs, then you can skip this part altogether!

Setting WebJob Schedule via Azure Portal

So even though in our last post, we were deploying our WebJob as part of our Web Application, let’s take a step back and pretend that we are still uploading a nice little raw executable via the Azure Portal (For steps on how to make that happen, refer back to Part 1 of this series).

When we go to upload our zip file, we are actually presented with the option to make things scheduled right from the get go.

All we need to do is make our “Type” of WebJob be triggered. As a side note, many people confuse this with “triggering” a WebJob through something like a queue message. It’s not quite the same. We’ll see this in a later post, but for now think of a “triggered” WebJob referring to either a “Manual” trigger, e.g. You click run inside the portal. Or “Scheduled” which is run every X minutes/hours/days etc.

Now our “CRON Expression” is like any other time you’ve used CRONs. Never used them before? Well think of it like a string of numbers that tells a computer how often something should run. You’ll typically see this in Linux systems (Windows Task Scheduler for example is more GUI based to set schedules). Here’s a great guide to understanding CRON expressions : https://www.baeldung.com/cron-expressions.

A big big word of warning. While many systems only allow CRON expressions down to the minute, Azure allows CRON syntax down to the second. So there will be 6 parts to the CRON instead of 5 just incase you can’t work out why it’s not accepting your expression. This is also pretty important so you don’t overwhelm your site thinking that your batch job is going to run once a minute when really it goes crazy at once a second.

Once created, our application will run on our schedule like clockwork!

Editing An Existing WebJob Schedule via Azure Portal

So about editing the schedule of a WebJob in the portal… Well.. You can’t. Annoyingly there is no way via the portal GUI to actually edit the schedule of an existing WebJob. Probably even more frustratingly there is not even a way to stop a scheduled WebJob from executing. So if you imagine that you accidentally set something to run once a second and not once a minute, or maybe your WebJob is going off the rails and you want to stop it immediately to investigate, you can’t without deleting the entire WebJob.

Or so Azure wants you to think!

Luckily we have Kudu to the rescue!

You should be able to navigate to  D:\home\site\wwwroot\App_Data\jobs\triggered\{YourWebJobName}\publish  via Kudu and edit a couple of files. Note that this is *not* the same as  D:\home\data\jobs\triggered . The data folder is instead for logs and other junk.

Anyway, once inside the publish folder of your WebJob, we are looking for a file called “settings.job”. The contents of which will look a bit like this :

This should obviously look familiar, it’s our CRON syntax from before! This is actually how Azure stores our CRON setting when we initially upload our zip. And what do you know, editing this file will update our job to run on the updated schedule! Perfect.

But what about our run away WebJob that we actually wanted to stop? Well unfortunately it’s a bit of a hack but it works. We need to set the contents of our settings.job file to look like :

What is this doing? It’s saying please only run our job at 5AM on the 31st of February. The top of the class will note there is no such thing as the 31st of the February, so the WebJob will actually never run. As dirty as it feels, it’s the only way I’ve found to stop a scheduled WebJob from running (except of course to just delete the entire WebJob itself).

Uploading A WebJob With A Schedule As Part Of A Website Deploy

Sorry for the butchering of the title on this one, but you get the gist. If we are uploading our WebJob as part of our Website deploy, how do we upload it with our schedule already defined? We obviously don’t want to have to go through the portal or Kudu to edit the schedule every time.

A quick note first. You should already have done Part 3 of this series on WebJobs in .NET Core that explains how we can upload a WebJob as part of an Azure Website deploy. If you haven’t already, please read that post!

Back to deploying our scheduled job. All we do is add a settings.job file to the root of our WebJob project. Remember to set the file to “Copy If Newer” to ensure the file is copied when we publish.

The contents of this file will follow the same format as before. e.x. If we want to run our job once a minute :

Now importantly, remember from Part 3 when we wrote a PostPublish script to publish our WebJob to the App_Data folder of our Website? We had to edit the csproj of our Website. It looked a bit like this :

Now we actually need to change the folder for our scheduled WebJob to instead be pushed into our “triggered” folder. So the PostPublish script would look like :

Again I want to note that “triggered” in this context is only referring to jobs that are triggered via a schedule. Jobs that are triggered by queue messages, blob creation etc, are still continuous jobs. The job itself runs continuously, it’s just that a particular “method” in the program will trigger if a queue message comes in etc.

If you publish your website now, you’ll also deploy your WebJob along with it. Easy!

What’s Next?

So far, all our WebJobs have been simple .NET Core console applications that are being run within the WebJob system. The code itself actually doesn’t know that it’s a WebJob at all! But if you’ve ever created WebJobs using FullFramework, you know there are libraries for WebJobs that allow you to trigger WebJobs based on Queue messages, blobs, timers etc all from within code. Up until recently, these libraries weren’t ported to .NET Core, until now! Jump right into it now!

This is part 3 of a series on getting up and running with Azure WebJobs in .NET Core. If you are just joining us, it’s highly recommended you start back on Part 1 as there’s probably some pretty important stuff you’ve missed on the way.


Azure WebJobs In .NET Core

Part 1 – Initial Setup/Zip Deploy
Part 2 – App Configuration and Dependency Injection
Part 3 – Deploying Within A Web Project and Publish Profiles

Part 4 – Scheduled WebJobs
Part 5 – Azure WebJobs SDK


Deploying Within A Web Project

So far in this series we’ve been packaging up our WebJob as a stand alone service and deploying as a zip file. There’s two problems with this approach.

  • We are manually having to upload a zip to the Azure portal
  • 9 times out of 10, we just want to package the WebJob with the actual Website, and deploy them together to Azure

Solving the second issue actually solves the first too. Typically we will have our website deployment process all set up, whether that’s manual or via a build pipeline. If we can just package up our WebJob so it’s actually “part” of the website, then we don’t have to do anything special to deploy our WebJob to Azure.

If you’ve ever created an Azure WebJob in .NET Framework, you know in that eco system, you can just right click your web project and select “Add Existing Project As WebJob” and be done with it. Something like this :

Well, things aren’t quite that easy in the .NET Core world. Although I wouldn’t rule out this sort of integration into Visual Studio in the future, right now things are a little more difficult.

What we actually want to do is create a publish step that goes and builds our WebJob and places it into a particular folder in our Web project. Something we haven’t jumped into yet is that WebJobs are simply console apps that live inside the “App_Data” folder of our web project. Basically it’s a convention that we can make use of to “include” our WebJobs in the website deployment process.

Let’s say we have a solution that has a website, and a web job within it.

What we need to do is edit the csproj of our website project. We need to add something a little like the following anywhere within the <project> node :

What we are doing is saying when the web project is published, *after* publishing, also run the following command.

Our command is a dotnet publish command that calls publish on our webjob, and says to output it (signified by the -o flag) to a folder in the web projects output directory called “App_Data\Jobs\continuous\WebJobExample”.

Now a quick note on that output path. As mentioned earlier, WebJobs basically just live within the App_Data folder within a website. When we publish a website up to the cloud, Azure basically goes hunting inside these folders looking for webjobs to run. We don’t have to manually specify them in the portal.

A second thing to note is that while we are putting it in the “continuous” folder, you can also put jobs inside the “triggered” folder which are more for scheduled jobs. Don’t worry too much about this for now as we will be covering it in a later post, but it’s something to keep in mind.

Now on our *Website* project, we run a publish command :  dotnet publish -c Release . We can head over to our website output directory and check that our WebJob has been published to our web project into the App_Data folder.

At this point, you can deploy your website publish package to Azure however you like. I don’t want to get too in depth on how to deploy the website specifically because it’s less about the web job, and more about how you want your deploy pipeline to work. However below I’ll talk about a quick and easy way to get up and running if you need something to just play around with.

Deploying Your Website And WebJob With Publish Profiles

I have to say that this is by no means some enterprise level deployment pipeline. It’s just a quick and easy way to validate your WebJobs on Azure. If you are a one man band deploying a hobby project, this could well suit your needs if you aren’t deploying all that often. Let’s get going!

For reasons that I haven’t been able to work out yet, the csproj variables are totally different when publishing from Visual Studio rather than the command line. So we actually need to edit the .csproj of our web project a little before we start. Instead of :

We want :

So we remove the $(ProjectDir)  variable. The reason is that when we publish from the command line, the $(PublishDir)  variable is relative, whereas when we publish from Visual Studio it’s an absolute path. I tried working out how to do it within MSBuild and have conditional builds etc. But frankly, you are typically only ever going to build one way or the other, so pick whichever one works for you.

If you head to your Azure Web App, on the overview screen, you should have a bar running along the top. You want to select “Get Publish Profile” :

This will download a .publishsettings file to your local machine. We are going to use this to deploy our site shortly.

Inside Visual Studio. Right click your website project, and select the option to Publish. This should pop up a box where you can select how you want to publish your website. We will be clicking the button right down the bottom left hand corner to “Import Profile”. Go ahead and click it, and select the .publishsettings file you just downloaded.

Immediately Visual Studio will kick into gear and push your website (Along with your WebJob) into Azure.

Once completed, we can check that our website has been updated (Visual Studio should immediately open a browser window with your new website), but on top of that we can validate our WebJob has been updated too. If we open up the Azure Portal for our Web App, and scroll down to the WebJob section, we should see the following :

Great! We managed to publish our WebJob up to Azure, but do it in a way that it just goes seamlessly along with our website too. As I mentioned earlier, this isn’t some high level stuff that you want to be doing on a daily basis for large projects, but it works for a solo developer or someone just trying to get something into Azure as painlessly as possible.

Verifying WebJob Files With Kudu

As a tiny little side note, I wanted to point out something if you ever needed to hastily change a setting on a WebJob on the fly, or you needed to validate that the WebJob files were actually deployed properly. The way to do this is using “Kudu”. The name of this has sort of changed but it’s all the same thing.

Inside your Azure Web App, select “Advanced Tools” from the side menu :

Notice how the icon is sort of a “K”… Like K for Kudu… Sorta.

Anyway, once inside you want to navigate to Debug Tools -> CMD. From here you can navigate through the files that actually make up your website. Most notably you want to head along to /site/wwwroot/App_Data/ where you will find your WebJob files. You can add/remove files on the fly, or even edit your appsettings.json files for a quick and dirty hack to fix bad configuration.

What’s Next?

So far all of our WebJobs have printed out “Hello World!” on repeat. But we can actually “Schedule” these jobs to run every minute, hour, day, or some combination of the lot. Best of all, we can do all of this with a single configuration file, without the need to write more C# code! You can check out Part 4 right here!

This is part 2 of a series on getting up and running with Azure WebJobs in .NET Core. If you are just joining us, it’s highly recommended you start back on Part 1 as there’s probably some pretty important stuff you’ve missed on the way.


Azure WebJobs In .NET Core

Part 1 – Initial Setup/Zip Deploy
Part 2 – App Configuration and Dependency Injection
Part 3 – Deploying Within A Web Project and Publish Profiles
Part 4 – Scheduled WebJobs
Part 5 – Azure WebJobs SDK


App Configuration Of Our .NET Core Web Job

Previously we managed to get our WebJob all up and running as a simple console application. But the reality is that in almost every application, we are going to want some sort of configuration swap happening when we deploy up to Azure. In full framework we might have done something as simple as a web.config transform, but here we are using appsettings.json, so things are a little different. Let’s get cracking!

I’m not going to explain what each one of these does, but I would just recommend installing all of the following nuget packages into your WebJob/Console Application. Adding these will give you an experience that you are probably used to from building .NET Core web projects.

Now let’s go ahead and create two configuration files in our project. One we will call appsettings.json, and the other appsettings.production.json

Both of these files should be set to “Copy If Newer” so that they are output to the bin directory both when running locally, and when publishing.

The contents of the appsettings.json file will be :

And for our production file :

You can probably see where this is going!

And now we will change the console app code to look a bit like so :

So let’s break this down a little.

First we go ahead and grab the environment available of “ASPNETCORE_ENVIRONMENT”, we’ll look at how we actually set this later. We also write this out to the console just for a bit of debugging.

Next we load configuration files. We load the default appsettings.json, and we load one that will be appsettings.environment.json, where environment is whatever was in the environment variable from earlier. Obviously if we set this to “production”, then we will pull in our production app settings which will override the default file. Perfect!

Finally, we print out the “message” app setting. Locally we see the following output :

Let’s publish our Web Job up to Azure (Using the zip method from Part 1), and see what we get. After uploading, we check the WebJob logging out :

Bleh! That didn’t work, it still thinks we are running in Development?! It’s because we didn’t set the environment variable!

Head to the “Application Settings” configuration panel of your Azure Web App. You need to add the variable “ASPNETCORE_ENVIRONMENT” with the setting of “production”.

If we head back to our WebJob logging output :

Awesome! So now our WebJob has the concept of both configuration, and which “environment” it’s running in so that it can swap configuration out at runtime.

Using .NET Core Dependency Injection

A pretty big part of .NET Core is it’s out-of-the-box dependency injection support. While usage of DI in a quick and dirty console application is probably pretty rare, if you are using shared libraries between the web project and your web job, you are probably going to need it to wire up a couple of services here and there. If you’ve already added DI into a .NET Core console application before, this may not be totally new for you, but it’s still worth stepping through it anyway.

First we need the nuget package that actually has the .NET Core dependency injection classes in it :

Our first point of order is actually going to wire up our configuration properly. Previously when we accessed our configuration, we were doing it on the raw ConfigurationRoot object, which isn’t too great. I personally prefer using POCO’s to hold configuration. So let’s create something to hold our “Message” :

We need to modify our appsettings.json files (Both the default and production) to better match our structure :

Now we need to fire up our service collection, and bind up our configuration. To do this, in our main method of our program.cs. Underneath the configuration setup, add the following :

What this does is it creates a new service collection, and binds our configuration for the IWebJobConfiguration interface. Not that helpful (yet!), but follow on.

Next we are going to do something a little funky. We are going to create a new “Entry Point” for our application. So far all of our setup *and* our actual “work” has been done within the main method of our program.cs. This is fine for now, but what we actually need is an application root that can be the kick off point for our WebJob to actually start. Now I want to point out, that later in this series we are going to move this “Entry Point” and instead use a library that essentially does it for us, but it’s still good to know.

Go ahead and create a class that looks like the following :

Pretty simple, we just have a single method that prints out our configuration message (Remember, this changes depending if we are local or in production).

Now we need to wire this up, we add the following to our main method of our program.cs at the very bottom.

So essentially we are adding WebJobEntryPoint as a service we can build. We are then requesting that service back (Which in the process injects in our configuration), and then we call Run on it. The reason we do this is it provides a way that the more we add into that entry point in terms of dependencies or services, the actual call to “new” everything up doesn’t change. All in all, our main method should end up looking like :

Publish this up to Azure and we get our usual output! Now of course, we haven’t really achieved much in total by adding in dependency injection to our console app, but that’s because this this a simple application without too many dependencies. If we had a much more complicated service layer and a tonne of business logic, especially if it’s buried away in shared DLLs, we wouldn’t have such a headache in getting things up and running.

What’s Next?

So far we’ve been fiddling around with individual console applications that we’ve deployed as zips. Next we are going to take a look at how we might be able to deploy a web job as part of a web application. By that I mean when we deploy out web app to Azure, we automatically push the web job with it. Again this is something that is pretty standard when building Web Jobs in .NET full framework, but does not work straight out of the box when working with .NET Core. You can check our Part 3 right here!

While working on a web project recently that was written in .NET Core, there was a need for a small background task to run either on a timer, or on an Azure queue message. No worries, we can just use an Azure WebJob for that, no extra infrastructure or Azure setup required right? Well, it then occurred to me that I had never actually written a WebJob in .NET Core. What started as a “Oh you just add a WebJob in Visual Studio and you are done” quickly turned into “OK… So I need this specific beta version of this nuget package that a random Microsoft developer mentioned over here”. So here it is, here is how you create an Azure WebJob in .NET Core.


Azure WebJobs In .NET Core

Part 1 – Initial Setup/Zip Deploy
Part 2 – App Configuration and Dependency Injection
Part 3 – Deploying Within A Web Project and Publish Profiles
Part 4 – Scheduled WebJobs
Part 5 – Azure WebJobs SDK


Forewarning

It’s tempting that if you already have a WebJob written in .NET Framework, to skip through this tutorial right to the part where it mentions something specifically related to your existing project. If there is one thing I learned about WebJobs in .NET Core, is that it pays to start with the real basics. I would recommend even if you already know about WebJobs and how they work, to still start on Part 1 and work your way through. Everything from configuration to publishing is totally different than what you might have expected, so even if it feels like we are going right back to Hello World level, it’s worth it to get a total understanding of how WebJobs currently work under .NET Core.

What You Should Already Know

While we may be creating a “Hello World” type WebJob along the way, this is certainly not a beginners series on “what” WebJobs are. Infact, we probably brush over some really important basics that if you’ve never used WebJobs (Or even Azure Web Apps) before, you are going to have a really rough time. This series is more on the .NET Core part, and less on the “How do I use Azure” part. So if you’ve never created an Azure WebJob before, go ahead and create one in the full .NET Framework, have a play, then come back when you are ready to get cracking with .NET Core.

A Console App And Nothing More

Did you know that a WebJob is actually just a console application? Infact I’ve seen people upload diagnostic tools as plain .exe’s as “WebJobs” to an Azure Web App just so they can run a specific tool on the same machine as their web app. For example a tool to spit out what SSL certificates were available on the machine, or what it thought certain environment variables were set to.

So let’s start there. Let’s forget all about the concept of a “WebJob”, and let’s just create a simple console application that runs in an Azure Web App.

First go ahead and create a new .NET Core Console Application. At the time of writing, there are no Visual Studio templates for creating web jobs for .NET Core. So for example you may see below inside VS:

But this is for full framework only. In the grand scheme of things, it’s not a big deal. The VS Template just installs a few nuget packages and gives us some boiler plate code, but realistically it’s just a console application anyway.

So what we want is :

After creating, we are going to have code that looks like the following :

Congrats! You just created your first Web Job. How easy was that! But now how to push things up to Azure. Hmmm.

Kicking Our Job Into Gear

Now let’s say we deploy this as is. Given that .NET Core applications compile down to .dll files, in our publish file we could have multiple .dll files, how will Azure know which one to run? Well, we actually need to give it a nudge in the right direction. The easiest way to do this is to create a “run” file.

The easiest way to explain a run file, is that we take an extension from the following list :  .fsx, .cmd, .bat, .exe, .ps1, .sh, .php. .py, .js  and we create a file called “run” with that extension. So for example, “run.cmd”. Azure checks our WebJob folder for any run file, and kicks it into gear. Also note that .cmd file extension is obviously used for Windows App Services, and .sh for Linux etc.

In the root of your project, go ahead and create a file called “run.cmd” with the contents :

Pretty simple. When we upload our WebJob, it’s going to find our run file, and then use the dotnet SDK to kick off our console app. Obviously replace the .dll filename with your projects dll name, and you are good to go.

Very Important!

Do not create this file in Visual Studio. It creates the file as UTF-8 BOM, and will break the WebJob. Even if you don’t create this file in Visual Studio, you should still check that you are not using BOM. The easiest way is to use Notepad++ and check the encoding on this file. Ensure that it’s set to UTF-8 (Without BOM).

And the second thing is to ensure that the file itself is set to copy to your output directory.

If either of these steps aren’t adhered to, your WebJob can either just fail to start, or Azure will fail the deployment (And silently, I might add) which can be a bit frustrating.

Zip Publishing

Later on in this series we are going to cover a much better way of getting Web Jobs into Azure, but for now let’s just just get things up and running. For that we are going to publish a very simple Zip with our webjob inside it, then just upload via the Azure Portal.

To publish our app, we just run the following in our project directory :

You then need to zip the following folder :  bin\Release\netcoreapp2.1\publish . Note that’s the publish folder not the parent. Once we have all of that zipped up, head over to Azure. If you haven’t already, now would be a great time to spin up a test Azure Web App (Windows) before progressing. I’ll wait…

Now with your Azure Web App in the Azure Portal, select Web Jobs from the side menu, then Add.

Don’t worry too much about the various settings, we can dive into these later. But it should look a bit like the following :

Once uploaded, we now need to check the logs of our WebJob and make sure it’s all working as intended. Select our WebJob from the list (You may need to refresh the list a couple of times after the upload), then select Logs. You should be taken to a screen where you can see the output of your WebJob :

Woop! So it ran and printed out Hello World! Our first WebJob is all go!

What’s Next?

I know the above might not seem like you’ve achieved a lot. I mean it took us probably a good 30 mins just to print Hello World on a log window in Azure, not that fancy right! But everything we’ve done so far will be built upon and give us better understanding of exactly how WebJobs work under the hood.

In future parts in this series, we will cover using .NET Core’s configuration, dependency injection, scheduled jobs, triggered jobs, uploading as part of a web app, and so much more! Check our Part 2 here!

ELO is a player rating system that was first used to rank chess players, but later found a lot of usage in video games, basketball, baseball and many other sports. It’s designed in a way that when underdogs win in a game, they are given more “credit” for their win than if a favourite was to win. For example if chess grandmaster Magnus Carlsen was to beat me (a non ranked player) in chess, it really shouldn’t affect his ranking. And vice versa should someone with a low rating beat the number 1 player in the world, their ranking should shoot up.

ELO is also designed in a way that means a top player can’t just continually play much lower ranked players and keep moving up the rankings at the same rate. It doesn’t mean that matchups don’t exist where a certain “style” of play (depending on the sport/game) means it’s easier or harder than their ELO lets on, but it’s meant to reward underdogs winning a whole lot more than someone picking favourable matchups.

ELO seems like it should be some massively complicated system, but it can really be boiled down to two “simple” equations.

Expectation To Win Equation

The “Expectation To Win” equation is really part of the ELO equation, but it’s worth splitting out because you often may want to see it as a stand alone number anyway.

After passing in two player ratings, we are returned the likelihood of Player 1 winning the match up. This is represented as a decimal (So a result of 0.5 would mean that Player 1 has a 50% chance to win the match up).

Some example input and output would look like :

Player 1 Rating : 1500
Player 2 Rating : 1500
Expectation For Player 1 Win : 0.5 (50% chance to win)

Player 1 Rating : 1700
Player 2 Rating : 1300
Expectation For Player 1 Win : 0.90 (90% chance to win)

ELO Rating Equation

The next step is, given two players compete against each other with a clear winner and loser, what would their new ELO ranking be? The equation for that looks a little bit like this :

Let’s break this down a little.

We pass in our two players ratings, and the outcome as seen by player 1. Once inside, we use a special number called “K”, we’ll talk a little more about this number later, but for now just think of it as a constant. We then take the outcome (Either 1 or 0), and minus out the actual expected outcome of the game. We then add this delta to player one’s rating, and subtract it away from player two. Because we are using the expected outcome as part of the equation, we can reward the underdog for winning more than if the expected winner actually wins. Let’s look at some actual examples :

Player 1 ELO : 1700
Player 2 ELO : 1300
Outcome : Player 1 Wins
Player 1 New ELO : 1702
Player 2 New ELO : 1298
ELO Shift  : 2

Player 1 ELO : 1700
Player 2 ELO : 1300
Outcome : Player 1 Loses
Player 1 New ELO : 1671
Player 2 New ELO : 1329
ELO Shift  : 29

So as we can see, when player 1 wins, they gain only 2 ELO points because they were expected to come out on top (Infact they were expected to win 90% of the time). However when they lose, they pass along 29 points to the loser which is a huge shift. This represents the underdog winning a game they were not expected to win at all.

Finding The Perfect “K”

So in our calculate method, we use a constant called “K”. In simple terms, we can think of this number of how “fast” ELO will change hands. A low number (Such as 10) will mean that ELO will fluctuate rapidly to results. A high ELO (Such as 32) will mean that ELO rankings will be much slower moving. Typically this means that for sports/games that have a low amount of games played per season (Or per career), you may want a rather low number so that results change pretty rapidly. In sports where there are possibly even hundreds of games a year, you would want a lower ELO to reflect that you are expected to lose a few games here or there, but overall you would have to go on a large losing run to really start slipping.

Other times K can change based on either the ELO rating of the players, or the amount of games already played. For example in a new “season”, with few games played, a high K rating would mean that ELO rankings would fluctuate wildly, and then as the season goes on you could lower K to stabilize the rankings. I’m not a huge fan of this as it begins to put more importance on winning games early in the season rather than the end, but it does make sense for new players in a game to be given a lower K so they can find their true ELO faster.

If you take the varying of K based on the ELO rating of the players, you can give a high ELO to lower/mid range ranked players so that they can dig themselves out of the weeds rather fast. Then lower K as you reach higher ELO’s to reflect that at the top of the rankings, things should be a bit more stabilized.

Ultimately, K should be between 10 and 32. And it will totally depend on what you are rating players in to what it should be.

I recently came across the need to host a .NET Core web app as a Windows Service. In this case, it was because each machine needed to locally be running an API. But it’s actually pretty common to have a web interface to manage an application on a PC without needing to set up IIS. For example if you install a build/release management tool such as Jenkins or TeamCity, it has a web interface to manage the builds and this is able to be done without the need for installing and configuring an additional web server on the machine.

Luckily .NET Core actually has some really good tools for accomplishing all of this (And even some really awesome stuff for being able to run a .NET Core web server by double clicking an EXE if that’s your thing).

A Standalone .NET Core Website/Web Server

The first step actually has nothing to do with Windows Services. If you think about it, all a Windows Service is, is a managed application that’s hidden in the background, will restart on a machine reboot, and if required, will also restart on erroring. That’s it! So realistically what we first want to do is build a .NET Core webserver that can be run like an application, and then later on we can work out the services part.

For the purpose of this tutorial, I’m just going to be using the default template for an ASP.net Core website. The one that looks like this :

We first need to head to the csproj file of our project and add in a specific runtime (Or multiple), and an output type. So overall my csproj file ends up looking like :

Our RuntimeIdentifiers (And importantly notice the “s” on the end there) specifies the runtimes our application can be built for. In my case I’m building only for Windows 10, but you could specify other runtime monkiers if required.

Ontop of this, we specify that we want an outputtype of exe, this is so we can have a nice complete exe to run rather than using the “dotnet run” command to start our application. I’m not 100% sure, but the exe output that comes out of this I think is simply a wrapper to boot up the actual application dll. I noticed this because when you change code and recompile, the exe doesn’t change at all, but the dll does.

Now we need to be able to publish the app as a standalone application. Why standalone? Because then it means any target machine doesn’t have to have the .NET Core runtime installed to get everything running. Ontop of that, there is no “what version do you have installed?” type talk. It’s just double click and run.

To publish a .NET Core app as standalone, you need to run the following command from the project directory in a command prompt/powershell :

It should be rather self explanatory. We are doing a publish, using the release configuration, we pass through the self contained flag, and we pass through that the runtime we are building for is Windows 10 – 64 Bit.

From your project directory, you can head to :  \bin\Release\netcoreapp2.1\win10-x64\publish

This contains your application exe as well as all framework DLL’s to run without the need for a runtime to be installed on the machine. It’s important to note that you should be inside the Publish folder. One level up is also an exe but this is not standalone and relies on the runtime being installed.

From your publish folder, try double clicking yourapplication.exe.

In your browser head to http://localhost:5000 and wallah, you now have your website running from an executable. You can copy and paste this publish folder onto any Windows 10 machine, even a fresh install, and have it spin up a webserver hosting your website. Pretty impressive!

Installing As A Window Service

So the next part of this tutorial is actually kinda straight forward. Now that you have an executable that hosts your website, installing it as a service is exactly the same as setting up any regular application as a service. But we will try and have some niceties to go along with it.

First we need to do a couple of code changes for our app to run both as a service, and still be OK running as an executable (Both for debugging purposes, and in case we want to run in a console window and not as a service).

We need to install the following from your package manager console :

Next we need to go into our program.exe and make your main method look like the following :

This does a couple of things :

  • It checks whether we are using the debugger, or if we have a console argument of “–console” passed in.
  • If neither of the above are true, it sets the content root manually back to where the exe is running. This is specifically for the service runtime.
  • Next if we are a service, we use a special “RunAsService()” method that .NET Core gives us
  • Otherwise we just do a “Run()” as normal.

Obviously the main point of this is that if the debugger is attached (e.g. we are running from visual studio), or we run from a command prompt with the flag “–console”, it’s going to run exactly the same as before. Back in the day we used to have to run the service with a 10 second sleep at the start of the app, and quickly try and attach the debugger to the process before it kicked off to be able to set breakpoints etc. Now it’s just so much easier.

Now let’s actually get this thing installed!

In your project in Visual Studio (Or your favourite editor) add a file called install.bat to your project. The contents of this file should be :

Obviously replace MyService with the name of your service, and be sure to rename the exe to the actual name of your applications exe. Leave the %~dp0 part as this refers to the current batch path (Allowing you to just double click the batch file when you want to install).

The install file creates the service, sets up failure restarts (Although these won’t really be needed), starts the service, and sets the service to auto start in the future if the machine reboots for any reason.

Go ahead and create an uninstall.bat file in your project. This should look like :

Why the timeout? I sometimes found that it took a while to stop the service, and so giving it a little bit of a break inbetween stopping and deleting helped it along it’s way.

Important! For both of these files, be sure to set them up so they copy to the output directory in Visual Studio. Without this, your bat files won’t output to your publish directory.

Go ahead and publish your application again using our command from earlier :

Now in your publish directory, you will find your install and uninstall bat files. You will need to run both of these as Administrator for them to work as installing Windows Services requires elevated access. A good idea is that the first time you run these, you run them from a command prompt so you can catch any errors that happen.

Once installed, you should be able to browse to http://localhost:5000 and see your website running silently in the background. And again, the best part is when you restart your machine, it starts automatically. Perfect!