ASP.NET Core: Making Your Project Production Ready For Deployment

I decided to write this post to act primarily as a reminder to myself for when I'm publishing an ASP.NET Core project ready for a production environment. Most of the ASP.NET Core projects I'm currently working on are based on pre-existing client or platform-based boilerplates and when taking these on, they vary in quality and a result, some key project settings are just not implemented.

I will be covering the following areas:

  • Ensuring the correct environment variable is set for your publish profile.
  • Setting custom error pages.
  • Switching between development and production appsetting.json files.

Setting Environment In Publish Profile

After you have created the publish profile, update the .pubxml file (found under the "/Properties/PublishProfiles" directory within your project) and add a EnvironmentName variable:

<PropertyGroup>
    <EnvironmentName>Production</EnvironmentName>
</PropertyGroup>

This variable is very much key to the whole operation. Without it, the project will be stuck in development mode and the sections, listed below, will not work.

Setting Custom Error Pages

We are only interested in seeing a custom error page when in production mode. To do this, we need to:

  1. Update the Startup.cs file to enable status code error pages.
  2. Create an error controller to render the custom error pages.

Startup.cs

To serve our custom error page, we need to declare the route using the app.UseStatusCodePagesWithReExecute() method. This method includes a placeholder {0}, which will be replaced with the status code integer - 404, 500, etc. We can then render different views depending on the error code returned. For example:

  • /Error/404
  • /Error/500
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // Render full blown exception only if in development mode.
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseStatusCodePagesWithReExecute("/Error/{0}");
        app.UseHsts();
    }
}

Error Controller

Based on the status code returned, different views can be rendered.

public class ErrorController : Controller
{
    [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
    [Route("/Error/{statusCode}")]
    public ViewResult Status(int statusCode)
    {
        if (statusCode == StatusCodes.Status404NotFound)
        {
            return View("~/Views/Error/NotFound.cshtml");
        }
        else
        {
            return View("~/Views/Error/GeneralError.cshtml");
        }
    }
}

Switching To appsetting.production.json

You've probably noticed that your ASP.NET Core project contains three appsettings.json files - each one for your environment:

  • appsettings.json
  • appsettings.development.json
  • appsettings.production.json

If your ASP.NET Core project version is less than 3.0, you can switch between each appsettings.json file by adding the following code to your Startup.cs file:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    IConfigurationBuilder configBuilder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", true, true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", true)
        .AddEnvironmentVariables();

    Configuration = configBuilder.Build();
}

However, if running on ASP.NET Core 3.0+, you will need to use WebHost.CreateDefaultBuilder(args) method that will be added to the Programs.cs file.

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseContentRoot(Directory.GetCurrentDirectory())
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

The CreateDefaultBuilder performs the following environment-related tasks (to name a few):

  • Sets the content root to the path returned by Directory.GetCurrentDirectory().
  • Loads host configuration from environment variables prefixed with ASPNETCORE_ (for example, ASPNETCORE_ENVIRONMENT).
  • Loads application configuration settings in the following order, starting from appsettings.json and then appsettings.{Environment}.json.

As you can see, from ASP.NET Core 3.0 onwards, quite a lot is being done for you from such a minimal amount of code.


Leave A Comment

If you have any questions or suggestions, feel free to leave a comment. I do get inundated with messages regarding my posts via LinkedIn and leaving a comment below is a better place to have an open discussion. Your comment will not only help others, but also myself. :-)