Изменение сообщений SOAP с помощью расширений SOAP
Этот раздел посвящен технологии прежних версий. Веб-службы XML и клиенты веб-служб XML должны создаваться с использованием Windows Communication Foundation.
Расширения SOAP позволяют разработчикам расширять функциональные возможности веб-службы, изменяя сообщения SOAP, принимаемые и отправляемые веб-службой или ее клиентом. Например, можно реализовать алгоритм шифрования или сжатия, выполняемый с существующей веб-службой.
Прежде чем изучать принцип работы расширений SOAP, рекомендуется ознакомиться с понятием времени существования веб-службы. Дополнительные сведения см. в разделе Схема времени существования XML-веб-службы.
На следующем рисунке показаны основные этапы вызова, поступающего от клиента к веб-службе.
Как видно по схеме, платформа .NET Framework сериализует и десериализует XML на обоих этапах обработки: как на компьютере веб-службы, так и на компьютере ее клиента. В эту инфраструктуру можно добавить расширение SOAP для проверки или изменения сообщений SOAP до и после каждого из этих этапов сериализации и десериализации. Например, расширение SOAP для шифрования может зашифровать XML-часть сообщения SOAP, после того как платформа .NET Framework сериализует аргументы клиента, а затем расшифровать сообщение SOAP на веб-сервере, прежде чем .NET Framework десериализует сообщение SOAP. Эти этапы (на которых расширение SOAP может проверить или изменить сообщение SOAP) определяются перечислением SoapMessageStage. В этом случае расширение SOAP выполняет шифрование на этапе AfterSerialize, а расшифровку — на этапе BeforeDeserialize.
Как правило, если расширение SOAP изменяет содержимое сообщения SOAP, изменения должны быть выполнены как на клиенте, так и на сервере. Т. е., если расширение SOAP выполняется на клиенте и зашифровывает сообщение SOAP, соответствующее расширение SOAP должно расшифровать это сообщение на сервере. Если сообщение SOAP не расшифровывается, инфраструктуре ASP.NET не удается десериализовать сообщение SOAP в объект.
Разумеется, если расширение SOAP не изменяет сообщения SOAP (например, если оно только ведет журнал таких сообщений), оно может выполняться только на клиенте или сервере. В этом случае получателю приходит такое же сообщение SOAP, как если бы расширение SOAP не выполнялось и инфраструктура ASP.NET могла расшифровать это сообщение. Кроме того, если изменение сообщений SOAP расширением SOAP не препятствует их десериализации, выполнение расширения SOAP на обеих сторонах (на клиенте и сервере) не обязательно.
Расширение класса SOAPExtension
Чтобы реализовать расширение SOAP, создайте класс, наследуемый от класса SoapExtension. Класс SOAPExtension имеет три метода, которые следует (или необходимо) реализовать:
ChainStream — виртуальный метод
GetInitializer — абстрактный метод с двумя подписями
Initialize — абстрактный метод
ProcessMessage — абстрактный метод
Способ реализации этих методов приведен в пошаговом руководстве "Изменение сообщения SOAP с помощью расширений SOAP".
Методу ChainStream передается объект Stream, и он возвращает объект Stream. Поскольку расширение SOAP выполняется на каждом этапе SoapMessageStage и изменяет сообщение SOAP, оно должно считывать данные из объекта Stream, передаваемый методу ChainStream, и записывать их в объект Stream, возвращаемый методом ChainStream. Поэтому важно, чтобы в методе ChainStream обе ссылки на Stream были назначены переменным-членам.
Класс, унаследованный от SoapExtension, использует методы GetInitializer и Initialize для инициализации внутренних данных на основании веб-службы, к которой он применяется, или ее метода. Например, расширение SOAP, ведущее журнал сообщений SOAP, отправляемых и получаемых методом веб-службы, может инициализировать имя файла для сохранения информации журнала (на основании имени веб-службы или ее метода, с которым выполняется расширение SOAP).
В какой момент инфраструктура веб-служб вызывает метод GetInitializer, и какие параметры передаются этому методу, зависит от конфигурации расширения SOAP следующим образом:
Если расширение SOAP настроено с помощью атрибута, инфраструктура веб-служб вызывает метод GetInitializer, когда доступ к методу (method) веб-службы осуществляется впервые.
Если расширение SOAP настроено с помощью файла конфигурации, инфраструктура веб-служб вызывает метод GetInitializer, только когда доступ ко всей веб-службе выполняется впервые.
Инфраструктура веб-служб кэширует объект, возвращаемый методом GetInitializer. Затем при каждом выполнении расширения SOAP с этой веб-службой или ее методом инфраструктура передает объект инициализатора методу Initialize.
Фактическая расширенная обработка (не предусмотренная в рамках стандартной обработки SOAP) выполняется методом ProcessMessage. При каждом вызове инфраструктурой веб-служб метод ProcessMessage передает (как аргумент) экземпляр класса, унаследованного от SoapMessage, содержащий информацию о сообщении SOAP именно на этом этапе. Если расширение SOAP выполняется с веб-службой, передается объект SoapServerMessage. Если оно выполняется с клиентом веб-службы, передается объект SoapClientMessage.
Расширения Soap и исключения
Сами по себе расширения Soap никогда не должны выдавать исключения. Впрочем, они могут добавить сведения об исключении в свойство Exception объекта SoapMessage, передаваемое методу ProcessMessage.
Они также могут выполнять роль обработчика исключений для всего приложения, с помощью тех же возможностей отслеживая все исключения в приложении, для которого установлено расширение SOAP, и выполнять некоторые задачи, в том числе изменять возвращаемую ошибку SOAP.
Порядок вызова методов расширения SOAP
В предыдущей части этой статьи показано, какие методы переопределяет расширение SOAP. Теперь рассмотрим порядок действий, в котором инфраструктура веб-служб вызывает методы расширения SOAP по мере вызова метода веб-службы. Следующая последовательность предполагает, что расширение SOAP выполняется и на клиенте, и на сервере. Действия, для которых необходимо, чтобы расширение SOAP выполнялось и на клиенте, и на сервере, игнорируются платформой .NET Framework, если это условие не выполняется.
На стороне клиента подготавливается сообщение запроса
Клиент вызывает метод прокси-класса.
На клиенте создается новый экземпляр расширения SOAP.
Если это расширение SOAP выполняется с этой веб-службой на клиенте впервые, вызывается метод GetInitializer расширения SOAP.
Вызывается метод Initialize.
Вызывается метод ChainStream.
Вызывается метод ProcessMessage, при этом SoapMessageStage получает значение BeforeSerialize.
ASP.NET на клиентском компьютере сериализует аргументы метода веб-службы в XML.
Вызывается метод ProcessMessage, при этом SoapMessageStage получает значение AfterSerialize.
ASP.NET на клиентском компьютере отправляет сообщение SOAP по сети на веб-сервер, на котором размещена веб-служба.
Сторона сервера получает сообщение запроса и подготавливает ответ
ASP.NET на веб-сервере получает сообщение SOAP.
На веб-сервере создается новый экземпляр расширения SOAP.
Если это расширение SOAP выполняется с этой веб-службой на клиенте впервые на стороне сервера, на веб-сервере вызывается метод GetInitializer расширения SOAP, выполняемого на сервере.
Вызывается метод Initialize.
Вызывается метод ChainStream.
Вызывается метод ProcessMessage, при этом SoapMessageStage получает значение BeforeDeserialize.
ASP.NET десериализует аргументы в XML.
Вызывается метод ProcessMessage, при этом SoapMessageStage получает значение AfterDeserialize.
ASP.NET создает новый экземпляр класса, реализующего веб-службу, и вызывает метод веб-службы, передавая десериализованные аргументы. Этот объект находится на том же компьютере, что и веб-сервер.
Метод веб-службы выполняет его код, и в конечном итоге задает возвращаемое значение и выходные параметры.
Вызывается метод ProcessMessage, при этом SoapMessageStage получает значение BeforeSerialize.
ASP.NET на веб-сервере сериализует возвращаемое значение и выходные параметры в XML.
Вызывается метод ProcessMessage, при этом SoapMessageStage получает значение AfterSerialize.
ASP.NET отправляет ответное сообщение SOAP по сети обратно на клиент веб-службы.
Сторона клиента получает ответное сообщение
ASP.NET на клиентском компьютере получает сообщение SOAP.
Вызывается метод ProcessMessage, при этом SoapMessageStage получает значение BeforeDeserialize.
ASP.NET десериализует XML в возвращаемое значение и выходные параметры.
Вызывается метод ProcessMessage, при этом SoapMessageStage получает значение AfterDeserialize.
ASP.NET передает возвращаемое значение и выходные параметры экземпляру прокси-класса.
Клиент получает возвращаемое значение и выходные параметры.
Реализация расширения SOAP
Существует два способа запуска расширения SOAP на клиентском либо серверном приложении. Первый из них заключается в том, чтобы настроить приложение так, чтобы оно запускало расширение. Чтобы настроить расширение SOAP для выполнения со всеми веб-методами всех веб-служб, в особенности vroot, измените раздел Элемент <soapExtensionTypes> файла Web.config. Следующий код показывает, что значение атрибута type должно находиться на одной строке и содержать полное имя расширения, его версию, язык и региональные параметры и маркер открытого ключа подписанной сборки.
<configuration>
<system.web>
<webServices>
<soapExtensionTypes>
<add type="Contoso.MySoapExtension, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
priority="1" group="0"/>
</soapExtensionTypes>
</webServices>
</system.web>
</configuration>
Второй способ заключается в создании настраиваемого атрибута, который применяется к методу веб-службы. Чтобы создать настраиваемый атрибут, создайте класс, наследуемый от SoapExtensionAttribute. Подробные сведения о создании настраиваемого атрибута см. в разделе Как реализовать расширение SOAP. Дополнительные сведения о создании настраиваемых атрибутов см. в статье "Создание настраиваемых атрибутов".
Примечание |
---|
При реализации расширения SOAP следует учитывать возможность атаки типа "отказ в обслуживании", если расширение использует XmlTextReader для чтения потока данных. Один из способов предотвратить такую атаку — обеспечить присвоение свойству ProhibitDtd значения true. |
Приоритеты и группы по приоритетам
С помощью атрибутов или файла конфигурации можно назначить расширениям SOAP приоритеты, которые помогут определить относительный порядок выполнения нескольких расширений SOAP, настроенных на выполнение с методом XML-веб-службы. Чем выше приоритет расширения SOAP, тем скорее оно будет выполнено (относительно сообщения SOAP, отправляемого или принимаемого по сети в данный момент). Расширения SOAP могут принадлежать к любой из трех групп по приоритетам. В каждой группе свойство priority определяет приоритеты отдельных элементов. Чем ниже значение свойства priority, тем выше его относительный приоритет (0 — высший приоритет).
Расширения SOAP делятся на следующие три группы по относительным приоритетам: настроенные с помощью атрибута, заданные в файле конфигурации с параметром group, имеющим значение 0, и со значением 1 для этого параметра. Порядок их приоритетов следующий:
Группа с наивысшим приоритетом: расширения SOAP, настроенные с помощью файла конфигурации, для которых параметр group имеет значение 0.
Группа со средним приоритетом: расширения SOAP, настроенные с помощью атрибута.
Группа с низшим приоритетом: расширения SOAP, настроенные с помощью файла конфигурации, для которых параметр group имеет значение 1.
В следующем примере кода приведен файл конфигурации, указывающий, что расширение SOAP Logger.LoggerExtension
выполняется в рамках группы по относительным приоритетам 0
и имеет приоритет 1
.
<configuration>
<system.web>
<webServices>
<soapExtensionTypes>
<add type="Logger.LoggerExtension,logger"
priority="1"
group="0" />
</soapExtensionTypes>
</webServices>
</system.web>
</configuration>
См. также
Задачи
Как реализовать расширение SOAP
Справочник
SoapExtension
SoapExtensionAttribute
SoapMessageStage
LogicalMethodInfo
Основные понятия
Изменение сообщений SOAP с помощью расширений SOAP
Схема времени существования XML-веб-службы
Создание клиентов XML-веб-службы
Другие ресурсы
Configuring Applications
XML-веб-службы с использованием ASP.NET