ASP.NET MVC · Production

Web.config

Web.config is the control panel of an MVC 5 app: database connections, feature switches, security settings and IIS behaviour all live in this one XML file.

Advanced 6 min Lesson 34 of 37Covers ASP.NET MVC 5.2 on .NET Framework 4.8.
Before you start:Logging
0/37 in ASP.NET MVC
On this page · 6 min · Advanced

Learning objectives#

  • Store and read settings and connection strings
  • Wrap settings in a typed class
  • Keep secrets out of source control with an external file
  • Change settings per environment with config transforms

Explanation#

<appSettings> holds key–value pairs read with ConfigurationManager.AppSettings["Key"] — always strings, so convert them. <connectionStrings> holds database connections read with ConfigurationManager.ConnectionStrings["Name"].

Wrap settings in a small class (AppSettings.FreeDeliveryOver) that parses and validates them once, so the rest of the code never sees raw strings or misspelled keys.

<appSettings file="secrets.config"> merges an extra file over the main settings. Keep secrets.config out of source control and create it on each server — or let Azure App Service settings override appSettings at runtime.

Config transforms (Web.Debug.config, Web.Release.config) change values when you publish: xdt:Transform="SetAttributes" with xdt:Locator="Match(key)" replaces a value; xdt:Transform="RemoveAttributes(debug)" removes debug="true".

Changing Web.config on a live server restarts the application (and clears InProc session). Plan changes for quiet times.

Syntax#

Razor / Markup Illustrative
<appSettings file="secrets.config">
  <add key="Shop:FreeDeliveryOver" value="500" />
</appSettings>
<connectionStrings>
  <add name="ShopDb" connectionString="Server=.;Database=Shop;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>

Code example: Typed settings, a secrets file and a release transform#

C#Web.config Illustrative
<!-- Web.config -->
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <connectionStrings>
    <add name="ShopDb" connectionString="Server=(localdb)\mssqllocaldb;Database=ShopMvc5;Integrated Security=True" providerName="System.Data.SqlClient" />
  </connectionStrings>
  <appSettings file="secrets.config">
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="Shop:Name" value="Techie Stationers" />
    <add key="Shop:FreeDeliveryOver" value="500" />
    <add key="Features:GiftCards" value="false" />
    <add key="Payments:ApiKey" value="set-in-secrets.config" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.8" />
    <httpRuntime targetFramework="4.8" maxRequestLength="10240" />
    <customErrors mode="RemoteOnly" />
  </system.web>
</configuration>


<!-- secrets.config -->
<appSettings>
  <add key="Payments:ApiKey" value="sk_test_51Hx9" />
</appSettings>


<!-- Web.Release.config -->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <appSettings>
    <add key="Features:GiftCards" value="true" xdt:Transform="SetAttributes" xdt:Locator="Match(key)" />
  </appSettings>
  <system.web>
    <compilation xdt:Transform="RemoveAttributes(debug)" />
    <customErrors mode="On" xdt:Transform="SetAttributes" />
  </system.web>
</configuration>


// App_Start/AppSettings.cs
using System;
using System.Configuration;


namespace ShopSite
{
    public static class AppSettings
    {
        public static string ShopName => Read("Shop:Name");
        public static decimal FreeDeliveryOver => decimal.Parse(Read("Shop:FreeDeliveryOver"));
        public static bool GiftCardsEnabled => bool.Parse(Read("Features:GiftCards"));
        public static string PaymentsKey => Read("Payments:ApiKey");


