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


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!

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


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


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!

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!

One of the easiest ways to publish your application to Azure App Service is straight from Visual Studio. While not an ideal solution long term or for any team over the size of one, it’s a great way for a solo developer to quickly get something up and running. Most of all, it doesn’t rely on any special configuration, scripts or external services.

Publish via Login

If the Azure account you are publishing to is the same one you use for your Visual Studio account or you have the username/password combination of the Azure account you are publishing to, you can publish direct from Visual Studio.

Inside solution explorer, right click your project and select “Publish”. You want to select “Azure App Service” on the next screen and “Select Existing”. The “Create New” option can be used if you don’t already have an App Service instance already (Rather than creating via the portal) – but we won’t do this this time around.

Click “Publish”. On the next screen you can select your Account, App Service and Deployment Slot to push to. Click “OK” and… that’s it. Really. You should see your project start building, publishing (via Web Deploy), and then Visual Studio will open your browser at the App Service URL.

Publish via Publish Profile

A publish profile is a settings file that holds all information for deploying your code direct to Visual Studio. The only real difference is that the publish profile can be given to you without you having any Azure login credentials yourself. Other than that, the actual deployment is largely the same.

To get a publish profile from the Azure Portal, head over to the dashboard of your App Service. Along the top you should see an option to “Get Publish Profile”.

With this file you are now able to deploy direct from Visual Studio. It’s important that this file is not just left lying around somewhere. With it, anyone can push code to your app service. So while it’s not quite the keys to the kingdom as much as a user/pass combination is, it’s pretty damn close.

Inside Solution Explorer, Right click your project, select Publish. Select “Import Profile” (You may have to scroll to the right to see this option).

Hit Publish! Immediately your project will build, publish and then open your browser at the App Service URL.

Obvious Issues

I touched on it earlier, but I feel the need to point it out further. Publishing from Visual Studio is not a long term strategy. Publishing from Visual Studio cuts out any CI/CD process you have running (If any), it creates possible inconsistencies with what you are deploying (Think “Did you get latest before you published?) and it creates a single point of failure of one developer doing all deployments in teams of more than 1.

That last point is important, while documentation can get some way around this, a single developer being the “release” guy usually creates some “magic” process where only that person can push code.

Again, with a single developer, especially when it’s just a hobby project, it’s less of an issue.

 

Deploying to the Azure App Service through Github is a simple but effective way to deploy websites that don’t require too much ceremony. Because many projects use Github for hosting their Git repositories, it’s a pretty seamless deployment process that is more around point and clicking in the Azure portal rather than having to write complicated deployment scripts.

It should be noted while this post references Github throughout, the exact same process can be used to setup Bitbucket to automatically deploy on a push.

Setting Up Github Deployment In Azure Portal

Setting up a Github Deployment for an Azure Web App Service is nothing more than a point and click process. Inside your App Service on the Azure Portal, select Deployment Options from under the Deployment category.

Select “Setup” on the online menu, and then select your source. In our case either Github or Bitbucket. You should now be able to click “Authorize” and use OAuth to connect your Github/Bitbucket account to Azure. Note that this account will be available for all other Azure App Services, not just this one.

Select your project and branch from the options. Typically your branch can just be master, but if this is a development instance you may want to use your develop branch, or you can even select a particular release branch if you are just using this deployment method as an easy way to push code rather than a continuous deployment strategy.

After connecting, wait 5 minutes for your project to sync up. Note that sometimes you need to go to a different blade in the portal and then head back to see updates (Not the greatest, but it works eventually!)

A great feature is that the deployment engine behind this will only sync files that are changed (Since it can see what has changed inside GIT). This makes deployments much faster than a FTP transfer or similar because it’s only uploading what it needs.

Any pushes to your selected branch will be deployed automatically within seconds, but if you get impatient, you can click the Sync button inside the Deployment Options blade and you should get a deployment going within seconds.

Rollback A Deployment

The Github CD Process allows you to roll back any deployment right from inside the Azure portal. Head to the Deployment Options screen inside your Azure App Service and select the deployment you wish to roll back to.

Select the option to “Redeploy” along the top menu and your previous deployment will be redeployed to production.

Linux App Service

