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 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 and receives a cookie.
  • Sometime later the user goes to 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 :

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 core helpers then a CSRF token is automatically generated for you without any extra code required.

So both of these :


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

If you are building forms without using the 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 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.


The web has been going ballistic over a proposed Core change.

Exhibit A : Core was now going to run solely on…. .net core. Sounds confusing? Keep reading.

It’s been interesting to read reaction on message boards such as Reddit and HN. Mostly because people take the opportunity to lay the smack down on Microsoft without full understanding the situation. Certainly if you don’t use .net core on a daily basis, it just looks like Microsoft doing whatever it wants developers be damned.

But here’s the thing. I actually agree with Microsoft on this one to a certain degree. And I actually think their eventual decision to not press forward with the changes could actually hurt core in the long run. This post is a bit of a riff off a Reddit comment I also made so it may be a bit over the place.

Let me explain.

There is currently 3 (main) ways to write a web application in the .net ecosystem

  • Core
  • Full Framework
  • Core running on Full Framework

That last one is probably the eye brow raiser and the one that sounds the most “cobbled together”. And it’s actually the one that everyone is fighting over.

You see you can actually run Core on the full framework. You get all the benefits that the Core team gives you (Kestrel etc), but you still have the ability to use full framework libraries. Sounds like a win win right? Kinda.

The reason this works is because Core is written against .net standard. That means any classes/methods it calls will also be available in full framework. But it also limits the ability for Core to innovate. They are restricting their own platform to keep the ability of running on the full framework.

So how does the .net standard work? There is another article on this site talking about the standard in general over here, but I’ll do my best to explain it in the context of the Core 2.0 debacle.

.net standard is essentially an agreement between the various .net platforms (UWP, .net Full Framework, .net Core, Mono etc), that they will all implement the same functionality. Think of it like an interface where a class can write an implementation of a method however they like, but the important thing is that they implement it in the first place. The issue with the standard as it is today is that everyone has to move together. If the .net core team says “OK, we would like this new thing in the standard please”, they have to wait for agreement from another platform to put it into the standard and implement on their end too (Usually this is going to be from the full framework team).

The problem that the core team is facing right now is that they have almost zero baggage and can move at an extreme pace. They are able to innovate and throw things into their platform as fast as a developer can code really. That’s why people are using core running on full framework, because they are enjoying the performance improvements that core offers. But for them to keep improving AND for core to keep supporting the ability to run on full framework, they need the full framework to add things almost as fast so that new versions of the .net standard can be released.

That’s not happening.

And what that means is that if Core writes a new feature that utilizes something that is NOT in the .net standard at that point, they cannot actually release it until the .net framework catches up. The Core team has basically said that for them to keep moving at the same pace, they are going to have to make their libraries work on .net core only so that their only limitation to releasing new features is their own ability to write them.

To me that’s understandable. They probably need some sort of pathway for those that have been caught in the middle of this hybrid approach. But we can’t have a web framework that everyone loves for it’s ability to innovate be tied down by a legacy frameworks ability to do the same.

Microsoft has backtracked and said that they will continue supporting core running on the full .net framework. I think it will be interesting a year from now to see how this pans out. Giving something like another years support seems look a good plan, but I don’t like the open ended support “we will see in a year” type approach.

What’s your thoughts? core comes with two ways to do authentication out of the box. The first is using 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 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.


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.

Microsoft has released an urgent patch to various packages in .net core. If you are using any of the following packages directly, or any packages you use are also dependent on these packages you should update them immediately. You can read the full advisory on Github here.

