This will be the third and last part of our series that will help you to get up and running to do F# development with .NET Core on Linux.

We’ve made this far and all we’re missing are just the finishing touches.

As promised we’ll be looking at how we can link our build, run and debug workflow into vscode.

The editor expects the project’s configuration to be located on a folder called .vscode  at the project’s root folder, containing to 2 files called launch.json  and tasks.json . We’ll be looking at how we can create and update them both manually and automatically.

Build

Let’s start with an easy one, the build task.

Anywhere in the editor just run the default build command ( ctrl+shift+b ) and vscode will let you know that it couldn’t find a build task for the project and it’ll offer you to create one.

We’re going to select ‘Configure Build Task’ and choose ‘.NET Core’

That’s going to create a tasks.json file inside your .vscode folder (which it’ll get created automatically if it didn’t existed). If the .NET Core option doesn’t show up for you, don’t worry, manually create the tasks.json file and paste the following.

Now we’re ready to build our project! Run the build command again ( ctrl+shift+b ) and this time you’ll see the following output.

Run

Now that we’ve set up our build task, adding one for running our project is trivial. Jump again into the tasks.json file and just add another task to the “tasks” array that looks like the following.

Save the file and fire up vscode ‘Quick Open’ ( ctrl+shift+p ), select ‘Tasks: Run Task’ and you’ll see your newly created ‘run’ task. Once you’ve selected it, vscode ‘output’ panel should show something like

Debug

This will be the last thing we add and it is as easy as the other two with a small caveat.

Remember how I mentioned there were going to be two configuration files ? We’ll make use of the other one now. It order to debug, we will not be creating a task but a launch configuration. Automatically creating the configuration file is as simple as pressing F5  and selecting  .NET Core  as our environment. By default this will create the launch.json file with three default configurations, of which we’ll be only focusing on one for this article.

Right now, you might be tempted to re run debug (F5) because you created the configuration but you’ll quickly be prompted with an error message that reads something like

launch: launch.json must be configured. Change ‘program’ to the path to the executable file that you would like to debug

Don’t worry, we’ll sort it out in seconds.

Once you open up your launch.json, you’ll realize that while vscode created the configuration it hasn’t really specified which program it should debug and instead the path for the program contains two placeholders but because we’ve already built our project we can see what values it is expecting, so go ahead and replace <target-framework>  with netcoreapp1.1  and <project-name.dll>  with fsharp_tutorial.dll .

Your “.NET Core Launch (console)” should now look like this

All that is missing now is giving it a try, so just place a break point and hit debug (F5)

And we’re done! We’ve covered the basic setup to get your F# on linux journey started.

You can find the finished project here

This will be the second part of a series of 3 articles that will help you to get up and running to do F# development with .NET Core on Linux.

Ok, for this particular entry we’ll be talking about tools that’ll improve our development experience.

State of the art

Unfortunately, one of the downsides of not developing on Windows is not having access to the excellent Visual Studio IDE but fear not, we’ll be covering a setup that should make us feel at home. Today’s post will focus on Visual Studio Code (vscode), a fantastic open source code editor developed by Microsoft. Sometime in the future we’ll be covering alternative tools, such as the promising Jetbrains Rider IDE and VIM/Emacs.

Now head onto vscode’s download page and install the package corresponding to your favorite distro (both deb and rpm as well as 32 and 64 bits packages are provided).

If you’ve been following our previous entry, you should have a folder fsharp_tutorial , go ahead and open it.

Extensions

The vscode extensions ecosystem is huge and worth spending some time looking at what it has to offer. For the scope of this series, we’ll only be covering one: ionide-fsharp . This extension comes to us thanks to the people at ionide and on top of the one that we’ll be looking at, they provide two more excellent F# extensions that you should check out.

Go ahead and install it, you’ll be prompted to reload the current window to enable it. If you search for it again, you should see something like this

While the out of the box settings should be enough to get you started if you wanted to change something you can find the extension settings under ‘FSharp configuration’ or by searching ‘fsharp’ in the settings page.

Taking it for a ride

We’ll go over a few things now, so open up our Program.fs  file.

