ASP.NET MVC: Читаем настройки сайта из своей секции файла конфигурации web.config

Постановка задачи

Требуется создать свою секцию настроек в конфигурационном файле web.config, со структурой более «продвинутой» чем appSettings (то есть нечто большее, чем просто Dictionary). А так же надо реализовать механизм считывания и обновления данных в этой секции.

Как сохранить настройки или выбор стратегии

Снова напомню, что есть серия статей «История одного проекта» (далее ИОП), которая посвящена разработке сайта “музей юмора”. И поэтому, давайте снова поговорим про этот проект, как можно расширить возможности по администрированию этого сайта. Предположим, что лента экспонатов, должна хранить записи за какой-то определенный срок. Например, за одну неделю, то есть семь дней. А если я захочу изменить срок, например на 14 дней? А если я захочу вообще временно отключить удаление записей? А если я хочу временно запретить публикацию экспонатов на ленте через IE-ускоритель? А если… Слишком много «а если»… Надо просто эти параметры где-то хранить с возможностью управления ими непосредственно со страниц сайта. Один из вариантов — файл конфигурации web.config, можно также хранить в базе данных, или, например, в текстовом файле, или сделать другой сайт, на котором сделать web-сервис, который сможет «выдать» всем моим сайта настройки для каждого или общие для всех. Или вообще, всё выложить в облако Azure и платить некоторую сумму в Microsoft… Всё ограничено лишь вашей фантазией. Мы будем говорить про первый вариант – сохранение настроек сайта в файле конфигурации.