Package Affected Versions Fixed Versions
System.Text.Encodings.Web 4.0.0
System.Net.Http 4.1.1
System.Net.Http.WinHttpHandler 4.0.1
System.Net.Security 4.0.0
System.Net.WebSockets.Client 4.0.0
Microsoft.AspNetCore.Mvc 1.0.0, 1.0.1, 1.0.2, 1.0.3
1.1.0, 1.1.1, 1.1.2
Microsoft.AspNetCore.Mvc.Core 1.0.0, 1.0.1, 1.0.2, 1.0.3
1.1.0, 1.1.1, 1.1.2
Microsoft.AspNetCore.Mvc.Abstractions 1.0.0, 1.0.1, 1.0.2, 1.0.3
1.1.0, 1.1.1, 1.1.2
Microsoft.AspNetCore.Mvc.ApiExplorer 1.0.0, 1.0.1, 1.0.2, 1.0.3
1.1.0, 1.1.1, 1.1.2
Microsoft.AspNetCore.Mvc.Cors 1.0.0, 1.0.1, 1.0.2, 1.0.3
1.1.0, 1.1.1, 1.1.2
Microsoft.AspNetCore.Mvc.DataAnnotations 1.0.0, 1.0.1, 1.0.2, 1.0.3
1.1.0, 1.1.1, 1.1.2
Microsoft.AspNetCore.Mvc.Formatters.Json 1.0.0, 1.0.1, 1.0.2, 1.0.3
1.1.0, 1.1.1, 1.1.2
Microsoft.AspNetCore.Mvc.Formatters.Xml 1.0.0, 1.0.1, 1.0.2, 1.0.3
1.1.0, 1.1.1, 1.1.2
Microsoft.AspNetCore.Mvc.Localization 1.0.0, 1.0.1, 1.0.2, 1.0.3
1.1.0, 1.1.1, 1.1.2
Microsoft.AspNetCore.Mvc.Razor.Host 1.0.0, 1.0.1, 1.0.2, 1.0.3
1.1.0, 1.1.1, 1.1.2
Microsoft.AspNetCore.Mvc.Razor 1.0.0, 1.0.1, 1.0.2, 1.0.3
1.1.0, 1.1.1, 1.1.2
Microsoft.AspNetCore.Mvc.TagHelpers 1.0.0, 1.0.1, 1.0.2, 1.0.3
1.1.0, 1.1.1, 1.1.2
Microsoft.AspNetCore.Mvc.ViewFeatures 1.0.0, 1.0.1, 1.0.2, 1.0.3
1.1.0, 1.1.1, 1.1.2
Microsoft.AspNetCore.Mvc.WebApiCompatShim 1.0.0, 1.0.1, 1.0.2, 1.0.3
1.1.0, 1.1.1, 1.1.2

Fixing Direct Dependencies

To fix direct dependencies, you should simply open your csproj file for your project and check package references for the ones above. If you find any, then you should update to the fixed package version and redeploy immediately if your project is in production.

For example if you had the following csproj file :

The package for Microsoft.AspNetCore version 1.0.3 is vulnerable. Update the version to 1.0.4.

Fixing Transitive Dependencies

Transitive dependencies are dependencies of libraries that you are directly using. These are harder to track down but still simple to fix.

Open your project.assets.json file for your project (Should be in your project folder). Search inside this file for any dependencies that match the vulnerable package list above. If you find a vulnerable package, you need to manually add a reference to the fixed package in your csproj. The csproj version will override any transitive dependencies from other libraries (think of it like version forwarding in web.configs).

Fixing Project.Json (Legacy .net Core Apps)

If you have a .net core web app that is still on project.json, the process is much the same. For more info read the full advisory on Github here.

Migrating a project.json .net core project to the latest csproj format can be a bit of a minefield. There are a few gotchas and even best practices that you likely did when using a project.json based project that will actually make the migration to csproj fail.

But first, why should you not upgrade :

  • Your team is not ready to use Visual Studio 2017 (e.g. no licenses). csproj based projects can only be opened in Visual Studio 2017, they cannot be opened in Visual Studio 2015
  • Your team is using another IDE such as Jetbrains Ryder that does not have support (Or complete support yet) for csproj based projects.

If those aren’t you, then it is really a no brainer to upgrade your project to the latest .net core tooling.

One important thing to note is that tooling is not the same as the .net core version. Tooling refers to things like project.json vs csproj and how the .net core CLI works. It does not refer to the version of .net core (1.0 or 1.1). Updating the tooling does not change the version of the actual .net core runtime!


You should go ahead and download the latest .net core SDK. If this is your first time doing this you should first read this article on how to run two versions of the .net core SDK side by side. This is really important if you intend to work on both project.json and csproj projects on the same machine for some time as you could end up not being able to open projects without the right global.json setup.

On the project you wish to migrate, check the root of your project/solution for a global.json file. This file is used to determine which SDK to use but annoyingly can cause havoc when you are trying to migrate. The reason being when you wish to migrate, you want to be able to run the migrate command using the latest tooling, but the global.json may point to an older version. If you try to migrate with this going on you will see the following error message :

Take a backup of the global.json and delete it from the root folder.

Using the Command Line

The command we are going to run from the command line is “dotnet migrate“. If we move our command line to the solution directory and run it, it will recursively move down into our projects and migrate them all to the csproj format.

It really is as simple as that!

Remember to create a global.json file in the root of our directory specifying what tooling version we are now on. This is actually an un-needed step realistically, but if you upgrade your tooling again on your machine you will want this project to be unaffected. It’s also handy when setting up a new developers machine to be able to remember which version of the SDK you actually need!

Rolling Back

