As I have mentioned before, my team and I are working on getting up and running with a new ASP.NET Core 1.0 application. I've spent some time with them going over the new JSON-based configuration files like project.json, global.json, and appsettings.json, and now I'm finally at a point where I can write this post. Let's take a look at the three default JSON configuration files in a new ASP.NET Core application, and see what each of them is responsible for and what new functionality we can expect to be using.

NOTE: This post was written using RC1 (Release Candidate 1) of ASP.NET Core, and as the framework gets closer to final release, some things may change. If they do, I'll do my best to keep this post up-to-date. If you notice anything that needs to be updated, let me know in the comments.

global.json

The first file we should take a look at is in the Solution Items folder, called "global.json":

Our sample project structure, with the global.json files singled out

This file contains settings relevant to the entire solution, specifically what projects are included in said solution and what version of the .NET Execution Environment (DNX) is being used. Here's the contents of that file:

{
  "projects": [ "src", "test" ],
  "sdk": {
    "version": "1.0.0-rc1-update1"
  }
}

The "projects" section specifies the folders which contain projects that are to be included in this solution. In our case, only the "src" folder currently exists, but if we had a "test" folder any projects within it would be included into our solution.

The "sdk" section specifies the version of the DNX that our solution is to be run under. As this post was written when ASP.NET Core was a Release Candidate, you'll see that the version of the DNX in use is "1.0.0-rc1-update1". This value will change for each version of ASP.NET Core released.

There are other sections we can use under the "sdk" section:

  • "runtime": Allows us to specify whether we will run on the ASP.NET 4.6 runtime ("clr") or the ASP.NET Core 1.0 runtime ("coreclr"). If we don't specify this, the app will be compiled for both runtimes.
  • "architecture": Allows us to specify whether this app is run under x86 or x64 computer architectures. The default architecture depends on the runtime selected.

Even better, we now get full Intellisense support in these configuration files:

The next file we need to dive into is the "appsettings.json" file.

appsettings.json

Our sample project structure, with the appsettings.json file singled out.

"appsettings.json" stores the application settings for our program, which were formerly stored in the <appSettings> portion of the web.config file for previous versions of ASP.NET. The default file looks like this:

{
  "Data": {
    "DefaultConnection": {
      "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=aspnet5-ASPNET5Demo-14da7232-82c7-4174-aee7-d8a42c04c5c3;Trusted_Connection=True;MultipleActiveResultSets=true"
    }
  },
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Verbose",
      "System": "Information",
      "Microsoft": "Information"
    }
  }
}

Currently we have two sets of settings, "data" and "logging". These two sets are not special, and you can define any sets you like. The way to access these values from within our code base is covered quite nicely over at docs.asp.net.

This file is, by default, injected into the .NET runtime environment by a line of code in the Startup.cs file:

var builder = new ConfigurationBuilder()  
                .AddJsonFile("appsettings.json")
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

Note the last call to AddJsonFile(). ASP.NET by default allows for us to inject different application settings files based on the current environment. If you're running in the Development environment, and you have a file called "appsettings.development.json", the values in that file will be added to the configuration only when executing in Development. This is how we handle adding different connection strings for different environments. In other words, Environment AppSettings files replace XST Transforms.

There's one last file we should look at, and it's arguably the most important of the three: project.json.

project.json

Our sample project structure, with the project.json file singled out.

The project.json file, in our default ASP.NET Web Application, contains information about how the project is to be built, what dependencies it has, what frameworks it runs on, etc. The default file looks like this:

{
  "version": "1.0.0-*",
  "compilationOptions": {
    "emitEntryPoint": true
  },

  "userSecretsId": "aspnet5-ASPNET5Demo-14da7232-82c7-4174-aee7-d8a42c04c5c3",

  "dependencies": {
    "EntityFramework.Commands": "7.0.0-rc1-final",
    "EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final",
    "Microsoft.AspNet.Authentication.Cookies": "1.0.0-rc1-final",
    "Microsoft.AspNet.Diagnostics.Entity": "7.0.0-rc1-final",
    "Microsoft.AspNet.Identity.EntityFramework": "3.0.0-rc1-final",
    "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
    "Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
    "Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-rc1-final",
    "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
    "Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final",
    "Microsoft.AspNet.Tooling.Razor": "1.0.0-rc1-final",
    "Microsoft.Extensions.CodeGenerators.Mvc": "1.0.0-rc1-final",
    "Microsoft.Extensions.Configuration.FileProviderExtensions" : "1.0.0-rc1-final",
    "Microsoft.Extensions.Configuration.Json": "1.0.0-rc1-final",
    "Microsoft.Extensions.Configuration.UserSecrets": "1.0.0-rc1-final",
    "Microsoft.Extensions.Logging": "1.0.0-rc1-final",
    "Microsoft.Extensions.Logging.Console": "1.0.0-rc1-final",
    "Microsoft.Extensions.Logging.Debug": "1.0.0-rc1-final",
    "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-rc1-final"
  },

  "commands": {
    "web": "Microsoft.AspNet.Server.Kestrel",
    "ef": "EntityFramework.Commands"
  },

  "frameworks": {
    "dnx451": { },
    "dnxcore50": { }
  },

  "exclude": [
    "wwwroot",
    "node_modules"
  ],
  "publishExclude": [
    "**.user",
    "**.vspscc"
  ],
  "scripts": {
    "prepublish": [ "npm install", "bower install", "gulp clean", "gulp min" ]
  }
}

Let's step through each of these sections to better understand what they do.

"version"