First thing we want to do is to add our add function that we used to test F# interactive on our previous post. Assuming things are working as intended, the first thing you should notice is the automatic function type signature displaying on top of our function.

The second thing now will be to test the integration with F# interactive. We can do this in several different way but for this post we’ll use the default ‘send line to fsi’ shortcut which is alt+/ .

Now your function is part of the interactive tool context and can be run.

You can find the rest of the options by opening up quick search ( ctrl+shift+p ) and searching for fsi .

On the next and final entry for the series, we’ll finish setting vscode for building, running and debugging our program.

This will be the first part of a series of 3 articles that will help you to get up and running to do F# development with .NET Core on Linux.

Installing .NET Core

The first thing we want to do is to install .NET core. Microsoft provides us with very easy to follow instructions for your favorite distro here.

Once the installation is over you can quickly check that it went well by running the following command.

Installing F#

At this stage we will be able to create, run and build projects but we still don’t have access to the language itself.

For that we will follow the instructions from the F# Foundation located here. One of the biggest benefits of doing so is to have access to the F# interactive tool, which we’ll use now to verify the installation went well by running the following command.

Taking it for a ride

F# Interactive

Let’s use it write a very simple function to see it in action.

Remember that in the context of F# interactive you need to terminate your instructions with  ;;

Dotnet CLI

The first time you fire up  dotnet it will take a few seconds while it bootstraps and prepares its cache.

We’ll create a new console app project which will be the basis for the series.

This will assume you’re running this command inside a folder called  fsharp_tutorial and that will be the name of our project as we won’t be specifying one.

You should now have 2 new files called  fsharp_tutorial.fsproj and  Program.fs .

Like with any other .NET core project type, we’ll need to restore its packages before can try to do anything useful.

Now we’re ready for the moment of truth as we’ll run our program for the first time.

If you see the above it means that your installation went as intended and we’re ready for our next step in this series which will be setting up our development environment.

Route Constraints can be a handy way to distinguish between similar route names, and in some cases, pre-filter out “junk” requests from actually hitting your actions and taking up resources. A route constraint can be as simple as enforcing that an ID that you expect in a URL is an integer, or as complicated as regex matching on strings.

An important thing to remember is that route constraints are not a way to “validate” input. Any server side validation you wish to occur should still happen regardless of any route constraints set up. Importantly, know that if a route constraint is not met than a 404 is returned, rather than a 400 bad request you would typically expect to see from a validation failure.

Type Constraints

Type constraints are a simple way to ensure that a parameter can be cast to a certain value type. Consider the following code :

At first glance you might assume that if you called “/api/controller/abc” that the route would not match – It would make sense since the id parameter is an integer. But infact what happens is that the route is matched and the id is bound as 0. This is where route constraints come in. Consider the following :

Now if the id in the URL is not able to be cast to an integer, the route is not matched.

You can do this type of constraints with int, float, decimal, double, long, guid, bool and datetime.

Size Constraints

There are two types of “size” constraints you can use in routes. The first is to do with strings and means you can set a minimum length, max length or even a range.

This sets a minimum length for the string value. You can also use maxlength to limit the length.

Alternatively, you can set how many characters a string can be within a range using the length property.

While that’s great for string variables, for integers you can use the min/max/range constraints in a similar fashion.

Regex Constraints

Regex constraints are a great way to limit a string input. By now most should know exactly what regex is so there isn’t much point doing a deep dive on how to format your regex, just throw it in as a constraint and away it goes.

It is worth noting there for whatever reason, the .NET core team added another handy “quick” way of doing alpha characters only instead of regex. There you can just use the constraint of “alpha”.

 

Culture in ASP.net has always been a bit finicky to get right. In ASP.net core there is no exception but with the addition of middleware, things are now configured a little differently. Lifting and shifting your standard ASP.net code may not always work in ASP.net core, and at the very least, it won’t be done in the new “ASP.net Core way”.

It should be noted that there are two “cultures” in the .net eco system. The first is labelled just “Culture”. This handles things like date formatting, money, how decimals are displayed etc. There is a second culture called “UICulture” in .net, this usually handles full language translations using resource files. For the purpose of this article, we will just be handling the former. All examples will be given using datetime strings that will change if you are in the USA (MM-dd-yyyy) or anywhere else in the world (dd-MM-yyyy).

