SiteMapProv >

Щоб внести справді суттєві зміни в роботу моделі навігації ASP.NET, доведеться створити власний постачальник картки сайту. Необхідність створення спеціального постачальника картки сайту може виникати з кількох причин:

Інформацію про карту сайту потрібно зберігати в іншому джерелі даних (наприклад, реляційна база даних).

Інформацію про карту сайту потрібно зберігати у вигляді схеми, відмінної від формату XML, який очікується ASP.NET. Це найімовірніше за наявності готової системи для зберігання карток сайтів.

Потрібна надзвичайно динамічна карта сайту, що генерується "на льоту". Наприклад, може знадобитися генерувати окрему карту сайту залежно від поточного користувача, параметрів запиту тощо.

У разі реалізації спеціального постачальника картки сайту можна використовувати одну з двох можливостей. Усі постачальники карт сайтів є похідними від абстрактного базового класу SiteMapProv & StatSiteMapProvider. Він надає базову реалізацію багатьох методів, включаючи логіку зберігання та пошуку вузлів.

У наступних розділах ми розглянемо спеціальний постачальник, який дозволяє зберігати інформацію про картку сайту у базі даних.

Зберігання інформації про картку сайту в базі даних

На малюнку нижче показано таблицю SiteMap з деякими зразками даних, яка брутально повторює карту сайту, представлену в попередній статті:

картки сайту

У цьому рішенні постачальник карти сайту не звертається до таблиці безпосередньо. Натомість він буде використовувати процедуру, що зберігається. Це надає рішенню деяку гнучкість і потенційно дозволяє зберігати інформацію про навігацію в іншій схемі за умови, що процедура, що зберігається, повертатиме таблицю з очікуваними іменами стовпців. У цьому прикладі використанонаступна процедура, що зберігається, і таблиця:

Створення постачальника картки сайту

Перш за все, необхідно перевизначити метод Initialize(), щоб отримати всю необхідну інформацію, що відноситься до сайту, з файлу web.config. Метод Initialize() надає доступ до елемента конфігурації у файлі web.config та визначає постачальника картки сайту.

У цьому прикладі постачальник потребує трьох фрагментів інформації:

Рядок з'єднання з базою даних, в якій зберігаються дані карти сайту (у моєму випадку таблиця SiteMap знаходиться у тестовій базі даних Northwind).

Ім'я процедури, що зберігається, яка повертає карту сайту.

Ім'я постачальника бази даних. Це дозволяє використовувати незалежне від постачальника кодування. Іншими словами, SQL Server, Oracle або будь-яку іншу базу даних можна підтримувати однаково просто, за умови, що є встановлена ​​фабрика постачальників .NET.

Веб-додаток можна налаштувати для використання спеціального постачальника (SqlSiteMapProvider) та надати три необхідні порції інформації в розділі файлу web.config:

Тепер у своєму постачальнику потрібно просто одержати ці три порції інформації та зберегти їх для подальшого використання. Код, який потрібно додати до класу SqlSiteMapProvider, має такий вигляд:

Реальну роботу постачальник виконує у методі BuildSiteMap(), який створює об'єкти SiteMapNode, що утворюють навігаційне дерево. Зазвичай під час існування програми можна буде створити об'єкт SiteMapNode один раз, а потім повторно використовувати його багато разів. Щоб це було можливим, постачальник повинен зберегти картку сайту в пам'яті або кешувати її. Я вибрав другий варіант.

Кореневий вузол SiteMapNode містить перший рівень вузлів, який, у свою чергу,міститиме наступний рівень вузлів, і т.д. Таким чином, кореневий вузол є точкою для всього дерева навігації.