If you are attempting to use Azure App Service with Linux (And now is a good time to be doing so, it’s 50% off!), unfortunately I couldn’t get Continuous Deployment working. Using the exact same Github repository but with a Linux App Service, the deployment failed. I have a sneaky suspicion that is related to the Docker Settings on App Service, but I wasn’t able to get things up and running. Feel free to drop a comment below if you have got it up and running!

With Azure App Service currently being 50% off for Linux, people are taking advantage and halving their .NET core hosting bill. And why wouldn’t you!? Because Azure App Service is fully PaaS, the underlying OS doesn’t make too much of a difference both from a deployment and management perspective.

Most deployment guides floating around the web center on deploying to a Windows App Service, which really isn’t too different to the Linux version, except for one important step. If you have deployed your ASP.net Core code and are not seeing anything when you visit your website in a browser, read on.

Docker Startup File

Linux App Service actually runs Docker under the hood. To get everything starting correctly you actually need to set a “startup file”. This is essentially the entry point for your app.

Inside the Azure Portal, inside your App Service, under the Settings category, find the option for “Docker Container”. Here is where you can set the runtime stack, but more importantly, your startup details.

For a dotnet project, the startup file line should read :  dotnet /home/site/wwwroot/{yourdllhere}

Where yourdllhere is the DLL of your main web project in your deployment. In practice it should end up looking a bit like this :

Once saved, you should head back to the app service dashboard and restart your service. It does take a while to boot up first time, so wait 5 minutes and give it a spin!

A quick and easy way to get your code up and running on Azure App Service is to upload your code using FTP. FTP can be as simple as a drag and drop process from your desktop, or as complicated as having your CI/CD pipeline run an FTP client for you. While it’s not an ideal scenario for large scale deployments due to the individual uploading of files one at a time, it’s a good starting point if you are just looking to have a play with Azure without too much fuss.

Setting Up FTP In Azure Portal

After creating your App Service, FTP may not be immediately available if you have never used it to deploy applications before. Deployment credentials, while they are viewable under a particular app service plan, are actually for the entire Azure account. So if you have *ever* used FTP or GIT to deploy apps before, the credentials will already be set and you should use those same ones. Resetting the credentials, even if you only do it within one app service, will reset them account wide.

Thankfully this is easy to check. Head over to your app service overview screen, if on this page you have an FTP deployment username showing, then you or someone else has already set up credentials.

If you don’t see anything here, then you will need to scroll down to the Deployment section, you should see an option for “Deployment credentials”.

Enter in a username/password combination you would like to use for FTP. Again, I cannot stress enough that this will be used on all FTP deployments for the entire account, not just this one app service plan.

Publishing Your ASP.net Core Web Project

Because App Service in Azure has a runtime installed, publishing your app is a one line job.

Open a command prompt in your project directory and run the following :

Heading to “bin\Release” you should see your published project for your .net core runtime (netcore1.0 or netcore1.1).

Uploading Your ASP.net Site

Back on your App Service overview, you should have a FTP hostname to connect to using your favourite client (I use Filezilla). After connecting, make your way to /site/wwwroot.

Upload your entire published app to the wwwroot.

Docker Settings For Linux App Services

Linux App Service plans are currently 50% of the Windows price right now, and given it’s a PaaS service, it really doesn’t make a huge difference what the underlying OS is. If you are using Linux, you will need one extra step to get going.

On the app service menu, under the Settings category, there should be an option for “Docker Container”. Here you can select your runtime stack but more importantly, you set the “entry” DLL for dotnet. Set the startup file to “dotnet /home/site/wwwroot/{yourdllhere}”.

Head back to the app service dashboard and restart the service. Wait 5 minutes and hit your URL and you should be up and running!

Pretty much any project that allows file uploads is going to utilize some cloud storage provider. It could be rackspace, it could be GCloud, it could be AWS S3, or in this post’s case, it’s going to be Azure Blob Storage.

Using Blob Storage in .net core really isn’t that different to using it in the full framework, but it’s worth quickly going through it with some quickfire examples.

Getting Required Azure Details

By this stage, you should already have an Azure account set up. Azure has a free tier for almost all products for the first year so you can usually get some small apps up and running completely free of charge. Blob Storage actually doesn’t have a free tier, but if you upload just a single file it’s literally cents to store a GB of data. Crazy. I should also note that if you have a MSDN subscription from your work, then you get $150 a month in Azure credits for the lifetime of your MSDN subscription.

