ASP.NET MVC: Сохраняем настройки сайта в свою секцию файла конфигурации web.config
Что будет в статье?
В предыдущей части были созданы сами настройки и реализовано чтение настроек. В этой предстоит создать форму управления настройками, ajax-сервис, ViewModel на javascript и всё что ещё потребуется.
Сохранение настроек в web.config
Для начал доработаем немного Config-помощник, дописав в него один новый метод, которой будет сохранять настройки:
1: internalstatic Configuring Save(SiteSettings settings) {
2: Configuring success = new Configuring();
3: try {
4: Configuration cfg = WebConfigurationManager.OpenWebConfiguration("~");
5: var group = cfg.SectionGroups[CONFIGGROUPNAME];
6: SiteSettings section = (SiteSettings)group.Sections[CONFIGSECTIONNAME];
7: if (section != null) {
8: section.Lenta.AllowPostFromShare = settings.Lenta.AllowPostFromShare;
9: section.Lenta.DeleteAfterDays = settings.Lenta.DeleteAfterDays;
10: section.PagerSize.Clear();
11: for (int i = 0; i < settings.PagerSize.Count; i++) {
12: section.PagerSize.Add(settings.PagerSize[i]);
13: }
14: cfg.Save();
15: success.Success = true;
16: }
17: }
18: catch (ConfigurationErrorsException error) {
19: success.ConfigException = error;
20: }
21: return success;
22: }
Рисуем форму редактирования
В панели управления администратора я сделал ссылку на представление Settings.cshtml. И вот так, не сложно, наполнил это представление html-разметкой:
1: <div class="clear">
2: <div class="left" style="width: 49%">
3: <h4>Лента</h4>
4: <div class="editor-label">
5: <label for="DeleteAfterDays">Очищать старее чем, дни:</label>
6: </div>
7: <div class="editor-field">
8: <input type="text" id="DeleteAfterDays"value="" />
9: </div>
10: <div class="editor-label">
11: <input type="checkbox" id="AllowPostFromShare" />
12: Разрешить публикацию через ускоритель
13: </div>
14: </div>
15: <div class="left" style="width: 49%">
16: <h4>Пользовательский интерфейс</h4>
17: <h6>Настройки пейджера для сущностей</h6>
18: <div></div>
19: <button>+</button>
20: </div>
21: </div>
22:
23: <div class="clear"></div>
24: <p>
25: <button>Сохранить все</button>
26: </p>
И раз уж я решил реализовать задуманное с использованием фреймворка Knockout.js, то далее это представление наполнится атрибутами привязки (data-bind). А пока надо подключить требуемые скрипты к этому представлению. Хочу заметить, что это пока не полный список.
1: @section scripts{
2: <scriptsrc="@Url.Content("~/scripts/knockout-2.1.0.js")"></script>
3: <script src="@Url.Content("~/scripts/knockout.validation.js")"></script>
4: }
Лирическое отступление
Я набросал небольшой Nuget-пакет, который при установки создает папку Js и помещает туда пока один единственный файл site.core.js (читателям моего блога название должно быть знакомо). Далее я постараюсь наполнить контролами и различными полезными штуками этот пакет, по мере написания сайтов. Это хороший старт для вашего фреймворка на JavaScript для всего сайта. Файл содержит обертку на jQuery методы getJSON и postJSON. Я установил себе в проект этот пакет:
PM> Install-Package JsSite
Successfully installed 'JsSite 0.1.0'.
Successfully added 'JsSite 0.1.0' to Calabonga.Mvc.Humor.
PM>
Пакеты и скрипты установлены. Давай подготовим серверную часть.
Создаем новый контролер
Название для контролера AjaxController говорит само за себя. Этот контролер будет обслуживать весь сайт. Но пока в нем будет только пара методов. Вот первый, он читает данные из конфигурации:
1: public JsonResult LoadSettings() {
2: SiteSettings config = Config.Get();
3: var jsonConfig = new SiteSettingsJson();
4: jsonConfig.Lenta.AllowPostFromShare = config.Lenta.AllowPostFromShare;
5: jsonConfig.Lenta.DeleteAfterDays = config.Lenta.DeleteAfterDays;
6: for (int i = 0; i < config.PagerSize.Count; i++) {
7: jsonConfig.PagerSize.Add(new PagerSizeItem {
8: Name = config.PagerSize[i].Name,
9: Size = config.PagerSize[i].Size
10: });
11: }
12: return Json(jsonConfig, JsonRequestBehavior.AllowGet);
13: }
Следует остановиться на минутку и описать казус, который у меня приключился. В строке 2 я получаю объект и при попытке его отправить через JsonResult в строке 12 выдавалась ошибка сериализации объекта SiteSettings. Сам по себе объект простой, но его предки (вспомните от чего он унаследован) упорно не хотели проходить сериализацию. Пришлось сделать простой прокси-класс SiteSettingsJson, и, наполняя его данными передавать на форму. Класс настолько прост, что я даже его приводить не буду, да?
Время для Js-сервиса
Новый файл в папке Js я назвал site.services.js. Вот его содержимое:
1: /// <reference path="site.core.js" />
2: /// <reference path="../Scripts/jquery-1.8.1.js" />
3: /// <reference path="../Scripts/knockout-2.1.0.debug.js" />
4:
5: (function (site) {
6:
7: "use strict";
8:
9: site.services.settings = {
10: load: function (callback) {
11: site.fw.ajaxService.getJson("LoadSettings", {}, callback);
12: },
13: save: function (jsonData, callback) {
14: site.fw.ajaxService.postJson("SaveSettings", jsonData, callback);
15: }
16: }
17:
18: })(site);
Этот сервис использует обертку на ajax, которую я получил вместе с JsSite-пакетом. Как вы видите есть уже и второй метод, который будет сохранять данные, но его я пока не писал в AjaxController’e, займусь им позже.
Основной ViewModel на JavaScript? Легко!
Для начала нужно прочитать настройки и отобразить их при открытии страницы. Для этого я создал ViewModel страницы Settings.cshtml, который “умеет” загружать настройки. Файл я назвал site.vm.settings.js положил его в папку Js:
1: /// <reference path="site.core.js" />
2: /// <reference path="site.services.js" />
3: /// <reference path="../Scripts/jquery-1.8.1.js" />
4: /// <reference path="../Scripts/knockout.mapping-latest.debug.js" />
5: /// <reference path="../Scripts/knockout-2.1.0.debug.js" />
6:
7: (function (site) {
8:
9: "use strict";
10:
11: site.vm.settings = function () {
12: var
13: //статус работы сервиса
14: isbusy = ko.observable(false),
15:
16: // конфигурация
17: config = ko.observable({
18: "Lenta": ko.observable({
19: "DeleteAfterDays": ko.observable(),
20: "AllowPostFromShare": ko.observable(true)
21: }),
22: "PagerSize": ko.observableArray()
23: }),
24:
25: // PagerSize: название
26: newName = ko.observable("Entity"),
27:
28: // PagerSize: размер страниц
29: newSize = ko.observable(0),
30:
31: // метод загрузки конфигурации
32: load = function () {
33: isbusy(true);
34: site.services.settings.load(function (json) {
35: isbusy(false);
36: ko.mapping.fromJS(json.Config, {}, config);
37: });
38: },
39:
40: // сохранение настроек
41: save = function () {
42: isbusy(true);
43: var jsonData = ko.toJSON(config);
44: site.services.settings.save(jsonData, function (json) {
45: isbusy(false);
46: alert(json)
47: })
48: },
49:
50: // добавдение объекта в список PagerSize
51: add = function () {
52: config().PagerSize.push(new PagerSize(newName(), newSize()));
53: newName("Entity"); newSize(10);
54: },
55:
56: // удаление объекта из списка PagerSize
57: remove = function (item) {
58: config().PagerSize.remove(item);
59: };
60:
61: load();
62:
63: return {
64: config: config,
65: isbusy: isbusy,
66: remove: remove,
67: add: add,
68: newName: newName,
69: newSize: newSize,
70: save:save
71: }
72: }();
73:
74: })(site);
Не думаю, что нужно подробно останавливаться на распечатке. Тем более, что я постарался с комментариями.
Представление Settings.cshtml
Теперь надо показать html-код разметки этого самого представления Settings.cshtml, потому что я кое-что добавил и “нашпиговал” атрибутами привязки. Приведу этот код тоже целиком:
1: @{
2: ViewBag.Title = "Настройки системы";
3: Layout = "~/Views/Shared/_LayoutMain.cshtml";
4: }
5:
6: <h2>Настройки системы</h2>
7: <divdata-bind="ifnot: isbusy">
8: <divclass="clear">
9: <divclass="left"style="width: 49%">
10: <h4>Лента</h4>
11: <divclass="editor-label">
12: <labelfor="DeleteAfterDays">Очищать старее чем, дни:</label>
13: </div>
14: <divclass="editor-field">
15: <inputtype="text"id="DeleteAfterDays"
16: data-bind="value: config().Lenta().DeleteAfterDays"/>
17: </div>
18: <divclass="editor-label">
19: <inputtype="checkbox"id="AllowPostFromShare"
20: data-bind="checked: config().Lenta().AllowPostFromShare"/>
21: Разрешить публикацию через ускоритель
22: </div>
23: </div>
24: <divclass="left"style="width: 49%">
25: <h4>Пользовательский интерфейс</h4>
26: <h6>Настройки пейджера для сущностей</h6>
27: <divdata-bind="foreach: config().PagerSize">
28: <p>
29: <b><spandata-bind="text: Name"></span></b> на одной странице <b>
30: <spandata-bind="text: Size"></span></b>
31: <buttondata-bind="click: $parent.remove">х</button>
32: </p>
33: </div>
34: Название класса сущности:<br/>
35: <inputtype="text"data-bind="value: newName"/><br/>
36: Количество объектов на странице:<br/>
37: <inputtype="text"data-bind="value: newSize"/><br/>
38: <buttondata-bind="click: add">Добавить новую</button>
39: </div>
40: </div>
41:
42: <divclass="clear"></div>
43: <p>
44: <buttondata-bind="click: save">Сохранить все</button>
45: </p>
46: </div>
47: @section scripts{
48: <scriptsrc="@Url.Content("~/scripts/knockout-2.1.0.js")"></script>
49: <script src="@Url.Content("~/scripts/knockout.validation.js")"></script>
50: <script src="@Url.Content("~/scripts/knockout.mapping-latest.js")"></script>
51: <script src="@Url.Content("~/js/site.core.js")"></script>
52: <script src="@Url.Content("~/js/site.services.js")"></script>
53: <script src="@Url.Content("~/js/site.vm.settings.js")"></script>
54: <script>
55: $(function () {
56: ko.applyBindings(site.vm.settings);
57: });
58: </script>
59: }
Ну, и как это выглядит, чтобы уж совсем всё было наглядно:
Слева я значение 17 поменяю на 15, а правом списке к уже существующим: Logs, Exhibit, Lenta добавил еще одну сущность Comment и теперь в режиме отладки хочу проверить, приходят ли данный в AjaxController. А-а-а-а-а вот они-и!
Осталось только “прикрутить” валидацию", но это пусть будет уже вашим домашним заданием, тем более, что об этом уже был разговор. А еще надо написать метод сохранения данных. Так как у меня появился прокси-класс для настроек, то теперь я могу использовать его как входящие данные для метода сохранения в Config-помощнике. Итак, представлю второй метод Config-помощника:
1: internalstatic Configuring Save(SiteSettingsJson settings)
2: {
3: Configuring success = new Configuring();
4: try
5: {
6: Configuration cfg = WebConfigurationManager.OpenWebConfiguration("~");
7: var group = cfg.SectionGroups[CONFIGGROUPNAME];
8: SiteSettings section = (SiteSettings)group.Sections[CONFIGSECTIONNAME];
9: if (section != null)
10: {
11: section.Lenta.AllowPostFromShare = settings.Lenta.AllowPostFromShare;
12: section.Lenta.DeleteAfterDays = settings.Lenta.DeleteAfterDays;
13: section.PagerSize.Clear();
14: for (int i = 0; i < settings.PagerSize.Count; i++)
15: {
16: section.PagerSize.Add(new PageSizeItemsElement()
17: {
18: Name = settings.PagerSize[i].Name,
19: Size = settings.PagerSize[i].Size
20: });
21: }
22: cfg.Save();
23: success.Success = true;
24: }
25: }
26: catch (ConfigurationErrorsException error)
27: {
28: success.ConfigException = error;
29: }
30: return success;
31: }
Вот еще маленький класс упомянутый в предыдущем листинге, для полноты картины:
1: publicclass Configuring
2: {
3: publicbool Success { get; set; }
4:
5: public ConfigurationErrorsException ConfigException { get; set; }
6: }
И, наконец, завершим начатое. Вот конечный вариант второго метода AjaxController’а, который сохраняет данные: 1: [HttpPost] 2: public JsonResult SaveSettings(SiteSettingsJson config) { 3: Response.CacheControl = "no-cache"; 4: 5: string message=string.Empty; 6: 7: if (ModelState.IsValid) 8: { 9: Config.Save(config); 10: message = "Настройки успешно сохранены"; 11: } 12: else { message = "Неверные данные в конфигурации"; } 13: return Json(message); 14: }
Заключение
Данные читаются, изменяются, сохраняются – значит поставленная цель достигнута и моя миссия завершена. Вас же я прошу писать комментарии.
Да прибудет с вами сила!
Подробнее: http://feedproxy.google.com/~r/blogmusor/~3/9Iz8lWcbfbo/96


