В
данной лекции представлены следующие
вопросы.
-
Правила иерархической модели и то,
как применить настройки к серверу,
приложению, директории и одному
файлу.
-
Как обрабатываются разделы настроек,
и как приложения осуществляют доступ
к значениям.
-
Внутренние механизмы примера
обработчика раздела настроек.
Иерархическая модель настроек
Как
говорилось в лекции 1, модель настроек
ASP.NET наследует параметры от сервера к
приложению при помощи иерархической
модели. Благодаря иерархической модели
можно указать параметры в файле
machine.config
или web.config
родительского приложения, и эти
параметры будут переданы во все дочерние
приложения. Дочерние приложения
наследуют настройки от родительских
приложений, и все приложения наследуют
настройки из файла
machine.config.
Вы можете указать параметры для всего
сервера, одного или нескольких
приложений, одной или нескольких
директорий и даже одного файла. При
наследовании настроечных параметров
используются следующие правила.
-
Приложения сначала наследуют
настройки из файла
machine.config сервера, затем
– из файла
web.config родительского
приложения и, наконец, из своего
собственного файла
web.config.
-
Параметры в каждом файле
web.config
переопределяют параметры из файлов
machine.config и
web.config,
стоящих перед ним.
-
Наследование следует адресу URL
запрошенного ресурса и не
обязательно следует физической
структуре файлов.
-
Параметры из файла
machine.config или файла
web.config
родительского приложения могут
запретить переопределение параметров.
- С
помощью установки расположения
параметры могут относиться к
конкретной директории, приложению
или файлу.
Для
наглядной демонстрации правил
наследования давайте взглянем на
сценарий, включающий несколько
директорий и приложений. Для этого
примера используются три приложения:
App1, App2
и App3. На
рисунке 2.1 показана виртуальная
структура этих приложений.
Дополнительная
информация. Виртуальная
структура приложений – это структура,
представленная при помощи
инструмента администрирования IIS.
Эта структура не связана с
физическим расположением директорий
и просто показывает, как вы
настраиваете приложения в IIS.
Рис. 2.1. Виртуальная структура
приложений
На
рисунке 2.1 App1
и App3 –
это корневые приложения, а
App2 –
дочернее приложение
App1.
Дополнительная
информация.
App3 в
IIS представляет собой виртуальную
директорию. Виртуальная директория –
это указатель из IIS на реальную
физическую директорию на диске.
Остальные приложения не являются
виртуальными директориями, так как в
физической структуре они находятся в
одном и том же месте wwwroot, как и
в виртуальной структуре.
Наследование в иерархической модели
сначала берет во внимание виртуальную
структуру, а затем – физическую
структуру приложений. На рисунке 2.2
показана физическая структура приложений.
Мы видим, что
App1 – это поддиректория в
директории
wwwroot, а
App2 и
App3 –поддиректории
App1.
SubDir
также является поддиректорией
App1, но
не является приложением или виртуальной
директорией в IIS.
-
Включите трассировку в файле
machine.config на сервере,
следуя шагам, описанным в разделе "Редактирование
настроечных файлов" в лекции 1.
Сделав это изменение, вы включите
трассировку для всех приложений и
файлов .aspx на этом сервере.
-
Отключите трассировку в файле
web.config
для App1
– первого веб-приложения.
Рис. 2.2. Физическая структура
приложений
При
доступе к указанным URL вы увидите
следующие результаты. В этом примере в
качестве имени сайта взято
http://www.northwindtraders.com/.
При тестировании замените его именем
вашего сайта.
-
http://www.northwindtraders.com/App1.
Этот URL наследует включенную
трассировку из файла
machine.config, но параметр в
файле
web.config для
App1,
отключающий ее, переопределяет
данный параметр. Следовательно, для
указанного URL трассировка отключена.
-
http://www.northwindtraders.com/App1/App2.
App2
является в виртуальной структуре
дочерним приложением
App1,
и трассировка здесь также отключена,
поскольку
App2 наследует файл
web.config
для App1,
а в файле
web.config для
App2
переопределение этого параметра
отсутствует.
-
http://www.northwindtraders.com/App1/SubDir.
Для всех файлов в директории
SubDir
трассировка отключена, так как они
наследуют этот параметр от файла
web.config
для App1.
-
http://www.northwindtraders.com/App3.
Для App3
трассировка включена, так как оно
наследует только от файла
machine.config сервера. Хотя
в физической структуре это
приложение дочернее по отношению к
App1,
оно не является дочерним в
виртуальной структуре.
-
http://www.northwindtraders.com/App1/App3.
App3 –
это самостоятельное приложение, но
оно является поддиректорией
App1 и
доступ к нему может осуществляться
по этому пути. В результате
трассировка для
App3
отключена, так как оно наследует
данный параметр из файла
web.config
для App1.
Замечание.
Заметили интересную особенность?
Одна директория или приложение могут
иметь несколько вариантов
настроечных параметров в зависимости
от того, по какому URL производится
доступ к этому ресурсу.
URL
ресурса определяет, какие настроечные
параметры будет наследовать ресурс.
Другими словами, одни и те же ресурсы
наследуют различные настроечные
параметры в зависимости от того, какой
URL используется для доступа к ним.
Поняв то, как настроечные параметры
наследуются от сервера к приложениям,
попробуем указать, к чему относятся
настроечные параметры.
Позиционирование настроечных параметров
С
помощью тега
location можно связать параметры
с конкретным путем, приложением или
файлом. Это особенно полезно, если вы
планируете использовать для физической
директории различные параметры, но не
хотите (или не должны) делать эту
директорию приложением. Например,
требуется, чтобы одна директория имела
различные параметры трассировки.
Используйте тег
location и добавьте в файл
web.config
для App1
следующий текст.
<location
path="SubDir">
<system.web>
<trace enabled="false" />
</system.web>
</location>
<location path="notracepage.aspx">
<system.web>
<trace enabled="false" />
</system.web>
</location>
Данный
способ отключает трассировку для всех
файлов в директории
SubDir.
Замечание.
Обратите внимание, что вам все равно
требуется включить в тег
location
группу разделов
system.web.
Всегда при использовании тега
location
должно быть включено имя группы
разделов.
Трассировка будет также отключена для
всех поддиректорий директории
SubDir. Вы
можете использовать данную процедуру для
назначения настроечных параметров одному
файлу. Это приведет к отключению
трассировки для файла
notracepage.aspx,
расположенного в корневой директории
App1.
Пример
из практики. Использование тега
location
оказывается полезным, когда
требуется задать права доступа для
одного файла приложения. Помните,
что это работает только для файлов,
обрабатываемых ASP.NET, то есть вы
не можете применить настроечные
параметры к файлам html или
графическим файлам, поскольку они
обрабатываются IIS, а не ASP.NET.
Запрет
переопределения настроечных параметров
Оказывается, можно переопределить
параметры в файле
web.config приложения. Однако
бывают ситуации, когда необходимо
запретить переопределять параметры. К
счастью, есть параметр, позволяющий это
сделать.
Если в
нашем примере установить параметр
allowOverride
в файле
machine.config или
web.config
в значение false,
то независимо от того, что вы укажете в
наследующем файле
web.config приложения,
трассировка всегда будет отключена.
<system.web>
<trace enabled="false" allowOverride="false" />
</system.web>
<location path="SubDir"
allowOverride="false >
<system.web>
<trace enabled="false" />
</system.web>
</location>
Можно
использовать этот параметр в сочетании с
тегом location.
<location
path="SubDir" allowOverride="false"
>
<system.web>
<trace enabled="false">
</system.web>
</location>
Пример
из практики. Запрет на
переопределение настроечных
параметров особенно полезен, если вы
являетесь администратором или
работаете в компании,
предоставляющей услуги хостинга. Он
позволяет установить глобальные
параметры для вашего сервера,
которые не могут быть изменены
вашими клиентами для отдельных
приложений.
Помните, что при использовании свойства
allowOverride="false"
любое приложение, которое пытается
переопределить этот параметр,
сгенерирует ошибку конфигурации. Перед
тем как задавать параметр
allowOverride="false",
убедитесь, что ни одно из приложений не
пытается установить это значение – иначе
вы нарушите их работу.
Изучение обработчиков разделов настроек
Итак,
я уже описал, где следует вводить
параметры, как эти параметры наследуются,
как указать, к чему они относятся, и как
их заблокировать. Теперь давайте
рассмотрим, как используются настроечные
параметры. Обработчики разделов настроек
обрабатывают параметры, указанные в
настроечных файлах, и делают их
доступными для приложений. Обработчики
разделов настроек – это классы, которые
реализуют интерфейс
IConfigurationSectionHandler.
Данные классы интерпретируют и
обрабатывают параметры из настроечного
файла и возвращают объект конфигурации,
основанный на этих параметрах.
Как
уже было сказано ранее, обработчики
разделов настроек сначала объявляются в
configSections.
Давайте снова посмотрим на объявление
обработчика настроек.
<section
name="appSettings"
type="System.Configuration.NameValueFileSectionHandler,
System,
Version=1.0.3300.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089" />
<appSettings>
<add key="MyPassword" value="Secret"
/>
<add key="ServerIP"
value="192.168.31.1" />
</appSettings>
Это
объявление раздела
<appSettings>
настроечного файла. Данный раздел
используется для хранения пар имя/значение,
к которым нужно получать доступ из
любого файла приложения. Данное
объявление указывает настроечному файлу
на класс, который будет обрабатывать
этот раздел. Вот пример раздела
<appSettings>,
который добавляет еще две пары имя/значение.
<appSettings>
<add key="MyPassword"
value="Secret">
<add key="ServerIP"
value="192.168.31.1">
</appSettings>
Теперь
доступ к этим параметрам можно получить
из приложений, что значительно облегчает
отслеживание и изменение параметров,
используемых на различных страницах или
в приложениях. Мы знаем, где
располагается объявление обработчика, но
еще не увидели реального кода .NET
Framework для объявления обработчика.
Взглянуть на пример обработчика можно в
исходном коде Microsoft Shared Source
CLI Implementation (кодовое имя: Rotor),
который является замечательной вещью.
Дополнительная
информация. Microsoft Shared
Source CLI Implementation, известная
как Rotor, – это реализация с
открытыми исходными текстами
значительной части .NET Framework,
доступная для разработчиков. Это не
совсем тот код, который используется
в .NET Framework, но он очень похож
на него и выполняет те же функции.
Однако между ними имеются
многочисленные отличия, так как код
Rotor разработан для того, чтобы
быть наиболее переносимым и читаемым.
За дополнительной информацией
обратитесь по адресу
http://msdn.microsoft.com/downloads/default.asp?url=/downloads/topic.asp?URL=/MSDN-FILES/028/000/123/topic.xml.
Следующий код – это обработчик раздела
настроек для раздела
<appSettings>,
который называется
NameValueFileSectionHandler. Я
удалил из него код, не имеющий отношения
к этому обсуждению.
//——————————————————––––––––––––———————————————
// <copyright file="NameValueFileSectionHandler.cs"
company="Microsoft">
//
// Copyright (c) 2002
Microsoft Corporation All
rights reserved.
// The use and distribution
terms for this software are
contained in the
// file named license.txt,
which can be found in the root of
this
// distribution. By using this
software in any fashion, you are
agreeing
// to be bound by the terms of
this license
// You must not remove this
notice, or any other, from this
software.
//
// </copyright>
//——————————————————––––––––––––———————————————
#if !LIB
namespace System.Configuration {
using System.IO;
using System.Xml;
public class
NameValueFileSectionHandler :
IConfigurationSectionHandler {
public object Create(object parent,
object configContext,
XmlNode section) {
object result = parent;
// parse XML
XmlNode fileAttribute =
section.Attributes.RemoveNamedItem("file");
result =
NameValueSectionHandler.CreateStatic(result,
section);
if (fileAttribute != null &&
fileAttribute.Value.Length != 0) {
/* Удалено для краткости. Этот
раздел будет срабатывать, если
имеется
свойство file="", расположенное в
разделе appSettings */
}
return result;
}
}
}
#endif
Данный
обработчик проверяет, имеется ли
свойство file=",
а затем, если это свойство пустое,
возвращает значение, основанное на
вызове метода
NameValueSectionHandler.CreateStatic().
Это метод, создающий объект конфигурации.
Ниже приведен код
NameValueSectionHandler.
//———————————————————————————––––––––––––——————
// <copyright file="NameValueSectionHandler.cs"
company="Microsoft">
//
// Copyright (c) 2002
Microsoft Corporation All rights
reserved.
// The use and distribution
terms for this software are
contained in the
// file named license.txt,
which can be found in the root of
this
// distribution. By using this
software in any fashion, you are
agreeing
// to be bound by the terms of
this license
// You must not remove this
notice, or any other, from this
software.
//
// </copyright>
//——————————––––––––––––———————————————————————
#if !LIB
namespace System.Configuration {
using System.Collections;
using System.Collections.Specialized;
using System.Xml;
using System.Globalization;
public class NameValueSectionHandler
:
IConfigurationSectionHandler {
const string defaultKeyAttribute =
"key";
const string defaultValueAttribute =
"value";
public object Create(object parent,
object context,
XmlNode section) {
return CreateStatic(parent, section,
KeyAttributeName,
ValueAttributeName);
}
internal static object
CreateStatic(object parent,
XmlNode section) {
return CreateStatic(parent, section,
defaultKeyAttribute,
defaultValueAttribute);
}
internal static object
CreateStatic(object parent, XmlNode
section, string keyAttriuteName,
string valueAttributeName)
{
ReadOnlyNameValueCollection result;
// start result off as a
shallow clone of the parent
if (parent == null)
result = new ReadOnlyNameValueCollection(new
CaseInsensitiveHashCodeProvider(
CultureInfo.InvariantCulture),
new CaseInsensitiveComparer(
CultureInfo.InvariantCulture));
else {
ReadOnlyNameValueCollection parentCollection =
(ReadOnlyNameValueCollection)parent;
result =
new ReadOnlyNameValueCollection(parentCollection);
}
// process XML
HandlerBase.CheckForUnrecognizedAttributes(section);
foreach (XmlNode child in
section.ChildNodes) {
// skip whitespace and comments
if (HandlerBase.IsIgnorableAlsoCheckForNonElement(
child))
continue;
// handle <set>, <remove>, <clear> tags
if (child.Name == "add") {
String key = HandlerBase.RemoveRequiredAttribute(
child, keyAttriuteName);
String value = HandlerBase.RemoveRequiredAttribute(
child, valueAttributeName, true
/*allowEmptyString*/);
HandlerBase.CheckForUnrecognizedAttributes(child);
result[key] = value;
}
else if (child.Name == "remove") {
String key = HandlerBase.RemoveRequiredAttribute(
child, keyAttriuteName);
HandlerBase.CheckForUnrecognizedAttributes(child);
result.Remove(key);
}
else if (child.Name.Equals("clear")) {
HandlerBase.CheckForUnrecognizedAttributes(child);
result.Clear(); }
else {
HandlerBase.ThrowUnrecognizedElement(child);
}
}
result.SetReadOnly();
return result;
}
protected virtual string
KeyAttributeName {
get { return defaultKeyAttribute;}
}
protected virtual string
ValueAttributeName {
get { return defaultValueAttribute;}
}
}
}
#endif
Данный
код создает объект коллекции настроек,
содержащий пары различных ключей и
значений из раздела настроек
<appSettings>.
Я не буду тратить много времени на
объяснение кода обработчика, но давайте
рассмотрим несколько наиболее важных пар.
Метод
CreateStatic() вызывается из
первого обработчика раздела и создает
объект конфигурации
ReadOnlyNameValueCollection,
который будет хранить всю информацию о
парах различных ключей и значений.
Давайте посмотрим на код, который
используется для разбора XML.
if (child.Name
== "add") {
String key =
HandlerBase.RemoveRequiredAttribute(child,
keyAttriuteName);
String value =
HandlerBase.RemoveRequiredAttribute(child,
valueAttributeName, true/*allowEmptyString*/);
HandlerBase.CheckForUnrecognizedAttributes(child);
result[key] = value;
}
Если
имя дочернего элемента XML равно "add",
то этот код добавляет в объект типа
ReadOnlyNameValueCollection с
именем result
пару ключ/значение. Когда вы в своем
коде ссылаетесь на коллекцию
<appSettings>,
то осуществляете доступ к этой коллекции
и обращаетесь к значениям, сохраненным в
этом разделе.
Обработчики разделов настроек
интерпретируют все параметры из
конкретных разделов и делают их
доступными для приложений. В лекции 9
описывется, как создавать собственные
обработчики разделов настроек для
интерпретации параметров из собственных
разделов.
Ключевые моменты
-
Иерархическая модель настроек
организует различные виды
наследования от сервера к приложению
и от одного приложения к другому.
Это наследование основано на URL,
который используется для доступа к
требуемому ресурсу.
-
Для указания того, что настроечные
параметры относятся к конкретной
директории или даже одному файлу,
используется тег
location.
-
Для запрета переопределение
параметров другими файлами
web.config
используется параметр
allowOverride.
-
Обработчики разделов настроек делают
настройки конфигурации доступными
для приложений, обрабатывая XML и
возвращая объект конфигурации.
|