Обновление AppSettings через ASP.NET MVC Controller

Я пишу базовое небольшое веб-приложение для форумов (для удовольствия и для резки оле), и у меня проблемы с AppSettings.

Мой план состоит в том, чтобы эти параметры были в их собственном файле (Settings.config), на который я предоставил разрешения на изменение для учетной записи пользователя веб-процесса, и сохраните все редактируемые параметры в этом файле (например, название форума, описание и т.д.).).

Это мой код:

[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");
    }
}

... но при запуске он возвращает следующую ошибку:

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

Я попытался предоставить полное разрешение всем пользователям файла настроек без эффекта (я в настоящее время только что запущен под Cassini, поэтому пользователь процесса - это тот, кто имеет право собственности на файл в любом случае).

Любые идеи?

Ответ 1

Измените свою первую строку следующим образом:

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

Как бы то ни было, OpenWebConfiguration ожидает виртуального пути, где находится Web.config, за исключением имени файла. Я предполагаю, что логика заключается в том, что в любом данном каталоге будет только один Web.config, поэтому включение имени не нужно.

документация MSDN в конечном счете подсказывает нам здесь - если вы посмотрите на примеры, все они используют явные относительные пути, а при размещении в IIS позволяют вы должны указать конфигурационные файлы из других мест, например:

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

Добавление:

Так почему же OpenWebConfiguration("~/Web.config") работает вообще? Я не уверен, что могу окончательно объяснить это, но попробуйте это для ударов: измените его на ( "~/Foo.bar" ). Тот же результат! Вы можете прочитать - тот же файл Web.config, но не можете писать! (теперь попробуйте добавить каталог foo.bar на свой сайт, а затем поместите в него Web.config...)

Так как OpenWebConfiguration ожидает каталог (и, по-видимому, допускает несуществующие, если он находит Web.config внутри родителя), я думаю, что именно поэтому ошибочно указывая ~/Web.config как "путь", позволяет нам для загрузки корневой конфигурации, но не сохранить ее.

Ответ 2

Попробуйте следующее:

var configFile = HttpContext.Current.Server.MapPath("~/Web.config");
var config = WebConfigurationManager.OpenWebConfiguration(configFile);

Однако, я думаю, что плохая идея хранить такую ​​информацию в Web.Config, особенно если она предназначена для динамического изменения.

Даже если вы планируете использовать отдельный файл конфигурации, я предпочел бы хранить это по-другому, и я бы не стал получать свою собственную конфигурацию через классы System.Configuration. Они в основном предназначены для чтения приложений App.Config приложений Web.Config и приложений Windows для приложений ASP.NET и для их работы с чем-то другим, действительно бессмысленным.

Я рекомендую следующее:

Добавить отдельный XML файл в ваш проект. (желательно в папку App_Data, где он не может быть доступен из Интернета и где ваше приложение уже имеет права на чтение и запись.)

Затем вы можете сохранить этот тип настроек в этом XML и легко прочитать и записать его с помощью System.Xml или LINQ to XML.

Ответ 3

Если вы используете это из другого проекта, вы будете использовать конфигурацию из этой папки, у которой не будет файла конфигурации, поэтому ошибка, которую он не может создать.

Вы можете использовать server.mappath или что-то в этом роде для доступа к конфигурационному файлу веб-папок.