Setting A Default Request Culture

If you are just looking for a way to hardcode a particular culture for all requests, this is pretty easy to do.

In the ConfigureServices method of your startup.cs, you can set the DefaultRequestCulture property of the RequestLocalizationOptions object.

In the Configure method of your app, you also need to set up the middleware that actually sets the culture. This should be placed atleast before your UseMvc call, and likely as one of the very first middlewares in your pipeline if you intend to use Culture anywhere else in your app.

I can write a simple API action like so :

When calling this action I can see the date is output as MM-dd-yyyy (I am from NZ so this is not the usual output!)

Default Request Culture Providers

When you use the request localization out of the box it comes with a few “providers” that you (Or a user) can use to override the default culture you set. This can be handy if your app expects these, otherwise it can actually be a hindrance if you expect your application to be displayed in a certain locale only.

The default providers are :

QueryStringRequestCultureProvider
This provider allows you to pass a query string to override the culture like so http://localhost:5000/api/home?culture=en-nz

CookieRequestCultureProvider
If the user has a cookie named “.AspNetCore.Culture” and the contents is in the format of “c=en-nz|uic=en-nz”, then it will override the culture.

AcceptLanguageHeaderRequestCultureProvider
Your browser by default actually sends through a culture that it wishes to use. A browser typically sends through your native language, but it will throw in a couple of “options”. So for example my browser currently ends through “en-GB and “en-US” (Even though I am in NZ).

This header in particular can become very problematic. If the default culture of your *server* matches the culture that a browser sends. Then by default it doesn’t matter what you set the “DefaultRequestCulture” to, this will override it.

There are two ways to keep this from happening. The first is to tell ASP.net core that the only supported cultures are the one that you want the default to be. You can do this in the ConfigureServices method of your startup.cs.

The second way is to remove the CultureProviders from the pipeline all together.

The second method should be done in anycase if you don’t intend to use them as this makes your pipeline much cleaner. It will no longer be running a bunch of code that you actually have no use for.

Supported Cultures List

If you do intend to allow the user to set their own culture in their browser, you intend to use a query string to define the culture, or you intend to do a custom request culture provider (outlined in the next section) to allow code to set a custom culture based on other parameters, then you need to provide a list of supported cultures.

Supported cultures is a list of cultures that your web app will be able to run under. By default this is set to a the culture of the machine. Even if you use a custom culture provider as outlined below to set a culture, it actually won’t be set unless the culture is in the supported list.

You can set the list as follows :

So in this example, I have set the default localization to “en-US”. But if a user comes through with a cultureprovider that wants to set them to en-NZ, the code will allow this. If for example a user came through with a culture of “en-GB”, this would not be allowed and they would be forced to use “en-US”.

Custom Request Culture Providers

Going beyond hard coding a particular culture, often you will want to set culture based on a particular user’s settings. In a global application for example, you may have saved into a database what datetime format a user wants. In this scenario, you can use a custom RequestCultureProvider class.

The code looks something like the following :

Inside your ConfigureServices method in startup.cs, you then need to add your new CultureProvider to the RequestCultureProviders list. In the below example I have cleared out all other providers as I don’t care about query strings, cookies or the accept language header.

However let’s say that you do care, and if your custom provider can’t sort out a culture you want it to try query strings, cookies and the accept header. Then the best way is to insert it at the start of the list. Remember that these are run in order, the first provider that returns a culture instead of null wins.

Remember! It doesn’t matter what your custom culture provider returns if the culture it tries to set is not in the supported culture list. This is extremely important and the cause of many headaches!

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.

In a previous article we talked about using CSRF Tokens to protect against CSRF attacks. But their main usage was in using the Razor helpers to build a web application in ASP.net Core. But what if you are building a SPA using something like AngularJS? Your forms will no longer have access to the Razor helpers, but you still want to protect against CSRF exploits.