Итак, хранение настроек в web.config тоже можно реализовать как минимум двумя способами. Читать/писать данные в файле конфигурации можно:

    Возьмем второй вариант. Мне хочется показать пример посложнее, да и структура у меня будет развиваться и совершенствоваться, а потому очень не хочется осознать в какой-то момент, что надо переписывать половину приложения, чтобы реализовать возможность читать/писать данные и настройки в своей секции конфигурации, а не из appSettings.

    Начнем с простого. Пусть на данный момент мне требуется такая ветка в файле конфигурации:

    1: <SiteSettingsGroup> 2: <SiteSettings> 3: <PagerSize> 4: <EntityName=»Logs»Size=»20″/> 5: <EntityName=»Exhibit»Size=»10″/> 6: <EntityName=»Lenta»Size=»15″/> 7: </PagerSize> 8: <LentaDeleteAfterDays=»17″AllowPostFromShare=»false»/> 9: </SiteSettings> 10: </SiteSettingsGroup>

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

    Немного специальных классов

    Создадим несколько классов. Для начала – главный класс SiteSettings (также называется и файл .cs). Чтобы все получилось, нужно для начала добавить namespace:

    using System.Configuration;

    Для начала создадим первый “кирпичик” выбранной структуры – класс LentaElement из указанной выше конфигурации:

    1: publicclass LentaElement : ConfigurationElement { 2: 3: [ConfigurationProperty(«DeleteAfterDays», DefaultValue = 7, IsRequired = true)] 4: [IntegerValidator(MinValue = 3, MaxValue = 30, ExcludeRange = false)] 5: publicint DeleteAfterDays { 6: get { 7: return (int)this[«DeleteAfterDays»]; 8: } 9: set { 10: this[«DeleteAfterDays»] = value; 11: } 12: } 13: 14: [ConfigurationProperty(«AllowPostFromShare», DefaultValue = true, IsRequired = true)] 15: publicbool AllowPostFromShare { 16: get { 17: return (bool)this[«AllowPostFromShare»]; 18: } 19: set { 20: this[«AllowPostFromShare»] = value; 21: } 22: } 23: }

    Обратите внимание на то, что класс унаследован от ConfigurationElement. Это один из основных базовых классов, которые используются в web.config для разделов. Дальше будет понятнее.

    Далее надо бы создать главный раздел для моей секции и уже использовать LentaElement как свойство. Класс я назову SiteSettings:

    1: publicclass SiteSettings : ConfigurationSection { 3: [ConfigurationProperty(«Lenta», IsRequired = true)] 4: public LentaElement Lenta { 6: return (LentaElement)this[«Lenta»]; 9: this[«Lenta»] = value;

    Между делом или Config-помощник

    Для того, чтобы “достучаться” до любого значения любого параметра моей конфигурации, давайте прямо сейчас создадим специальный класс-помощник. Я буду его использовать чтобы протестировать работоспособность конфигурации:

    1: publicclass Config { 2: 3: /// <summary> 4: /// скроем конструктор от любопытных программеров 5: /// </summary> 6: internal Config() { } 7: 8: /// <summary> 9: /// наименование раздела конфигурации 10: /// </summary> 11: privateconststring CONFIGGROUPNAME = «SiteSettingsGroup/»; 12: 13: /// <summary> 14: /// наименование секции 15: /// </summary> 16: privateconststring CONFIGSECTIONNAME = «SiteSettings»; 17: 18: /// <summary> 19: /// Чтение раздела конфигурации целиком 20: /// </summary> 21: /// <returns></returns> 22: internalstatic SiteSettings Get() { 23: var config = (SiteSettings)ConfigurationManager  
                        .GetSection(String.Concat(CONFIGGROUPNAME, CONFIGSECTIONNAME)); 24: return config; 25: } 26: }

    А теперь пришло время попробовать что получилось. Попробуем прочитать информацию из конфигурации. Я предварительно в файле  web.config пока убрал (закомментировал) из своей конфигурации секцию PagerSize. Потому что она еще не реализована, а значить приложение даже не будет пытаться запуститься, а просто вывалится с ошибкой.

    В головном контролере в методе Index, я для проверки вставил пару строк, чтобы проверить что конфигурация читается, запустил и…

    Отлично! Как раз то, что я и указал в своей конфигурации. Дальше — больше. Я добавил еще несколько классов. Это самое интересное. В раздел SiteSettings я добавил определение класса PagerSizeCollection. Чтобы можно было работать с коллекцией настроек. Далее определил класс PageSizeItemsElement, который и представляет собой одну из строчек в списке PagerSize… Наверное, всё-таки имеет смысл показать весь файл SiteSettings целиком:

    1: publicclass SiteSettings : ConfigurationSection 2: { 3:   4: [ConfigurationProperty(«PagerSize»)] 5: public PagerSizeCollection PagerSize 6: { 7: get 8: { 9: return ((PagerSizeCollection)base[«PagerSize»]); 10: } 11: } 12:   13: [ConfigurationProperty(«Lenta», IsRequired = true)] 14: public LentaElement Lenta 15: { 16: get 17: { 18: return (LentaElement)this[«Lenta»]; 19: } 20: set 21: { 22: this[«Lenta»] = value; 23: } 24: } 25: } 26:   27: [ConfigurationCollection(typeof(PageSizeItemsElement), AddItemName = «Entity»)] 28: publicclass PagerSizeCollection : ConfigurationElementCollection 29: { 30:   31: public PageSizeItemsElement this[int index] 32: { 33: get { return (PageSizeItemsElement)BaseGet(index); } 34: } 35:   36: protectedoverride ConfigurationElement CreateNewElement() 37: { 38: returnnew PageSizeItemsElement(); 39: } 40:   41: protectedoverrideobject GetElementKey(ConfigurationElement element) 42: { 43: return ((PageSizeItemsElement)element).Name; 44: } 45: } 46:   47: publicclass PageSizeItemsElement : ConfigurationElement 48: { 49:   50: [ConfigurationProperty(«Size», DefaultValue = 20, IsRequired = true)] 51: [IntegerValidator(MinValue = 5, MaxValue = 100, ExcludeRange = false)] 52: publicint Size 53: { 54: get 55: { 56: return (int)this[«Size»]; 57: } 58: set 59: { 60: this[«Size»] = value; 61: } 62: } 63:   64: [ConfigurationProperty(«Name», DefaultValue = «EntityName», IsRequired = true)] 65: [StringValidator(MinLength = 3, MaxLength = 50,
                      InvalidCharacters = » ~!@#$%^&*()[]{}/;'»|\»)] 66: public String Name 67: { 68: get 69: { 70: return (String)this[«Name»]; 71: } 72: set 73: { 74: this[«Name»] = value; 75: } 76: } 77: } 78:   79: public class LentaElement : ConfigurationElement 80: { 81:   82: [ConfigurationProperty(«DeleteAfterDays», DefaultValue = 7, IsRequired = true)] 83: [IntegerValidator(MinValue = 3, MaxValue = 30, ExcludeRange = false)] 84: public int DeleteAfterDays 85: { 86: get 87: { 88: return (int)this[«DeleteAfterDays»]; 89: } 90: set 91: { 92: this[«DeleteAfterDays»] = value; 93: } 94: } 95:   96: [ConfigurationProperty(«AllowPostFromShare», DefaultValue = true, IsRequired = true)] 97: public bool AllowPostFromShare 98: { 99: get 100: { 101: return (bool)this[«AllowPostFromShare»]; 102: } 103: set 104: { 105: this[«AllowPostFromShare»] = value; 106: } 107: } 108: }

    Чтобы проверить работоспособность проделываю такую же операцию как и в прошлый раз:

    Всё работает. Теперь осталось в подключить настройки к системе, то есть начать использовать их. Читается всё замечательно. Попробуем сохранить?

    Заключение

    В следующей статье я создам форму редактирования настроек (скорее всего это будет knockout.js, то есть значит AJAX).

    Подробнее: http://feedproxy.google.com/~r/blogmusor/~3/rSNupmGLoRo/95

    Источник: lred.ru

    Оцените статью
    новости для мужчин