Asp.net-mvc – Updating AppSettings via ASP.NET MVC Controller

asp.net-mvcconfigurationconfiguration-files

I'm writing a basic little forums web app (for fun and to sharpen the ole' saw), and I'm having a bit of trouble with AppSettings.

My plan is to have these settings in their own file (Settings.config), to which I will grant modify permissions to the web process user account, and store all editable settings in this file (e.g. forum title, description, etc).

This is my code:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(FormCollection collection)
{
    try
    {
        var config = WebConfigurationManager.OpenWebConfiguration("~/Web.config");

        config.AppSettings.Settings["SiteTitle"].Value = collection["SiteTitle"];
        config.AppSettings.Settings["SiteDescription"].Value = collection["SiteDescription"];

        config.Save(ConfigurationSaveMode.Minimal, false);
        ConfigurationManager.RefreshSection("appSettings");

        return RedirectToAction("Index");
    }
    catch (Exception ex)
    {
        ModelState.AddModelError("_FORM", ex.Message);
        return View("Index");
    }
}

…but running it returns the following error:

A configuration file cannot be created for the requested Configuration object.

I've tried granting full permission to all users to the settings file, with no effect (I'm currently just running under Cassini, so the process user is me who has ownership of the file in any case).

Any ideas?

Best Answer

Change your first line to this:

var config = WebConfigurationManager.OpenWebConfiguration("~");

Confusing as it may be, OpenWebConfiguration expects the virtual path where the Web.config resides, excluding the file name. I guess the logic is that there will only be one Web.config in any given directory so including the name is unnecessary.

The MSDN documentation ultimately clues us in here - if you look at the examples they all use explicit relative paths, and when hosting under IIS allow you to specify config files from other locations, for example:

OpenWebConfiguration("/siteName", "Default Web Site", null, "myServer");

Addendum:

So why does OpenWebConfiguration("~/Web.config") work at all? I'm not sure I can definitively explain it, but try this for kicks: change it to ("~/Foo.bar"). The same result! You can read - your same Web.config file - but cannot write! (now try adding the foo.bar directory to your site, then put a Web.config inside it...)

Since OpenWebConfiguration expects a directory (and apparently allows non-existent ones, as long as it finds a Web.config within the parent), I think this is why mistakenly specifying ~/Web.config as a "path" allows us to load the root config, but not save it.