The version number of the application. I know, I know, it's positively mind-boggling, but try to contain your enthusiasm, please.

"compilationOptions"

The "compilationOptions" section defines certain options for the project, such as the language version or turning warnings into errors.

"compilationOptions": {
    "emitEntryPoint": true,
    "warningsAsErrors": true,
    "languageVersion": "csharp6"
},

"userSecretsId"

ASP.NET Core includes a secrets configuration system which allows you to store confidential information (e.g. connection strings that use passwords) on your local system rather than checking them in to source control. You can do this by using the Secret Manager tool. Please note that the Secret Manager is still in beta, and could change.

The "userSecretsId" section of project.json is used by the Secret Manager to access application secrets in a secure manner.

"dependencies"

This is, hands-down, the coolest section of this file.

ASP.NET Core 1.0 is completely broken down into NuGet packages, creating a pluggable system that allows you to only use the packages you actually need. The "dependencies" section of the project.json file allows you to tell the DNX what dependencies are required for your app to run. Here's a snippet of the section:

  "dependencies": {
    "EntityFramework.Commands": "7.0.0-rc1-final",
    "EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final",
    ...
    "Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
    "Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-rc1-final",
    "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
    "Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final",
    "Microsoft.AspNet.Tooling.Razor": "1.0.0-rc1-final",
    ...
  },

Each of the dependencies specifies their version number, and we get full Intellisense support here just like we do in the other files. Even better than that, we can get NuGet packages from the NuGet server, and we get Intellisense support for that as well:

But the most amazing thing is that, when we specify a new NuGet dependency and save the file, Visual Studio will automatically attempt to download the NuGet package and include it in our project. NuGet is now seamless, fully integrated into Visual Studio and ASP.NET projects. NuGet all the things!

"commands"

The "commands" section defines DNX commands that can be run from the command line or Visual Studio's Command Window. A command, according to the docs, is a named execution of a .NET entry point with specific arguments. Essentially, the .NET Execution Environment exposes a way to run commands within the environment, and you can define what exactly those commands do in this section.

"commands": {
    "web": "Microsoft.AspNet.Server.Kestrel",
    "ef": "EntityFramework.Commands"
  },

Note the defined "web" command. That command will start a Kestrel web server and begin listening for requests. In other words, the "web" command is a shortcut to getting Kestrel running. The ASP.NET docs have a more in-depth tutorial on using commands, both in the command line and VS's Command Window.

"frameworks"

This section goes hand-in-hand with the "dependencies" section. Here's the JSON for reference:

"frameworks": {
    "dnx451": { },
    "dnxcore50": { }
  },

ASP.NET can now target multiple versions of the .NET Framework, which is nice because the different version do different things (for example, "dnx451" means .NET 4.5.1, which contains the DLLs for WebForms, something that "dnxcore50" doesn't have).

We can use this section to specify that certain dependencies should only when be used when running on certain frameworks (regardless of whether they are framework dependencies or NuGet packages). For example, I could pull down the DLLs for WebForms and the NuGet package for JSON.NET only when using .NET 4.5.1, like so:

"frameworks": {
    "dnx451": {
      "frameworkAssemblies": {
        "System.Web.DynamicData": "4.0.0.0"
      },
      "dependencies": {
        "Newtonsoft.Json": "8.0.2"
      }
    },
    "dnxcore50": { }
},

"exclude"

The "exclude" section of project.json is used exclude folders from the Roslyn compilation search path (StackOverflow source).

"exclude": [
    "wwwroot",
    "node_modules"
],

This means that folders specified in this section will not be compiled (hence why, by default, the folders included are "wwwroot" and "node_modules" both of which contain client-side resources like JS and CSS files and should not be compiled server-side). Simply adding another folder to the "exclude" collection will ensure that Roslyn does not attempt to compile that folder. For example, if you have a "forms" folder that contains PDF files, you probably don't want that folder to be compiled, so you would exclude it by placing it in this collection.

"publishExclude"

Similarly to "exclude", the "publishExclude" section specifies files that should not be published when the app is published.

"publishExclude": [
    "**.user",
    "**.vspscc"
  ],

The use of the ** wildcard indicates that any file, regardless of folder, with the specified extensions should not be published with the site. Right now, this section is just excluding some user- and Visual Studio-specific files.

"scripts"

The "scripts" section specifies commands that will be run at certain points in either the build or publish processes. The section currently defines four commands that run immediately before publishing.

"scripts": {
    "prepublish": [ "npm install", "bower install", "gulp clean", "gulp min" ]
  }

If I wanted to run certain commands immediately after the build, I could use the "postbuild" section, like so:

"scripts": {
    "prepublish": [ "npm install", "bower install", "gulp clean", "gulp min" ],
    "postbuild": [ "command1", "command2" ]
  }

The other possible sections are listed over on docs.asp.net, and most of them are self explanatory.

Others

There are quite a few sections that ASP.NET and Visual Studio understands that are not included in the default project.json file. Of course, we get full Intellisense for these options, so feel free to explore them.

A screenshot of the intellisense options for the project.json file

Summary

The three default JSON configuration files (global.json, appsettings.json, project.json) contain a myriad of configuration options and completely replace the functionality of the old web.config files, as well as providing entirely new features like NuGet integration and full Intellisense support. In particular, I'm digging the Commands and Scripts sections, as now I can automate certain tedious parts of developing a web app (like bundling/minification, etc.).

Is this was useful to you, if you noticed a bug in my code, or if you just need to sound off, feel free to do so in the comments!

Happy Coding!