Luckily AngularJS actually has a handy “helper” that will add CSRF tokens as a header automatically as long as it can find a particular cookie. And in actual fact, even though Angular does most of the leg work for us and makes it easy, you can use any flavor of javascript frameworks using this pattern. At the end of the article we even show how you can get up and running using something as plain as jQuery. Let’s jump into it!

Anti Forgery Setup

Later on we will delve into how AngularJS works with CSRF Tokens, but for now what you need to know is that Angular will be sending the token in a header called “X-XSRF-TOKEN”. We need to let our API know this and expect it.

Inside your startup.cs inside your ConfigureServices method, you will need a call to “AddAntiforgery” and we will set the headername inside there.

Setting The Cookie On The Initial Request

Now we need to return a cookie to our front end. There are 2 different ways to do this. You create an endpoint that does nothing more than return a response code of 200 and returns the cookie in the response, or you make it so when your index file is returned, the cookie is returned along with it.

Let’s go with the latter for now.

If you are returning your index file as a C# view, then you will need to inject the IAntiforgery service into your controller, generate a new token, and set it as a cookie. It looks like this :

Now importantly, the cookie name is XSRF-TOKEN and not X-XSRF-TOKEN. The cookie is missing the X on purpose (This catches people out!). And the other important thing is that HttpOnly is set to false on the cookie meaning that javascript is able to read the cookie. Generally speaking, if the cookie holds any sensitive info (Such as authentication cookies), you do not want to do this, but here it’s required.

If you are using a static index.html file that is not returned as a view. You will need to use middleware instead. In your startup.cs file you will have a method called “Configure”. On this method you need to add a parameter called IAntiforgery. Don’t worry too much about the order as this is all worked out using the servicecollection anyway. From there you will want to check if the user is requesting the root file (index.html) and if they are add a cookie onto the response.

Important! This middleware needs to come before the call to UseStaticFiles. The StaticFiles middleware short circuits the pipeline and returns the static file immediately meaning your cookie won’t be set.

Setting The Cookie On Demand

A common scenario is going to be that the API and the front end are actually two seperate websites probably hosted on different boxes. With this in mind you won’t be serving any of the front end code from the API box, so you can’t set the cookie when the index.html file is requested.

In this scenario, you will need to setup an endpoint that will return the token for you. This could actually be after a user logs on, or it could be an endpoint that does nothing more than return a 200 and sets the cookie (Possibly with expiration). It will look something like this :

The front end can call this endpoint at any point to generate a new CSRF token.

Using AngularJS

So what is there left to do in AngularJS? Well… actually nothing.

When $http is used inside Angular, it will now go ahead and look through your browser cookies for something named “XSRF-TOKEN”. If it finds it, it will then add a header to every request called “X-XSRF-TOKEN” to every request. You don’t have to set anything special up inside AngularJS… Phew.

Using jQuery

So jQuery isn’t going to be quite as easy as AngularJS, but the process will still be the same.

We are going to use the handy JS Cookie library that allows us to easily grab out values from Cookies from the front end. Then we are going to take that token and send it as a header with the name X-XSRF-TOKEN.

CSRF or Cross Site Request Forgery is a type of web attack that uses a users own browser to post a form from one site to another. It works like so :

  • User logs into www.mybankaccount.com and receives a cookie.
  • Sometime later the user goes to www.malicioussite.com and is shown a completely innocuous form on the surface. Something like :
  • If a user clicks the submit button. Because they are still logged in and have a cookie, the POST request is accepted

Unsurprisingly Wikipedia actually has a pretty good article on the subject and explains it a little better than I do : https://en.wikipedia.org/wiki/Cross-site_request_forgery

The most common way to protect against CSRF attacks is by using a token that is returned on a GET request for a form, and must be present for a POST request to complete. The token must be unique to the user (Cannot be shared), and can either be per “session” or per “request” based. As always, .net core has done most of the leg work for us.

Generating Tokens

If you build a form using ASP.net core helpers then a CSRF token is automatically generated for you without any extra code required.

So both of these :

and

End up generating a form with a request verification token built in :

If you are building forms without using the ASP.net helpers, then you can generate a token manually :

Validating Tokens

