ASP.NET MVC: Читаем настройки сайта из своей секции файла конфигурации web.config
Постановка задачи
Требуется создать свою секцию настроек в конфигурационном файле web.config, со структурой более "продвинутой" чем appSettings (то есть нечто большее, чем просто Dictionary). А так же надо реализовать механизм считывания и обновления данных в этой секции.
Как сохранить настройки или выбор стратегии
Снова напомню, что есть серия статей "История одного проекта" (далее ИОП), которая посвящена разработке сайта “музей юмора”. И поэтому, давайте снова поговорим про этот проект, как можно расширить возможности по администрированию этого сайта. Предположим, что лента экспонатов, должна хранить записи за какой-то определенный срок. Например, за одну неделю, то есть семь дней. А если я захочу изменить срок, например на 14 дней? А если я захочу вообще временно отключить удаление записей? А если я хочу временно запретить публикацию экспонатов на ленте через IE-ускоритель? А если... Слишком много "а если"... Надо просто эти параметры где-то хранить с возможностью управления ими непосредственно со страниц сайта. Один из вариантов - файл конфигурации web.config, можно также хранить в базе данных, или, например, в текстовом файле, или сделать другой сайт, на котором сделать web-сервис, который сможет "выдать" всем моим сайта настройки для каждого или общие для всех. Или вообще, всё выложить в облако Azure и платить некоторую сумму в Microsoft... Всё ограничено лишь вашей фантазией. Мы будем говорить про первый вариант – сохранение настроек сайта в файле конфигурации.
Итак, хранение настроек в web.config тоже можно реализовать как минимум двумя способами. Читать/писать данные в файле конфигурации можно:
- Из секции appSettings. ASP.NET предоставляет программистам в своё распоряжение самый простой вариант. Информация в этой секции хранится по принципу Dictionary (ключ = значение).
- Из собственной секции файла конфигурации. ASP.NET также предоставляет такую возможность. Структура данных в этом случае может быть сколь угодно сложной (комплексные типы), более того, вы можете гарантировать значения по умолчанию для своих параметров и даже валидацию ввода при изменении свойств, что является неоспоримым плюсом для этого способа.
Возьмем второй вариант. Мне хочется показать пример посложнее, да и структура у меня будет развиваться и совершенствоваться, а потому очень не хочется осознать в какой-то момент, что надо переписывать половину приложения, чтобы реализовать возможность читать/писать данные и настройки в своей секции конфигурации, а не из 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
Дайджест новых статей по интернет-маркетингу на ваш email
Новые статьи и публикации
- 2024-12-26 » Универсальный промпт для нейросети: как выжать максимум из ChatGPT, YandexGPT, Gemini, Claude в 2025
- 2024-11-26 » Капитан грузового судна, или Как начать использовать Docker в своих проектах
- 2024-11-26 » Обеспечение безопасности ваших веб-приложений с помощью PHP OOP и PDO
- 2024-11-22 » Ошибки в Яндекс Вебмастере: как найти и исправить
- 2024-11-22 » Ошибки в Яндекс Вебмастере: как найти и исправить
- 2024-11-15 » Перенос сайта на WordPress с одного домена на другой
- 2024-11-08 » OSPanel 6: быстрый старт
- 2024-11-08 » Как установить PhpMyAdmin в Open Server Panel
- 2024-09-30 » Как быстро запустить Laravel на Windows
- 2024-09-25 » Next.js
- 2024-09-05 » OpenAI рассказал, как запретить ChatGPT использовать содержимое сайта для обучения
- 2024-08-28 » Чек-лист: как увеличить конверсию интернет-магазина на примере спортпита
- 2024-08-01 » WebSocket
- 2024-07-26 » Интеграция с Яндекс Еда
- 2024-07-26 » Интеграция с Эквайринг
- 2024-07-26 » Интеграция с СДЕК
- 2024-07-26 » Интеграция с Битрикс-24
- 2024-07-26 » Интеграция с Travelline
- 2024-07-26 » Интеграция с Iiko
- 2024-07-26 » Интеграция с Delivery Club
- 2024-07-26 » Интеграция с CRM
- 2024-07-26 » Интеграция с 1C-Бухгалтерия
- 2024-07-24 » Что такое сторителлинг: техники и примеры
- 2024-07-17 » Ошибка 404: что это такое и как ее использовать для бизнеса
- 2024-07-03 » Размещайте прайс-листы на FarPost.ru и продавайте товары быстро и выгодно
- 2024-07-01 » Профилирование кода в PHP
- 2024-06-28 » Изучаем ABC/XYZ-анализ: что это такое и какие решения с помощью него принимают
- 2024-06-17 » Зачем вам знать потребности клиента
- 2024-06-11 » Что нового в работе Яндекс Метрики: полный обзор обновления
- 2024-06-11 » Поведенческие факторы ранжирования в Яндексе
Не было еще ни одного великого ума без примеси безумия. Аристотель |
Мы создаем сайты, которые работают! Профессионально обслуживаем и продвигаем их , а также по всей России и ближнему зарубежью с 2006 года!
Как мы работаем
Заявка
Позвоните или оставьте заявку на сайте.
Консультация
Обсуждаем что именно Вам нужно и помогаем определить как это лучше сделать!
Договор
Заключаем договор на оказание услуг, в котором прописаны условия и обязанности обеих сторон.
Выполнение работ
Непосредственно оказание требующихся услуг и работ по вашему заданию.
Поддержка
Сдача выполненых работ, последующие корректировки и поддержка при необходимости.