Щоб створити карту сайту, потрібно перевизначити метод BuildSiteMap(). Спочатку необхідно перевірити, чи було вже згенеровано мапу сайту, а потім створити її. Оскільки кілька сторінок можуть спільно використовувати один і той же екземпляр постачальника картки сайту, перед оновленням будь-якої інформації загального користування (такі як дерево навігації, що зберігається в пам'яті) доцільно заблокувати об'єкт:

Давайте розглянемо цей код докладніше. Після вилучення кореневого вузла з кешу він перевіряється на наявність null-посилання, що свідчить, що це об'єкт створюється вперше. Якщо це так, потрібно створити постачальника бази даних і застосувати його для виклику збереженої процедури, яка отримує хронологію навігації. Хронологія навігації зберігається в об'єкті DataSet (об'єкт DataReader не буде працювати, оскільки для переміщення структурою карти сайту необхідна навігація назад і вперед).

Після цього необхідно перейти до DataTable, щоб створити об'єкти SiteMapNode, починаючи з кореневого вузла. Кореневий вузол можна знайти за допомогою пошуку вузла, що не має батька (у такого вузла властивість parentID має значення null у таблиці SiteMap). У цьому прикладі перевірка на всілякі стани помилок (наприклад, дублювання кореневих вузлів) не виконується.

Після цього потрібно заповнити частину ієрархії, що залишилася. Цей крок необхідно виконувати рекурсивно, що дозволить проникнути углиб ієрархії, що має необмежену кількість рівнів. З цією метою постачальник SqlSiteMapProvider використовує приватний метод AddChildren, який заповнює один рівень. Після завершення цього процесу буде повернуто кореневий вузол,надає доступ до всієї карти сайту.

Метод AddChildren() просто шукає в DataTable записи, у яких властивість Parent >AddNode(), успадкованого від класу StaticSiteMapProvider. Нижче наведено повний код:

Залишилося тільки заповнити ще кілька обов'язкових перевантажень, які отримують інформацію про картку сайту:

Цей код завершує приклад. Тепер можна запитати ті самі сторінки, що були створені раніше, за допомогою нового постачальника картки сайту (конфігурація якого задана у файлі web.config). По суті, використовується така сама розмітка. Спеціальний постачальник підключається легко та просто. Нова інформація проходитиме через спеціальний постачальник і надходитиме на сторінки без будь-якого натяку на зміну в базовій структурі. Можна просто видалити файл Web.sitemap створений у прикладі з попередньої статті та запустити цей приклад (з тією ж розміткою майстер-сторінки), щоб переконатися, що вузли завантажуються з бази даних, а не з фала:

даних

Додавання сортування

На даний момент постачальник SqlSiteMapProvider повертає результати, впорядковані за заголовком в алфавітному порядку. Це означає, що сторінка "Служби" завжди з'являтиметься перед сторінкою "Товари". Для швидкої перевірки такий варіант є цілком прийнятним, але на практиці, ймовірно, потрібно буде керувати порядком появи сторінок. На щастя, існує просте вирішення цього завдання. Насправді, для цього навіть не потрібно змінювати код SqlSiteMapProvider. Достатньо буде додати до таблиці SiteMap нове поле (скажімо, OrdinalPosition) та змінити процедуру GetSiteMap так, щоб вона використовувала це поле:

По-перше, записи сортуються за групами батьківських вузлів (тобто процедура визначає, під яким вузлом повинні розташовуватися ці вузли). Потім вониупорядковуються за значеннями Ordinalposition, якщо вони були задані. І, нарешті, вони сортуються за заголовками.

Сортування здійснюється тільки до тих груп сторінок, які знаходяться на тому самому рівні. Наприклад, можна використовувати одні й ті самі порядкові числа (скажімо, 1, 2, 3), щоб упорядкувати сторінки в галузі Products так само, як у галузі Services. Якщо дві сторінки з однієї і тієї ж групи матимуть однаковий порядковий номер, їх упорядкування щодо один одного виконуватиметься в алфавітному порядку за заголовком. (Побічним ефектом у цьому випадку буде те, що якщо не задати якісь порядкові номери, вузли будуть відсортовані в алфавітному порядку за заголовками, як це було зроблено в попередньому прикладі.)

Додавання кешування

Ви могли помітити, що SqlSiteMapProvider постійно зберігає кореневий вузол для поточної картки сайту в кеші. Якби він зберігав цей вузол у пам'яті (наприклад, у полі класу), це означало, що SqlSiteMapProvider використовує ту саму карту сайту доти, доки не буде перезапущено домен програми (наприклад, при повторному створенні веб-сайту або зміні його) параметрів конфігурації). Якщо передбачається регулярна зміна карти сайту, то перевірити, чи були сприйняті зміни додатком, і чи було оновлено карту сайту, можна кількома способами. Найкраще для цієї мети підходить кешування даних, завдяки якому кореневий вузол зберігатиметься протягом певного періоду часу.

Давайте акцентуємо увагу на моментах попереднього прикладу, пов'язаних з кешуванням. Спочатку ми вказали тимчасову межу терміну зберігання картки сайту в кеші, використовуючи файл конфігурації web.config (у вигляді значення, вираженого в секундах):

КонструкторSqlSiteMapProvider отримує його за допомогою наступного оператора:

У методі BuildSiteMap() першому створенні карти сайту кореневий вузол кешується, а при повторному запиті витягується з кешу:

Щоб написати більш витончений код, можна застосувати перевірку кешу на основі SQL Server. Це дозволить автоматично видаляти карту сайту, що знаходиться в кеші, якщо у таблиці SiteMap відбудуться зміни. Єдиний недолік такого підходу в тому, що ця особливість є специфічною для SQL Server, тому в разі її застосування втрачаються широкі можливості сумісності з базою даних, які пропонує SqlSiteMapProvider (нині він підтримує будь-яке джерело даних, яке має постачальника та фабрику даних ADO.NET) ).

Налаштування параметрів безпеки

Щоб задіяти засіб налаштування параметрів безпеки, потрібно використовувати атрибут securityTrimmingEnabled під час реєстрації постачальника картки сайту у файлі web.config. Незважаючи на те, що для цієї мети можна було б відредагувати кореневий файл web.config на веб-сервері, найпростіше додати стандартний постачальник картки сайту з новими параметрами конфігурації, як показано нижче:

Після включення засіб налаштування параметрів безпеки автоматично застосовується до всіх вузлів файлу картки сайту. Тим не менш, цю поведінку можна змінити. Якщо відомо, що певні розділи картки сайту мають бути показані всім користувачам, або якщо ви не хочете застосовувати засіб налаштування параметрів безпеки для приховування деяких сторінок, його можна явно вимкнути для певної частини картки сайту. Для цього атрибут roles даного вузла повинен бути встановлений *, як показано нижче:

Тепер вузол Services буде видно всім користувачам, незалежно від їх ролі, навіть якщо засібналаштування параметрів безпеки увімкнено. Необхідність у цьому виникає з кількох причин:

З метою підвищення продуктивності.

Чим менше вузлів ASP.NET перевірятиме, тим менше накладних витрат припадатиме на кожен запит.

З метою полегшення користувачам використання захищеної сторінки як відправна точка.

Щоб уникнути приховування дочірніх вузлів.

Наприклад, якщо вузол Administration містить інші вузли, які не захищені (наприклад, Meet Our Administrators), ці вузли виявляться прихованими, якщо буде прихований вузол Administration. Ця проблема зазвичай свідчить про непродуманий дизайн карти сайту.

Значення атрибуту roles не передається до вкладених вузлів. Це означає, що якщо вузол Administration містить інші вузли, і ці вузли вказують на захищені сторінки, які потрібно показувати в карті сайту, кожен такий вузол потрібно буде додати атрибут roles="*".

Налаштування параметрів безпеки передбачає, що у кожному запиті буде виконано додаткову роботу. Якщо карта сайту містить велику кількість вузлів, то додаткове навантаження може негативно вплинути на продуктивність. У Microsoft рекомендують використовувати засіб налаштування параметрів безпеки для тих карток сайту, в яких налічується не більше 150 вузлів. Інший спосіб забезпечення високої продуктивності передбачає відключення засобу налаштування параметрів безпеки для тих розділів картки сайту, в яких не потрібно використовувати атрибут roles.