What good is generating tokens if you don’t validate them! There are two filters in ASP.net core to validate tokens as part of the request pipeline :

  • ValidateAntiForgeryToken – This filter validates the request token on each and every method it’s placed on regardless of the HTTP verb (So it validates even on GET requests).
  • AutoValidateAntiforgeryToken – This filter is almost the same, but it doesn’t validate tokens on GET, HEAD, OPTIONS and TRACE requests.

Typically you are going to use the second option. Very rarely are you going to want to validate GET requests, but it’s there if you need it.

You can apply the filters on an entire controller or action by using it as an attribute :

Or you can apply the filter globally if you prefer. In your startup.cs file, find your ConfigureServices method. You should already have a call to AddMvc but you can add a global filter like so :

Adding A Passthrough

You may end up with an endpoint that you actually don’t want to validate CSRF tokens. It may legitimately be receiving POST requests from an outside source. If you have already applied the validate attributes to your controller or globally but need to allow an exception through, you can use the IgnoreAntiforgeryToken attribute on both an Action or a Controller.

 

ASP.net core comes with two ways to do authentication out of the box. The first is using ASP.net cores “identity” service that wraps a MSSQL set of tables and allows you to get every piece of functionality out of the box, but does require you to have a very rigid structure and do things the “Microsoft” way. It also requires you to use a database adapter that has been pre-built (Typically this means using Microsoft SQL). If you are using something like a NoSQL database store to your users, or you authenticate your users using something other than a username password combination, then using the full identity service can be a bit of a pain.

The alternative is to use ASP.net Core’s “Cookie Authentication” which allows you to use cookie based claims for a user, but authenticate the users yourself using your own data store, however that may work. That’s what this article is going to focus on.

Setup

If you are creating a brand new project using Visual Studio for this tutorial, ensure that when creating your project you select the “authentication type” to be none. We essentially want to start with a clean slate.

In your nuget package manager window, install the following package :

In your startup.cs file, find your configure method. You should add the following code to your pipeline but you must ensure this is before your call to “AddMvc”. This is extremely important. Your pipeline runs in the order you have added it so you need to obviously have authorization run before MVC kicks in.

A little bit about the options we have set here.

AuthenticationScheme is just the name we have given this instance of authentication. You can actually have multiple authentication middleware in your application. The name isn’t too important and can be anything if you are only having the single login.

LoginPath is the path to your login page

AccessDeniedPath is the path to a “denied” page

AutomaticAuthenticate means that the middleware runs automatically on every request and tries to authenticate the user

AutomaticChallenge means that a user should automatically be routed to the LoginPage if the user is not authorized.

Registering A User

Using Cookie Authentication as a simple middleware and not using the full identity service means you need to organize registering users and creating them in your data store yourself. There is nothing in the middleware to help you out there.

Logging In A User

For logging in, we will create a simple post model to accept our username and password combination.

I’ve created a controller called “AccountController”. Inside I’ve created a GET and POST endpoint for our model. The GET endpoint returns a view that has a simple form for logging in, the POST endpoint is where we do our work.

Let’s walk through that code a little.

First we validate the user. In our example we just validate every user but obviously in real life this would go away to our data store and validate the user/password combination.

Next we create a Claims list. These are things we know about the user that we wish to store on the cookie. In this example I’ve just stored the Username as the “Name” claim. This one is slightly important as we see later as there is a shortcut to get this name, but you can actually store any key/value combination inside the claims if you don’t want to have to go back to the database each time to get info on the logged in user.

We then build an identity, a principal, and then set the cookie using the SignInAsync method. There is a bit of cruft going on here in terms of building the identity and principal, but the important part is building claims and calling signin.

Authorizing Controllers

Next we obviously need to learn how to “lockdown” certain areas of our website to force a user to have to login. We can do this simply by adding an “Authorize” attribute to any controller.

And that’s all there is to it! Any user that navigates to this controller will be redirected to your “Logon” url.

Logging Our A User

Logging out a user is very simple.

That’s really all there is too it! Remember the Authentication Scheme you use here must match the one you set in the middleware setup.

Viewing The Logged In User

