Working with Environments and Launch Settings in ASP.NET Core

I'm continuing my series of deep dives into ASP.NET Core, on my never-ending quest to keep my coding career from becoming obsolete. In this part of the series, let's discuss a new feature in ASP.NET Core that will make debugging and testing much more intuitive and pain-free: Environments and Launch Settings.

ASP.NET Core includes the native ability to modify how an application behaves (and what it displays) based upon the environment it is currently executing in. This ends up being quite useful, since now we can do things as simple as not showing the error page to people using the application in a production environment. But it requires just a tiny bit of setup, and some knowledge of how environments are controlled.


At the heart of all the stuff ASP.NET Core can do with environments is the ASPNETCORE_ENVIRONMENT environment variable. This variable controls what type of environment the current build will run in. You can edit this variable manually by right-clicking your project file and selecting "Properties", then navigating to the "Debug" tab.

There are three "default" values for this variable:

  • Development
  • Staging
  • Production

Each of those values corresponds to certain methods we can use in our Startup.cs file. In fact, the Startup.cs file includes several extension methods that make modifying our application based it's current environment quite simple.

Selecting an Environment

The Startup.cs file that every ASP.NET Core application needs does many things, not the least of which is setting up the environment in which the application runs. Here's a snippet of the default Startup.cs file that was generated when I created my sample project for this post:

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)  

    if (env.IsDevelopment())


    app.UseMvc(routes =>
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");

Notice the IHostingEnvironment variable. That variable represents the current environment in which the application runs, and ASP.NET Core includes four extension methods that allow us to check the current value of ASPNETCORE_ENVIRONMENT:

  • IsDevelopment()
  • IsStaging()
  • IsProduction()
  • IsEnvironment()

Notice what we're setting up in the Startup.cs file: if the current environment is Development, we use the Developer Exception Page (which was formerly the Yellow Screen of Death) as well as enabling Browser Link in Visual Studio, which helps us test our application in several browsers at once.

But we don't want those features enabled in a Production environment, so instead our configuration establishes an error handling route "/Home/Error".

This is the coolest thing about this feature: you can decide what services are enabled for your application in each environment without ever touching a configuration file!

However, what if you need more environments? For example, at my day job we have up to four environments: Development, Staging, Production, and Testing, and very often I'll need to change application behaviors or display based on which environment it's currently running in. How do I do that in ASP.NET Core?

The launchSettings.json File

ASP.NET Core 1.0 includes a new file called launchSettings.json; in any given project, you'll find that file under the Properties submenu:

This file sets up the different launch environments that Visual Studio can launch automatically. Here's a snippet of the default launchSettings.json file that was generated with my demo project:

  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
    "CoreEnvironmentBehaviorDemo": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"

At the moment we have two profiles: one which runs the app using IIS Express and one which runs the app using a command-line handler. The interesting thing about these two profiles is that they correspond directly to the Visual Studio play button:

In other words: the launchSettings.json file controls what environments you can run your app in using Visual Studio. In fact, if we add a new profile, it automatically adds that profile to the button, as seen on this GIF I made:

All this together means that we can run the app in multiple different environment settings from Visual Studio, simply by setting up the appropriate launch profiles.

The Environment Tag Helper

Quite a while ago I wrote a post about Tag Helpers and how awesome they are, and I want to call out a particular helper in this post: the <environment> tag helper.

With this helper, we can modify how our MVC views are constructed based upon which environment the application is currently running in. In fact, the default _Layout.cshtml file in Visual Studio 2015 comes with an example of this:

<environment names="Development">  
    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>
<environment names="Staging,Production">  
    <script src=""
    <script src=""
            asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal">
    <script src="~/js/site.min.js" asp-append-version="true"></script>

In this sample, when we run the app in Development mode we use the local files for jQuery, Bootstrap, and our custom Javascript; but if we're running in the Staging or Production environments, we use copies of those libraries files found on the ASP.NET content delivery network (CDN). In this way, we improve performance, because a CDN can deliver these static files from one of many centers around the globe, rather than needing to round-trip all the way to the source server to get those files.

But, remember, in our sample we have the custom environment Testing. The environment tag helper also supports custom environments:

<div class="row">  
    <environment names="Development">
        <span>This is the Development environment.</span>
    <environment names="Testing">
        <span>This is the Testing environment.</span>
    <environment names="Production">
        <span>This is the Production environment.</span>


Working with environments (both default and custom) gets a whole lot easier in ASP.NET Core, and with the new Launch Settings feature, getting the app started in different environment modes is a breeze! Using these features, we can:

  • Create and use custom environments.
  • Enable or disable application services based on the environment the app is running in.
  • Use the environment tag helper (<environment>) to modify our MVC views based on the current execution environment.

You can check out my sample project over on GitHub to see this code in action. Feel free to mention any cool tips and tricks you've found when dealing with environments and launch settings in the comments!

Happy Coding!

It's All Just Software

I had a meeting with a customer (let's call her Kate) last week, and she wanted some changes to a web-based messaging application that my group owns and manages. That meeting didn't exactly go as planned.

Blame Tennis

Here's how the conversation between myself and Kate went:

Matthew: OK, so the request you submitted said you wanted the icon on the task bar to flash orange whenever a message comes in from the messaging application, right?

Kate: Right.

Matthew: Unfortunately, that kind of thing is basically impossible in a web app.

Kate: What? Why?

Matthew: Well, it's a completely different environment. The old app was a Windows application, where this kind of thing is trivial to do. But now, the app is a Web app, so it's a totally different environment.

Kate: I don't understand.

Matthew (exasperated): ...See, the web app only exists in the browser, and the browser exists in Windows. But the code can only call it's container. So the web app can call the browser, and the browser can call Windows. But the web app cannot call Windows.

Kate: You just said it could. The app can call the browser, and the browser can call Windows. So the app can call Windows and make the icon flash orange.

Matthew (confused): No. That's not how it works, because if it did work that way it would be a massive security risk. Imagine a malicious website being able to screw with Windows without you downloading something. That would be incredibly bad.

Kate (desperate): But the old app did that!

Matthew (resolute): Right, I know, but that was a Windows app, not a Web app. Making the taskbar icon flash in a web app is basically impossible.

Kate (angrily): It can't be impossible! They did it before.

And around and around we went. She wants something, I say we can't do that the way she wants, she says "but you did it before," ad infinitum. It's an endless game of blame tennis, where she serves with "we did it before!" and I return with "we can't do that now!" over and over until one of us collapses from exhaustion. It's maddening.

Throughout the game, it struck me as odd that she held steadfast to the idea of "well you did it before, why can't you do it again?" Because, to me, the very idea of a web app making Windows do something is preposterous, laughable. It's so far removed from "normal" web development as to be obvious to even the most junior web programmer.

But that wasn't at all obvious to Kate, and I should have known that would happen.

Basically Magicians

Developers, programmers, tech people in general (yes, including me) often forget that to all the people who don't work in the tech world, we are basically magicians. We take abstract ideas and turn them into concrete applications by using indecipherable texts and acronyms known only as "MVC" and "IDE" and "HTML". We are wizards using tools and laws that seemingly break the rules of physics and are seldom understood by persons who are not part of our "exclusive" club.

With that kind of power comes the responsibility to explain ourselves, clearly and thoughtfully, without resorting to name-calling or annoyance. Because, despite our myriad skills, varied experiences, and entirely different tech stacks which we work on daily, to the vast majority of people it's all just software. It's all the same.

This is the key thing that I failed to remember in my conversation with Kate. To her, to anyone who doesn't deal with these things on a regular basis, it's all just software. It's all 0s and 1s and true and false and math and colors and little buttons that won't do anything and links that don't open new windows unless you count to 6 and summon Beelzebub. It's all just crap that gets in the way of doing their job. If they didn't have to deal with it, they wouldn't.

Check Yourself

Kate and I eventually reached a point where we could solve some of her other issues with this system, and she felt pretty good about those agreements. We never got a resolution on the taskbar icon flash thing, and we never will. But eventually we got to a consensus where she understood why this was impossible, and can now go to her boss and try to find alternate solutions (like providing her teams with two monitors each instead of one). We got to a resolution, it just took a while.

We could have gotten there faster if I'd left my attitude at the door.

It is not the customer's job to know the ins and outs of our daily lives. It is our job to explain it to them, so they will know that we are not magicians but craftsmen, plying a trade and solving their problems with code. It is their job to explain to us what they want us to do, so that together we can work up a viable plan for getting their needs met. Both sides must do their part in order for anything to get done.

Nobody wants to play blame tennis; everybody just wants to find a solution. Leave your racket and your attitude at the door, and we can work it out together.

After all, it's all just software.

Happy Coding!

Why Aren't You Blogging Yet? Tips for Getting Started

I've been writing this blog for about a year and a half now, and I firmly believe that every software professional should write a blog. It's an invaluable tool for connecting with other professionals, for getting your ideas out there, for making bad jokes making good jokes.

I've told this to several other programmers, and I'm always met with the same responses. Wow, you're such a good writer! I can't possibly write as well as you do! Once I've told my ego to calm down and eat a bagel, I start hearing all kinds of excuses: I don't have time, I don't know any good topics, nobody cares about what I have to say. Which is bull, but there you have it.

Writing a blog is not some ancient magic that I studied for years to master! It's a process, one which is becoming a part of me just as much as working or eating is. You can do it too!

Still don't believe me? OK then, let me first dispel some common myths about blogging. All of these are things I have heard from others about why they can't or won't write a blog.

Myths About Blogging

Nobody cares about what I have to say. You're telling me that in a world of 7 billion people, where almost everybody can have someone that looks like them, that no one will ever care about your ideas? I don't believe this for an instant. Someone, somewhere, will have the same problem you have, the same ideas you thought of, and will want to know that someone else out there is thinking the same thing.

I don't have time. Neither do I. I have a family, a career, a house to maintain. But I make time. Writing this blog is now just something I do, rather than something I have to do. My blog is my outlet, my window into new tech and new stories, and my way to communicate with other members of my profession. You can always watch less TV, or play less video games, or find other ways to make time.

I can't write. It's not a requirement to be a writer in order to be a blogger. Half the bloggers out there couldn't write their way out of a contrived plot coincidence wet paper bag! That doesn't stop them, it doesn't stop me, and it shouldn't stop you. Besides, how do you expect to get better if you don't practice? Nobody's asking you to write the next great novel.

I'm scared of what my coworkers/friends/peers will think. Ignore them! If they're gonna change their mind about you because you put yourself out there, do you want to care about their opinion? Nobody gets to influence you more than you.

I don't have any good topics to blog about. Everything you know, someone else doesn't know. Don't assume that because you know something, everyone else does too.

Everything I want to write about has already been written. This doesn't matter at all. Half the topics I blog about have already been blogged about by other people. The trick is to find a way to make it interesting for your readers, make it unique in some way that doesn't In my case, I use humor (to varying effect), simple sentences, and general topics to reach as many people as I can.

Why Should I Blog Anyway?

Glad you asked!

It helps your communication skills. Sitting down and thinking about a problem for long enough allows you to concisely and accurately describe that problem to others. Communication is one of the most (if not the most) important soft skill for developers, and writing blog posts will make you a better communicator.

It gets your name out there. Especially if you have a super common name like I do. Writing a blog gets your ideas out into the world for your friends, coworkers, even prospective employers to see.

It teaches humility. There's been quite a few times where I've screwed something up and some kind soul out there on the interwebs has pointed it out (always with respect, of course).

It teaches you to be thorough. If you're taking the time to write something, you'd better be pretty darn sure it's accurate; or else you'll have a hoard of annoyed internet dwellers ready to explain, in excruciating detail, why and how and where you are wrong. Repeatedly.

Hopefully by now I've got you convinced to try blogging out (or, at least not actively hostile to the idea). Here's a couple of tips for getting started with your very own blog.

Tips For Getting Started

Get your own domain name. Your own, custom domain name makes it much easier for people to find and refer back to your blog, plus it looks professional. I personally think the top-level domain (TLD, e.g. .net, .com, .whatever) doesn't matter at all, but I'd still get something people recognize.

Start small. Pick a small topic, write a clear, concise post about it, and post it.

Don't write novels. I've seen other bloggers recommend writing everything about a topic on one page, but for me (probably because I'm a distracted individual) seeing a huge wall of text on a page is cause for me to run screaming in terror (aka hitting the back button). If the topic is large, break it up into multiple posts.

Post often. I personally write at least one post per week. They don't have to be big, involved works; hell they don't even have to be good, just write something. The post you've published is better than the post you've written.

Use whitespace. Huge multi-sentence paragraphs are a big turn off to many readers; they look impenetrable, dense, scary. Use whitespace by making lots of small paragraphs, and cut out any words or sentences that don't clearly and concisely support the point you are making.

Allow comments. It boggles my mind that bloggers can write some huge, insightful post and not allow other people to leave comments on it. Comments are where much of the value in writing a blog lies! After all, the whole of humanity is generally going to be smarter than you.

Manage the comments. Of course, allowing comments means some extra work on your part. You have to make sure you don't allow spam, or ads, or abusive posters. But in my opinion the extra work involved in maintaining a comments section is heavily outweighed by the value it provides.

Make it something you just do. If you want your blog to be successful, make it something you do, rather than something you have to do. This is the truly difficult part of writing a blog, but that kind of commitment tends to shine through your writing, making it obvious that blogging is something you enjoy rather than tolerate.

Don't expect to make money, because you probably won't. Blogging is not something people do to make a living. Sure, some super-famous bloggers can do this, but for the vast majority of us we're lucky if we make enough money to pay our hosting costs. Don't blog if all you're after is money, because you'll be sorely disappointed.

I love writing. It's why I write stories, why I write tutorials, why I write at all. But you don't have to love to write to be a good blogger, and you certainly don't need to be a good writer to be an effective blogger (proof). To me, the benefits of blogging significantly outweigh the downsides, and the skills writing teaches (communication, humility, confidence) are useful in almost every facet of our lives, not just our professional one.

So go get started! Nothing's stopping you except you!

Happy Coding Writing!

Getting All Valid Enum Values in ASP.NET Web API

One of the commenters on my blog posed an interesting question on my article about serializing enumerations in Web API:

A comment on my blog, asking

He wanted to know how someone who is querying a Web API might know what possible values a given enumeration has. I didn't answer that in the post he commented on, so I'll do that now. How do we tell consumers what possible values an enumeration in a Web API app has?

Let's say we have the following enums:

public enum AddressType  

public enum AccessLevel  

We want to expose a query which returns these values for each enumeration. To do that, let's create a class for EnumValue:

public class EnumValue  
    public string Name { get; set; }
    public int Value { get; set; }

It's a pretty generic class, to be sure, but since all enumerations are is a name and a value it serves our purposes well enough.

The trick now is to create an extension which uses Reflection to get all the names for the given enum. In fact, we can even make that method generic, so it can be used for any enumeration at all.

public static class EnumExtensions  
    public static List<EnumValue> GetValues<T>()
        List<EnumValue> values = new List<EnumValue>();
        foreach (var itemType in Enum.GetValues(typeof(T)))
            //For each value of this enumeration, add a new EnumValue instance
            values.Add(new EnumValue()
                Name = Enum.GetName(typeof(T), itemType), 
                Value = (int)itemType
        return values;

Finally, we can use Web API methods that call this extension:

public class HomeController : ApiController  
    public IHttpActionResult GetAccessLevels()
        return Ok(EnumExtensions.GetValues<AccessLevel>());

    public IHttpActionResult GetAddressTypes()
        return Ok(EnumExtensions.GetValues<AddressType>());

When we call this method using Postman, we now get an appropriate response code (200 OK) and the data we were looking for. Here's the address types:

A Postman response, showing the three possible values for the enumeration AddressType

And here's the access levels:

A Postman response, showing the three possible values for the enumeration AccessLevel

Of course, this is just one of many possible solutions to this particular problem. I like this method because it's generic and reusable for all enumerations, but if you find a better method, please feel free to share in the comments!

That's all there is to it! Now any consumer can hit these methods and know exactly what values can be used for the AccessLevel and AddressType enumerations!

I also have a repository over on GitHub which stores the sample code for this post. Check it out!

Happy Coding!