Дайджест новых статей по интернет-маркетингу на ваш email
Новые статьи и публикации
- 2025-03-14 » SPF-запись
- 2025-03-07 » SEO на маркетплейсах: как оптимизировать карточку товара для поисковой выдачи
- 2025-02-18 » Топ-10 бесплатных нейросетей для генерации изображений: лучшие ии генераторы 2024 года
- 2025-02-11 » Критическая уязвимость в 1С-Битрикс
- 2025-02-11 » Google Search Console: руководство для начинающих вебмастеров
- 2025-02-11 » Методы измерения результативности рекламных кампаний: плюсы и минусы
- 2025-02-11 » Тренды SEO в 2025 году
- 2025-02-10 » Свой Google в локалке. Ищем иголку в стоге сена
- 2025-01-29 » SEO — это комплексная работа. Шесть главных факторов ранжирования сайтов
- 2025-01-29 » Гайд для главной страницы e-commerce сайта: как оформить, чтобы повысить конверсию
- 2025-01-20 » Krea AI выпустила бесплатную функцию преобразования изображений в 3D-объекты — их можно вращать и вписывать в фотографии
- 2025-01-19 » Отзывы на Яндекс Картах: как пройти модерацию
- 2025-01-15 » Топ-6 лучших российских нейросетей, в которых можно генерировать тексты и изображения бесплатно и без VPN
- 2025-01-14 » 15 бесплатных способов узнать, чем интересуется ваша аудитория
- 2025-01-11 » Бездепозитные бонусы в казино за регистрацию с выводом: особенности и возможности получения
- 2025-01-09 » Новая модель LAM способна выполнять задачи в Word
- 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 » Интеграция с Яндекс Еда
"Успеха в ближайшем десятилетии добьются только те компании, которые сумеют реорганизовать свою работу с помощью электронного инструментария. Только это позволит им быстро принимать правильные решения, предпринимать эффективные действия и поддерживать тесные плодотворные связи со своими клиентами." |
Мы создаем сайты, которые работают! Профессионально обслуживаем и продвигаем их , а также по всей России и ближнему зарубежью с 2006 года!
Как мы работаем
Заявка
Позвоните или оставьте заявку на сайте.
Консультация
Обсуждаем что именно Вам нужно и помогаем определить как это лучше сделать!
Договор
Заключаем договор на оказание услуг, в котором прописаны условия и обязанности обеих сторон.
Выполнение работ
Непосредственно оказание требующихся услуг и работ по вашему заданию.
Поддержка
Сдача выполненых работ, последующие корректировки и поддержка при необходимости.
Или напишите нам в WhatsApp
Или напишите нам в WhatsApp