Obviously at some point we will want to view the logged in user, either to get further details about the user from the database or set onscreen elements in a view. Here we have some example code on how we can get both the username we set earlier, and any other claim we may have set.

The Name on the Identity object is just a fancy way of getting the “Name” claim that we set earlier, but for any other claim you can work with the claims list and fetch our data. Remember this will only be set after logging in so null checks should be done along the way.

In ASP.net core there is this concept of “environments” where you set at the machine level (Or sometimes at the code level) what “environment” you are in. Environments may include development, staging, production or actually any name you want. While you have access to this name via code, the main uses are actually to do configuration swaps at runtime. In full framework you might have previously used web.config transforms to transform the configuration at build time, ASP.net core instead determines it’s configuration at runtime.

It should be noted that there are two uses of the word “environment variables” being used here. The first is that “Environment Variables” are used to describe the actual definition of an environment variable on your machine. The second is that you can add an “environment” to that environment variables list to describe what ASP.net Core environment you are using… That may sound confusing but it will all come together at the end!

Setting Environment Variable In Visual Studio

When developing using Visual Studio, any debugging is done inside an IIS Express instance. You can set Environment variables for debugging by right clicking your project, selecting properties, and then selecting “Debug” on the left hand menu. By default you should see that a variable has been added for you called “ASPNETCORE_ENVIRONMENT” and it’s value should be Development.

You can set this to another value (like “Staging”), when you want to debug using another configuration set. It should be noted that editing this value actually edits your “launchSettings.json” and sets the variable in there. It ends up looking like this :

Setting Environment Variable Machine Wide

You will need to set the ASP.net core environment machine wide if…

  • You are not using Visual Studio/IIS Express
  • You are running the website locally but using full IIS
  • You are running the website on a remote machine for staging/production

To set your entire machine to an environment you should do the following :

For Windows in a Powershell window

For Mac/Linux edit your .bashrc or .bash_profile file and add

It should be noted that setting this up machine wide means that your entire machine (And every project within it) is going to run using that environment variable. This is extremely important if you are currently running multiple websites on a single box for QA/Staging purposes and these each have their own configurations. Setting the environment machine wide may cause issues because each site will think they are in the same environment, if this is you, read the next section!

Setting Environment Variable via Code

You can go through mountains of official ASP.net core documentation and miss the fact that you can set the ASP.net Core Environment through code. For some reason it’s a little known feature that makes the use case of multiple websites with different environments live on the same machine.

In your ASP.net core site, you should have a program.cs. Opening this you will see that you have a WebHostBuilder object that gets built up. You can actually add a little known command called “UseEnvironment” like so :

Obviously as a constant string it’s probably not that helpful, but this is regular old C# code so how you find that string is up to you. You could load a text file for example and from there decide which environment to use. Any logic is possible!

Accessing Environment via Code

To access the environment in your code (Such as a controller), you just have to inject IHostingEnvironment into your controller. The interface is already setup by calling “AddMvc” in your ConfigureServices method so you don’t need to add the interface to your service collection manually.

Here is some example code that returns the environment I am currently in :

Swapping Config Based Off Environment

In your startup.cs there is a method called “Startup” that builds your configuration. By default it adds a json file called “appsettings.json” but it can be used to add a file called “appsettings.{environment}.json where environment is swapped out for the environment you are currently running in. The code looks like this :

Any settings in your base appsettings.json are overwritten using your environment specific file.

Configuration itself is a massive topic and Microsoft has already done an incredible job of it’s documentation so head over and read it here.

Naming Conventions Per Environment

Again, another little known “feature” of using environments is that naming conventions can be used to completely change how your application starts. By default, you should have a file called startup.cs that contains how your app is configured, how services are built etc. But you can actually create a file/class called “startup{environmentname}.cs” and it will be run instead of your default if it matches the environment name your app is currently running in.

Alternatively, if you stick with a single startup.cs file, the methods Configure and ConfigureServices can be changed to Configure{EnvironmentName} and ConfigureServices{EnvironmentName} to write completely different pipelines or services. It’s not going to be that handy on larger projects because it doesn’t call both the default and the environment specific methods, it only calls one which could lead to a lot of copy and pasting. But it’s handy to know!