There is no CLI command to “migrate down” a .net core project, but you can rollback manually. Inside each project directory you will find a backup folder with your original project.json file. You can pull this out and replace the csproj files with your project.json files again. Remember that after moving back to project.json, you will need to create/update your global.json file with the correct SDK versioning so it is able to be opened by Visual Studio 2015 again.

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 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.


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 : 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 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 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!).

In 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, 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 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 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 core documentation and miss the fact that you can set the 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 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!

In 99% of cases, static files you want served for your website will be able to live in the wwwroot folder. But in that rare 1% use case that you need to have static files littered throughout your project (Or you dislike having a wwwroot folder nonstop!), what can you do?

First off, you will need the StaticFiles nuget package to be able to serve files at all. So run the following from your nuget package manager :

In your startup.cs, you would typically see something similar to the following where the “UseStaticFiles” call allows you to serve files from your wwwroot folder :

But you can actually add multiple calls to StaticFiles each with it’s own file location :

We leave the original StaticFiles call in there so that the wwwroot is still used to serve static files if we want (Although if you are intending to never use it, you can remove that call completely), but we can add subsequent calls to the middleware for each additional static content folder.

The FileProvider parameter tells the middleware where it can find the physical files, and the RequestPath is the actual URL that a browser should go to to reach the static files. In this example if we we went to something like, we would be served static files.

Modifying the RequestPath can come in handy, consider the following :

In this example our physical folder hasn’t changed, but the request path is now simply /js rather than /content/js. You can use this to essentially rewrite public urls for your static content (Which can come in handy if you end up moving around the actual physical folder).

If you’re up to date on your dotnet tooling, then you are probably using the very latest Dotnet Nuget command (dotnet add package). And then on top of that you are wondering where the hell are all your packages, and where is your packages.config? I know atleast for me it was extremely confusing adding a nuget package and not seeing a packages folder fill up. So let’s run through some of the changes.

What Is The Dotnet CLI Command “dotnet add package” Actually Doing?

So when you run the command “dotnet add package”, what is it doing under the hood? Well actually, when it boils down to it, it’s actually just forwarding your command to the “nuget.exe” anyway. If you dig into the source code eventually you end up at a class called “NugetForwardingApp” (Source) that takes your dotnet command and transforms it to the original nuget command anyway. This makes sense as nuget will still be used with the .net full framework so it’s pointless for the .net core team to completely rebuild a package manager from scratch right?

As a side note, you’ll often find this with dotnet CLI commands. Often they are just a wrapper or a skin over things like nuget or msbuild to make your life a little easier (Because who hasn’t wasted a day trying to get a finicky msbuild command to work!).

Where Is My packages.config?

Previously when you added a nuget package, you would end up with a packages.config file in the root of your project directory that told nuget what dependencies you had. You’ll quickly notice that this is not the case anymore, so where are your dependencies defined? In the .csproj of course. Let’s say I create a new project with a reference to EntityFramework, my csproj would look a bit like the following :

The csproj format that is used for .net core projects is now very very clean, so it makes viewing your dependencies as easy as viewing your packages.json. The other benefit is that you have all your dependencies in a single file. When you add project references (Or hardcoded DLL references), it’s all contained within the csproj.

Where Is My Packages Folder?

You are probably used to having a packages folder in your solution that holds the nuget downloads. This is now gone and been replaced by a global packages folder. By default this is located at “%userprofile%\.nuget\packages”. Opening this folder the first time might give you a heart attack with how much is in here, and I suspect that “cleaning” this folder in the future is going to be the fix for various bugs.

It certainly makes sense to have a global folder on some levels though as for many projects you will be using the exact same version of the same library across many projects. With core itself being inside nuget, it also makes sense to not have to download this over and over for each project.

It’s also important to note that the location of “%userprofile%\.nuget\packages” is just the default, you are able to edit your nuget.config either on the global level or per project level to specify another location. But be aware if you do this on the project level and give each project it’s own packages folder, you will download all of core into that packages folder all over again.

What Happens When I Publish?

When it comes to publishing, there is really nothing to worry about. When you publish, .net core works out what packages you need and moves them into your publish destination folder for a stand alone solution. You don’t for example need this packages folder on your server, it’s only for development purposes.

Editing Nuget.config

As discussed earlier, you can edit your nuget.config file to change your local global cache location, add nuget feeds, and configure other settings such as HTTP Proxies, default package versions etc. The Microsoft documentation for editing your nuget.config can be found here. A handy tip to generating a nuget file at the project level is the following command from a command line/bash/terminal.

Be aware that adding a nuget file at the project level (even a completely empty one) can have bad side effects. I’ve found that settings don’t exactly “fall through”, e.g. If a setting is missing from the project level nuget.config, it doesn’t then go to the global config, it just treats it as false/missing etc.