Создание маршрутизатора WCF - Проверка сообщений

ОГЛАВЛЕНИЕ

Проверка сообщений

Хотя обычно маршрутизаторы перенаправляют исходное сообщение службам приложений, они могут выполнять действия на основе содержимого сообщения, например проверять заголовки или элементы тела в случае маршрутизации на основе содержимого, или отклонять сообщения на основе допустимости заголовков или элементов тела.

Проверка заголовков выполняется очень просто, поскольку тип Message предоставляет свойство Headers для непосредственного извлечения адресных заголовков и настраиваемых заголовков по их имени и пространству имен. Рассмотрим следующую операцию службы, использующую контракт сообщения для добавления настраиваемого заголовка LicenseKey для входящей операции.

// operation
[OperationContract]
SendMessageResponse SendMessage(SendMessageRequest message);

// message contract
[MessageContract]
public class SendMessageRequest {
  [MessageHeader]
  public string LicenseKey { get; set; }

  [MessageBodyMember]
  public string Message { get; set; }

Клиенты отправляют сообщения, содержащие заголовок LicenseKey, возможно пустой, если у них еще нет ключа лицензии. Маршрутизатор может извлечь этот заголовок следующим образом.

string licenseKey = 
  requestMessage.Headers.GetHeader<string>(
  "LicenseKey",
  "http://www.thatindigogirl.com/samples/2008/01"); 

Если это же значение LicenseKey требовалось бы передать в теле сообщения, для получения доступа к этому значению маршрутизатору необходимо было бы прочесть тело сообщения (поскольку к этой информации нет прямого доступа посредством типа Message). Метод GetReaderAtBodyContents возвращает XmlDictionaryReader, который можно использовать для чтения тела сообщения, следующим образом.

XmlDictionaryReader bodyReader = 
  requestMessage.GetReaderAtBodyContents(); 

Свойство State типа Message может быть одним из следующих значений перечисления MessageType: Created, Copied, Read, Written или Closed. Сообщение начинается в состоянии Created, и маршрутизаторы, принимающие параметры Message операций, не обрабатывают сообщения, поэтому сохраняется состояние Created.

Чтение тела сообщения вызывает переход сообщения запроса из соотояния Created в состояние Read. После прочтения сообщение невозможно перенаправить службам приложений, поскольку сообщение может быть только один раз прочитано, записано или скопировано.

Перед чтением сообщения реализация маршрутизатора на основе содержимого должна скопировать сообщение в буфер. С помощью этой буферизованной копии сообщения можно создавать новые копии исходного сообщения и использовать их для обработки следующим образом.

MessageBuffer messageBuffer = 
  requestMessage.CreateBufferedCopy(int.MaxValue);
Message messageCopy = messageBuffer.CreateMessage();
XmlDictionaryReader bodyReader =
  messageCopy.GetReaderAtBodyContents();

XmlDocument doc = new XmlDocument();
doc.Load(bodyReader);
XmlNodeList elements = doc.GetElementsByTagName("LicenseKey");
string licenseKey = elements[0].InnerText; 

Этот же буфер можно повторно использовать для создания сообщения для перенаправления к службам приложений. Вызов CreateMessage возвращает новый экземпляр Message, основанный на исходном сообщении.