Обновление 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, поэтому пользователь процесса - это я, владеющий файлом в любом случае).

Любые идеи?


person Keith Williams    schedule 16.11.2009    source источник


Ответы (3)


Измените свою первую строку на это:

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 в качестве «пути» позволяет нам загружать root config, но не сохранять.

person Kurt Schindler    schedule 22.11.2009
comment
На самом деле это очень интересное поведение, о котором я не слышал. Большое спасибо за объяснение, так как я был немного невежественен в этом. - person Venemo; 22.11.2009
comment
Спасибо, это очень интересно - я попробую сегодня вечером! - person Keith Williams; 23.11.2009
comment
Это было очень полезно. Спасибо! :) - person Adam Prescott; 18.02.2010
comment
большое спасибо. что, если мы хотим сохранить конфигурацию в другой файл, например app.config? - person Ashkan Mobayen Khiabani; 19.05.2014

Попробуй это:

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

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

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

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

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

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

person Venemo    schedule 21.11.2009
comment
Да, я знаю, что это может быть не лучший способ сделать это - я действительно просто хотел посмотреть, работает ли это, и попробовать что-то другое (и было слишком ленив, чтобы настроить таблицу настроек в моей базе данных, если честно ;)) - person Keith Williams; 23.11.2009
comment
@Venemo - Ваше предложение имеет большой смысл. Гораздо практичнее использовать XML-файл, в котором мы можем свободно читать и писать без ограничений, налагаемых web.config. Мне также понравилось предложение разместить его в AppData, где права на чтение и запись уже предоставлены, не говоря уже о том, что он может использоваться бесчисленным количеством приложений. Не то чтобы я так далеко зашел :) - person Ben Junior; 29.05.2014

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

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

person griegs    schedule 17.11.2009
comment
Не могли бы вы пояснить, что вы имеете в виду, когда запускаете это из другого проекта? - person Keith Williams; 17.11.2009
comment
Если у вас есть веб-сайт и ваш бизнес-уровень, а код выполняется в проекте бизнес-уровня, я подозреваю, что файл конфигурации, который он ищет, будет находиться в проекте бизнес-уровня. вам нужно получить путь к файлу веб-конфигурации - person griegs; 17.11.2009
comment
Ах, понятно ... на самом деле нет, хотя я обычно настраиваю такие вещи, в данном случае я ленив и располагаю бизнес-уровень в папке Models моего приложения MVC. - person Keith Williams; 21.11.2009
comment
@griegs: Это неправда. System.Configuration считывает конфигурацию из фактического файла конфигурации AppDomain. Таким образом, даже если бизнес-уровень находится в другом проекте или другой DLL, если вы вызовете его из своего приложения, он все равно будет использовать конфигурацию вашего приложения. - person Venemo; 22.11.2009