Once you have your account setup, you need to head into the Azure portal and follow the instructions to create a storage account. Once created, inside your storage account settings you need to find your access keys.

The end screen should look like this (Minus the fact I’ve blurred out my keys) :

Write down your storage name and your keys, you will need these later to connect via code to your storage account.

Project/Nuget Setup

For this tutorial I’m just working inside a console application. That’s mostly because it’s easier to try and retry things when we are working on something new. And it means that we don’t have to fiddle around with other ASP.net boilerplate work. It’s just open our main and start writing code.

Inside your project, you need to run the following commands from your Nuget Package Manager.

This is all you need! It should be noted that the same package will be used if you are developing on full framework too.

Getting/Creating A Container

Containers are just like S3 Buckets in Amazon, they are a “bucket” or “collection” to throw your files into. You can create containers via the portal and some might argue this is definitely safer, but where is the fun in that! So let’s get going and create our own container through code.

First, we need to create the object to hold all our storage account details and then create a “client” to do our bidding. The code looks a bit like this :

When we create our storage credentials object, we pass it in the account name and account key we retrieved from the Azure portal. We then create a cloud storage account object – the second param in this constructor is whether we want to use HTTPS. Unless there is some specific reason you don’t… just put true here. And then we go ahead and create our client.

Next we actually want to create our container via code. It looks a bit like this :

That container object is going to be the keys to the world. Almost everything you do in blob storage will be run off that object.

So our full C# code for our console app that creates a container called “mycontainer” in our Azure Cloud Storage account looks like the following :