        private static string Read(string key)
        {
            var value = ConfigurationManager.AppSettings[key];
            if (string.IsNullOrWhiteSpace(value))
                throw new ConfigurationErrorsException(
quot;Missing app setting '
{key}'");
return value; } } } // Controllers/SettingsController.cs using System.Configuration; using System.Web.Configuration; using System.Web.Mvc; namespace ShopSite.Controllers { public class SettingsController : Controller { public ActionResult Index() { var db = ConfigurationManager.ConnectionStrings["ShopDb"]; var runtime = (HttpRuntimeSection)ConfigurationManager.GetSection("system.web/httpRuntime"); return Content(
quot;Shop:
{AppSettings.ShopName}\n" +
quot;Free delivery over:
{AppSettings.FreeDeliveryOver:0}\n" +
quot;Gift cards enabled:
{AppSettings.GiftCardsEnabled}\n" +
quot;Payments key:
{AppSettings.PaymentsKey.Substring(0, 7)}… (from secrets.config)\n" +
quot;Database provider:
{db.ProviderName}\n" +
quot;Max request:
{runtime.MaxRequestLength} KB\n" +
quot;Debug compilation:
{HttpContext.IsDebuggingEnabled}",
"text/plain"); } } }
Expected output
GET /Settings
200 OK
Shop: Techie Stationers
Free delivery over: 500
Gift cards enabled: False
Payments key: sk_test… (from secrets.config)
Database provider: System.Data.SqlClient
Max request: 10240 KB
Debug compilation: True

This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.

Step-by-step explanation#

  1. AppSettings reads each key once through ConfigurationManager and converts it to the right type, throwing a clear error if a key is missing.
  2. Payments:ApiKey is defined in Web.config as a placeholder, but secrets.config (merged through file="…") overrides it with the real value.
  3. The connection string and httpRuntime values come from their own sections.
  4. Locally, debug compilation is on and gift cards are off. When you publish in Release, Web.Release.config turns gift cards on, removes debug="true" and switches customErrors to On.

Real-world use case#

A retailer runs the same MVC 5 app for three countries. Each server has its own secrets.config with payment keys and a transform sets the currency and tax settings, so the code and the main Web.config are identical everywhere.

Common mistakes#

Committing secrets in Web.config

Connection strings with passwords and API keys in Git are leaked with every clone. Use a secrets file, environment-specific transforms built on the server, or App Service settings.

Leaving debug="true" in production

Debug compilation disables batching and optimisations and makes errors more verbose. The Release transform should remove it.

Reading raw strings everywhere

ConfigurationManager.AppSettings["FreeDelivery"] scattered across the code breaks silently on a typo. Centralise keys in one class.

Best practices#

  • Group keys with prefixes like Shop: and Features:
  • Validate settings at startup
  • Keep secrets out of source control
  • Use transforms or deployment settings per environment

Remember this#

AppSettings = strings; convert them once.

file="secrets.config" overrides keys locally.

Web.Release.config transforms on publish.

Practice exercise#

Your task: Add a Shop:SupportEmail setting and show it on a contact page through the AppSettings class, failing clearly when it is missing.

Need a hint?
Add public static string SupportEmail => Read("Shop:SupportEmail");
Show solution
C# Illustrative
<!-- Web.config -->
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="Shop:SupportEmail" value="help@techie-stationers.example" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.8" />
    <httpRuntime targetFramework="4.8" />
  </system.web>
</configuration>


// Controllers/ContactController.cs
using System.Configuration;
using System.Web.Mvc;


namespace ShopSite.Controllers
{
    public class ContactController : Controller
    {
        public ActionResult Index()
        {
            var email = ConfigurationManager.AppSettings["Shop:SupportEmail"];
            if (string.IsNullOrWhiteSpace(email)) throw new ConfigurationErrorsException("Missing Shop:SupportEmail");
            return Content("Write to us: " + email, "text/plain");
        }
    }
}
Expected output
GET /Contact
200 OK
Write to us: help@techie-stationers.example

Mini quiz#

Web.config quizMultiple choice Question 1 of 3

What type does ConfigurationManager.AppSettings["Key"] return?

Score so far: 0/0

Want more? Practise all ASP.NET MVC MCQs · ASP.NET MVC interview questions

My notes#

Saved in this browser.

Progress is saved in this browser. Sign in to sync.