Choosing between Production and Developing with ASP.NET vNext

One of the things that I want to do in my application is have a choice between Production mode and Development mode. You need to do certain things differently. In development you want BrowserLink and fancy error pages. You want to see your JavaScript and stylesheets. You are used to having a speed penalty because you are debugging. In production, by contrast, you want to load things from a CDN, minify things, and make pretty error pages. I actually want two environment decisions as I want to test the error pages as well.

ASP.NET vNext has this environment variable called “ASPNET_ENV” – you can set it to whatever you want. In debug mode, it’s assumed to be Development. I could use this. I’m tempted to use this. This is the way that the ASP.NET team is telling me I should do things.

But I’m not going to. I like configuration files. I want finer grained control of my output. So I’m going to have a settings file. By consensus this file is called “config.json” and here is my initial version:

{
	"debug": {
		"browserlink": "true",
		"errorpage": "long"
	}
}

I’ve set up this file for development mode. When I’m close to releasing, I’ll switch these settings up for production usage and check it in, then I want to override via environment variables. Now I’ve got my configuration file – how do I use it?

The first step is to load the configuration file and the environment variables on application initialization. The new ASP.NET v5 has a whole section of the FrameWork dedicated to configuration management, so I will use that. I started by bringing in the Configuration framework into my project by adding the assemblies to the project.json file:

	"dependencies": {
		"Microsoft.AspNet.Diagnostics": "1.0.0-beta3",
		"Microsoft.AspNet.Mvc": "6.0.0-beta3",
		"Microsoft.AspNet.Server.IIS": "1.0.0-beta3",
		"Microsoft.Framework.ConfigurationModel": "1.0.0-beta3",
		"Microsoft.Framework.ConfigurationModel.Json": "1.0.0-beta3",
		"Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-beta3"
	},

That’s four additional assemblies. The Microsoft.Framework.ConfigurationModel is the new configuration framework. Microsoft.Framework.ConfigurationModel.Json allows us to read JSON files as well as environment variables. I also mentioned needing to use BrowserLink and error pages. Well, Microsoft.AspNet.Diagnostics contains the code for the error pages and Microsoft.VisualStudio.Web.BrowserLink.Loader contains the code for BrowserLink.

All of this is initialization code and that happens in myStartup.cs file. I need to load our configuration file:

		/// <summary>
		/// Holds the configuration for the web application
		/// </summary>
		public IConfiguration Configuration { get; set; }

		/// <summary>
		/// Application Initialization - loads the configuration we have specified
		/// </summary>
		/// <param name="env"></param>
		public Startup(IHostingEnvironment env)
		{
			Configuration = new Configuration()
				.AddJsonFile("config.json")
				.AddEnvironmentVariables();
		}

The Configuration property just holds what I tell it to load. I initialize in the constructor, first loading my config.json file and then overriding anything with environment variables. I can now handle my two debug changes. These occur in the Configure() function:

			#region Configure BrowserLink
			if (IsEnabled("debug:browserlink", "true"))
			{
				app.UseBrowserLink();
			}
			#endregion

			#region Configure Error Pages
			if (IsEnabled("debug:errorpage", "long"))
			{
				app.UseErrorPage(ErrorPageOptions.ShowAll);
			}
			else
			{
				app.UseErrorHandler("/Home/Error");
			}
			#endregion

Note the use of the IsEnabled() helper function. This is fairly simple code that checks to see if the configuration element exists and if it is set to what I am looking for:

		private bool IsEnabled(string key, string enabledValue)
		{
			var v = Configuration.Get(key);
			if (v != null && v.Equals(enabledValue, StringComparison.CurrentCultureIgnoreCase))
				return true;
			else
				return false;
		}

Running the application will add the BrowserLink and a custom error handler. Check the F12 Developer Tools and you will see that BrowserLink is loading:

browserlink-enabled

Stop the server, change the browserLink value to “false” in the config.json and restart your server. You will note that the BrowserLink has gone from the page.

There is one extra thing I want to do here. I’m not setting the ASPNET_ENV any more. However, I do want to set the EnvironmentName if any of the debug settings are on – just in case a library I depend on uses it to enable or disable debug modes. Once I’ve loaded the configuration file I can simply loop through each debug setting and see if they are on.

		public Startup(IHostingEnvironment env)
		{
			Configuration = new Configuration()
				.AddJsonFile("config.json")
				.AddEnvironmentVariables();

			if (IsEnabled("debug:browserlink", "true") || IsEnabled("debug:errorpage", "long"))
			{
				env.EnvironmentName = "Development";
			}
			else
			{
				env.EnvironmentName = "Production";
			}
		}

There are always “development” vs. “production” things I need to do. With this infrastructure I can decide which development pieces to turn on and which can be turned off. This allows me to fine-tune my debugging environment easily.