Build a .NET Config File Safely with mconfig

mconfig can bolt a named feature onto a .NET config file, or spit out a default template from a packaged layout, using Mono's own definitions. It will not invent a feature name if none is installed: that failure is a diagnostic, not a reason to guess. The examples use the mconfig installed by Ubuntu's mono-devel package, version 6.8.0.105, and the whole job takes about ten minutes.

You need Mono's mconfig command and a feature or layout definition supplied by mconfig's configuration files. You do not normally need root: write to a project directory you own, and reach for elevated privileges only when the destination is deliberately under a protected system directory. Keep a copy of the existing config file before changing it.

1. Check the version and the vocabulary

Run these first, they cost nothing:

mconfig --version
mconfig --help
mconfig

The version check on this system prints 0.1.0.0. The no-argument report lists the commands, default templates and available features. In this installation it reports no data for templates or features, so the demonstration commands below fail cleanly until a definition is supplied.

2. Confirm the definitions

mconfig reads its packaged configuration first, then a per-user file under XDG_CONFIG_HOME (or ~/.config), and finally ./mconfig.xml. Later files override earlier settings. Inspect those locations before choosing a feature:

printf '%s\n' "${XDG_CONFIG_HOME:-$HOME/.config}/mconfig/config.xml"
test -f ./mconfig.xml && sed -n '1,120p' ./mconfig.xml

Do not copy an arbitrary XML file into one of these locations. Read the definitions and use the exact feature or template names shown by mconfig without arguments. A local mconfig.xml is project-specific: useful for controlled overrides, but it also means the same command run from another directory can produce a different result.

3. Choose the target

The target controls which definitions are eligible and supplies defaults for some output names. Prefer the long option with an equals sign in scripts and copy-and-paste commands:

mconfig --target=web --help
mconfig --target=application --help

The installed command accepts the short form in its help too, but the long form makes the parameter boundary unambiguous. The target is a selection filter, not a permission change, and it does not enable ASP.NET or change the runtime.

4. Add a feature to an existing file

Use addfeature, or its af alias, followed by the exact feature name and an optional destination:

cp --preserve=mode,ownership ./Web.config ./Web.config.before-mconfig
mconfig --target=web addfeature FEATURE_NAME ./Web.config

Replace FEATURE_NAME with a name printed by the no-argument report. If the destination exists, mconfig injects the feature at locations defined by its configuration, and it may touch more than one XML section, so check the diff straight away:

diff -u ./Web.config.before-mconfig ./Web.config

Warning: if the destination does not exist, mconfig creates it with the requested feature and its dependencies. That is a state-changing operation: do not point the command at a live service's configuration until you have reviewed the generated file and know how that service reloads configuration.

5. Generate a default configuration

Use defaultconfig, or dc, with a configured layout name and optional target directory:

mconfig --target=web defaultconfig CONFIG_NAME ./generated-config

The manual calls the command defaultconfig, but on this installed 6.8.0.105 build mconfig --help shows the shorter spelling defconfig instead. Use whichever spelling the local help shows if the long name is rejected:

mconfig --target=web defconfig CONFIG_NAME ./generated-config

Omit the config name and the web target falls back to Web.config, the application target to application, subject to the layout definitions; the target directory defaults to the current directory. Build into a disposable directory and inspect its contents before you go anywhere near a project file:

mkdir -p ./generated-config
mconfig --target=web defconfig CONFIG_NAME ./generated-config
find ./generated-config -maxdepth 1 -type f -printf '%f\n'

6. Use a project override deliberately

For a one-off configuration source, pass it with --config:

mconfig --config=./team-mconfig.xml --target=application addfeature FEATURE_NAME ./MyTool.exe.config

The supplied file is read after the standard locations, so its settings override them. Treat it as code: review it, keep it with the project, and do not put secrets into it unless the application's secret-handling policy explicitly permits that. The final argument above is still the .NET configuration file being generated or modified.

7. Recover from an unwanted change

mconfig has no documented undo command. For an existing file, restore the backup once you have checked it is the right one:

cmp -s ./Web.config.before-mconfig ./Web.config
cp --preserve=mode,ownership ./Web.config.before-mconfig ./Web.config

If you generated a new file, remove it only after confirming the path and that no process needs it. A safer first move is to shift it aside:

mv ./generated-config/Web.config ./generated-config/Web.config.rejected

Recovery: for a service configuration, validate with that service's own checker before restarting it. mconfig can write syntactically valid XML that is still wrong for a particular application.

Common traps

Done means