It’s important to note that every remote action in the storage library is async. Therefore I’ve had to do a quick wrap of an async method in our main entry point to get async working. Obviously when you are working inside ASP.net Core you won’t have this issue (And as a side note, from C# 7.1 you also won’t have an issue as they are adding async entry points to console applications to get around this wrapper).

Running this code, and viewing the overview of the storage account, we can see that our container has been created.

Uploading A File

Uploading a blob is incredibly simple. If you already have the file on disk, you can upload it simply by creating a reference to your blob (That doesn’t exist already), and uploading.

You can also upload direct from a stream (Great if you are doing a direct pass through of a file upload on the web), or even upload a raw string.

The important thing to remember is that in the cloud, a file is just a blob. While you can name your files in the cloud with file extensions, in the cloud it really doesn’t care about mimetypes or anything along those lines. It’s just a bucket to put whatever you want in.

Downloading A File

Downloading a file via C# code is just as easy.

Similar to uploading a file, you can download files to a string, stream or byte array also.

Leasing A File

Leasing is an interesting concept and one that has more uses than you might think. The original intent is that while a user has downloaded a file and is possibly editing it, you can ensure that no other thread/app can access that file for a set amount of time. This amount of time is a max of 1 minute, but the lease can be renewed indefinitely. This makes sense and it means if you are building some complex file management system, it is definitely handy.

But actually leasing has another great use and that is handling race conditions across apps that have been scaled out. You might typically see Redis used for this, but blob storage also works too.

Consider the following code :

When the second AcquireLease runs, an exception is thrown that a lease cannot be obtained – and can’t be obtained for another 30 seconds. A full rundown on using leasing is too much for this post, but it is not too much work to write code that can acquireleases on a blob, and if a lease cannot be obtained, do a spin wait until a lock can be obtained.

AWS Lambda is usually seen as a way for small, short functions to be run in the cloud. Usually small backend processes like resizing images or reading messages from a queue and processing them. But you can actually deploy an entire API on Lambda, and not only that, you can deploy an existing ASP.net Core API with very little extra effort.

It’s not always going to be the right architecture to be running a full API in Lambda, but if your API is being called infrequently and doesn’t need to be chewing resources 24/7, it might be a real cost saver.

Setup

If you haven’t done already, you need to install the AWS Tooling For Visual Studio 2017. Make sure VS2017 is closed while you install this. When opening Visual Studio again, you will see a window asking you to type in a few AWS credentials, follow the instructions to do so. This is mostly for deployment purposes from Visual Studio (Which this tutorial uses), but isn’t strictly required long term if you don’t want Visual Studio having access to your AWS account all the time.

For this tutorial, I’m creating a standard .net core API project in Visual Studio 2017 (The one that has the “valuescontroller” and nothing else). You can either create a new project to follow along or use your existing project, it’s up to you.

With your project open, you need to install the Amazon.Lambda.AspNetCoreServer nuget package. It’s currently in preview only at the moment so the command you need to run from your package manager console is the following :

One of the most frustrating bugs/issues in Visual Studio is that you can’t add CLI Tooling that lives in Nuget via the nuget package manager (See bugs like the following : https://github.com/aspnet/Scaffolding/issues/422). So you need to manually open up your csproj file of your project. In the ItemGroup for your Packages, add the following line :

And in your ItemGroup for DotNetCliTools add the following :

My complete csproj looks like the following if you get lost. This is just the standard .net core api project with the above nuget packages installed.

Code Changes

Add a class in your project named “LambdaFunction”, it should inherit from the abstract class “APIGatewayProxyFunction”. The code of this class should look like :

The biggest thing people ask when they hear about Lambda is “How can I test that locally?”.

Our LambdaFunction above is our entry point for AWSLambda, but you will notice that it’s pretty damn close to how our program.cs file looks in an ASP.net core project. When you run locally, our program.cs bootstraps Kestrel/IIS and starts hosting on our local machine. When you run in AWS Lambda, it doesn’t call Program.cs, it instead calls the code above and bootstraps everything for us, but the underlying code of controllers, services, pipelines etc are all the same. That means for the most part, the site locally and inside Lambda should function more or less identically.

Add a new JSON file to your project and name it “aws-lambda-tools-defaults.json”. This file holds a bunch of defaults when publishing from Visual Studio so you don’t have to type them over and over. Open up the file and enter the following :

The important thing to change here is the “function-handler”. The actual contents of this setting should be “{AssemblyName}::{LambdaFunctionName}::{FunctionHandler}”. In my case I named my project AWSApiExample, so you will need to swap this out for your project’s name. The “FunctionHandlerAsync” part is because our entrypoint that inherits from “APIGatewayProxyFunction” actually implements a methoid called “FunctionHandlerAsync” behind the scenes.

Another quick note is that I’m deploying this to the us-west-2 region, obviously change this if another region suits you better,

Deployment

Deployment could not be simpler! Right click your project and select “Publish To AWS Lambda”.

You should be given a screen to type in a few details, including naming your Function. Fill these out (Most should already be filled out), and be sure to tick the box that says it will save your settings. This actually just saves back to our json file from the last step, so you don’t have to pre-build that JSON file, but it’s much easier to copy and paste it in and just change the few details you need to. Click Next.

For permissions, if you have never used Lambda before (And don’t have a role for it), create a new role with the AWSLambdaFullAccess policy. Everything else on this page just leave default unless you know what you are doing!

Press upload and you should see your app be published up to AWS. Normally this would be the end of a normal lambda function publish, but now we need to setup our API Gateway. The API Gateway in Amazon simply acts as a proxy between the public and your Lambda. It can handle complex scenarios such as authorization, headers inspection etc, but we will actually be using it more or less as a straight pass through.

Open up your AWS Dashboard in your browser and head over to the API Gateway services screen. Go ahead and create a new API, name it whatever you like.

On the next screen, (Resources section of your new api), select the Actions dropdown and hit Create Resource. Here is where we basically create a wildcard pass through to our Lambda function. Tick the box that says “Configure as proxy resource” and leave everything else as is.

The next screen asks what you actually want to proxy to. Select Lambda Function Proxy, and select the region you deployed your Lambda function to. The most infuriating thing is that you have to type your function name here (Why can’t it just be a drop down!). Hopefully you remember what you deployed your function as (If not, in the AWS dashboard quickly pop over to the Lambda section and jog your memory).

Still in the Resources section. Select the Actions dropdown again and select “Deploy API”. A popup will come up, select new stage and type in “prod” as your stage name for now.

After hitting deploy, you will be given an “invoke” URL. I open my url and add on the end /api/values (Since I’m using the default .net Core API template). And what do you know!

So as we see, we can take an entire API and lift and shift it to Lambda. Again, I’m not really sure whether this makes total sense to do and I can’t see it being a hugely popular move, but it can be done (And fairly simple at that!).