Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В примере текста показано, как реализовать пользовательский кодировщик текстовых сообщений с помощью Windows Communication Foundation (WCF).
WCF TextMessageEncodingBindingElement поддерживает только кодировки UTF-8, UTF-16 и Юникода с прямым порядком байтов. Кодировщик пользовательского текстового сообщения в этом примере поддерживает все кодировки символов, поддерживаемые платформой, которые могут потребоваться для взаимодействия. Пример состоит из клиентской консольной программы (.exe), библиотеки служб (.dll), размещенной службами IIS, а также библиотекой кодировщика текстовых сообщений (.dll). Служба реализует контракт, определяющий шаблон связи с запросом и ответом. Контракт определяется интерфейсом ICalculator
, который предоставляет математические операции (добавление, вычитание, умножение и деление). Клиент выполняет синхронные запросы к заданной математической операции, и служба отвечает результатом. Клиент и служба используют CustomTextMessageEncoder
вместо значения по умолчанию TextMessageEncodingBindingElement.
Реализация пользовательского кодировщика состоит из фабрики кодировщика сообщений, кодировщика сообщений, элемента привязки сообщения и обработчика конфигурации и демонстрирует следующее:
Создание кастомного кодировщика и фабрики кодировщиков.
Создание элемента привязки для пользовательского кодировщика.
Использование пользовательской конфигурации привязки для интеграции собственных элементов привязки.
Разработка настраиваемого обработчика конфигурации, позволяющего настроить файл конфигурации для пользовательского элемента связывания.
Настройка, сборка и запуск примера
Установите ASP.NET 4.0 с помощью следующей команды.
%windir%\Microsoft.NET\Framework\v4.0.XXXXX\aspnet_regiis.exe /i /enable
Убедитесь, что вы выполнили процедуру настройки One-Time для образцов Windows Communication Foundation.
Чтобы создать решение, следуйте инструкциям по созданию примеров Windows Communication Foundation.
Чтобы запустить пример в конфигурации с одним или несколькими компьютерами, следуйте инструкциям в запуска примеров Windows Communication Foundation.
Фабрика кодировщика сообщений и кодировщик сообщений
Когда ServiceHost или клиентский канал открывается, компонент CustomTextMessageBindingElement
времени разработки создает CustomTextMessageEncoderFactory
. Фабрика создаёт CustomTextMessageEncoder
объект. Кодировщик сообщений работает как в режиме потоковой передачи, так и в буферизованном режиме.
XmlReader используется для чтения и XmlWriter для записи сообщений соответственно. В отличие от оптимизированных объектов чтения и записи XML в WCF, поддерживающих только UTF-8, UTF-16 и big-endian Unicode, эти объекты чтения и записи поддерживают все кодировки, поддерживаемые платформой.
В следующем примере кода показан customTextMessageEncoder.
public class CustomTextMessageEncoder : MessageEncoder
{
private CustomTextMessageEncoderFactory factory;
private XmlWriterSettings writerSettings;
private string contentType;
public CustomTextMessageEncoder(CustomTextMessageEncoderFactory factory)
{
this.factory = factory;
this.writerSettings = new XmlWriterSettings();
this.writerSettings.Encoding = Encoding.GetEncoding(factory.CharSet);
this.contentType = $"{this.factory.MediaType}; charset={this.writerSettings.Encoding.HeaderName}";
}
public override string ContentType
{
get
{
return this.contentType;
}
}
public override string MediaType
{
get
{
return factory.MediaType;
}
}
public override MessageVersion MessageVersion
{
get
{
return this.factory.MessageVersion;
}
}
public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType)
{
byte[] msgContents = new byte[buffer.Count];
Array.Copy(buffer.Array, buffer.Offset, msgContents, 0, msgContents.Length);
bufferManager.ReturnBuffer(buffer.Array);
MemoryStream stream = new MemoryStream(msgContents);
return ReadMessage(stream, int.MaxValue);
}
public override Message ReadMessage(Stream stream, int maxSizeOfHeaders, string contentType)
{
XmlReader reader = XmlReader.Create(stream);
return Message.CreateMessage(reader, maxSizeOfHeaders, this.MessageVersion);
}
public override ArraySegment<byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset)
{
MemoryStream stream = new MemoryStream();
XmlWriter writer = XmlWriter.Create(stream, this.writerSettings);
message.WriteMessage(writer);
writer.Close();
byte[] messageBytes = stream.GetBuffer();
int messageLength = (int)stream.Position;
stream.Close();
int totalLength = messageLength + messageOffset;
byte[] totalBytes = bufferManager.TakeBuffer(totalLength);
Array.Copy(messageBytes, 0, totalBytes, messageOffset, messageLength);
ArraySegment<byte> byteArray = new ArraySegment<byte>(totalBytes, messageOffset, messageLength);
return byteArray;
}
public override void WriteMessage(Message message, Stream stream)
{
XmlWriter writer = XmlWriter.Create(stream, this.writerSettings);
message.WriteMessage(writer);
writer.Close();
}
}
В следующем примере кода показано, как создать фабрику кодировщика сообщений.
public class CustomTextMessageEncoderFactory : MessageEncoderFactory
{
private MessageEncoder encoder;
private MessageVersion version;
private string mediaType;
private string charSet;
internal CustomTextMessageEncoderFactory(string mediaType, string charSet,
MessageVersion version)
{
this.version = version;
this.mediaType = mediaType;
this.charSet = charSet;
this.encoder = new CustomTextMessageEncoder(this);
}
public override MessageEncoder Encoder
{
get
{
return this.encoder;
}
}
public override MessageVersion MessageVersion
{
get
{
return this.version;
}
}
internal string MediaType
{
get
{
return this.mediaType;
}
}
internal string CharSet
{
get
{
return this.charSet;
}
}
}
Элемент привязки кодирования сообщений
Элементы привязки позволяют настроить стек времени выполнения WCF. Чтобы использовать пользовательский кодировщик сообщений в приложении WCF, требуется элемент привязки, создающий фабрику кодировщика сообщений с соответствующими параметрами на соответствующем уровне в стеке времени выполнения.
CustomTextMessageBindingElement
выводится из базового класса BindingElement и наследуется от класса MessageEncodingBindingElement. Это позволяет другим компонентам WCF распознавать этот элемент привязки как элемент привязки сообщения. Реализация CreateMessageEncoderFactory возвращает экземпляр фабрики кодировщика сообщений, соответствующей заданным параметрам.
CustomTextMessageBindingElement
открывает настройки для MessageVersion
, ContentType
и Encoding
через свойства. Кодировщик поддерживает версии Soap11Addressing и Soap12Addressing1. Значение по умолчанию — Soap11Addressing1. Значением по умолчанию является ContentType
text/xml. Свойство Encoding
позволяет задать значение требуемой кодировки символов. В примере клиента и службы используется кодировка символов ISO-8859-1 (Latin1), которая не поддерживается TextMessageEncodingBindingElement WCF.
В следующем коде показано, как программно создать привязку с помощью пользовательского кодировщика текстовых сообщений.
ICollection<BindingElement> bindingElements = new List<BindingElement>();
HttpTransportBindingElement httpBindingElement = new HttpTransportBindingElement();
CustomTextMessageBindingElement textBindingElement = new CustomTextMessageBindingElement();
bindingElements.Add(textBindingElement);
bindingElements.Add(httpBindingElement);
CustomBinding binding = new CustomBinding(bindingElements);
Добавление поддержки метаданных в элемент привязки кодирования сообщений
Любой тип, наследуемый от MessageEncodingBindingElement, отвечает за обновление версии привязки SOAP в документе WSDL, созданном для службы. Это делается путем реализации ExportEndpoint
метода в интерфейсе IWsdlExportExtension , а затем изменения созданного WSDL. В этом примере CustomTextMessageBindingElement
использует логику экспорта WSDL из TextMessageEncodingBindingElement
.
Для этого примера конфигурация клиента настраивается вручную. Нельзя использовать Svcutil.exe для создания конфигурации клиента, так как политика CustomTextMessageBindingElement
не экспортирует утверждение для описания своего поведения. Обычно следует реализовать IPolicyExportExtension интерфейс в элементе пользовательской привязки для экспорта утверждения пользовательской политики, описывающего поведение или возможность, реализованную элементом привязки. Пример экспорта утверждения политики для пользовательского элемента привязки см. в примере Transport: UDP .
Обработчик конфигурации привязки кодирования сообщений
В предыдущем разделе показано, как программно использовать кодировщик пользовательского текстового сообщения.
CustomTextMessageEncodingBindingSection
реализует обработчик конфигурации, который позволяет вам указать использование пользовательского кодировщика текстовых сообщений в файле конфигурации. Класс CustomTextMessageEncodingBindingSection
наследуется от класса BindingElementExtensionElement. Свойство BindingElementType
сообщает системе конфигурации типа элемента привязки, который будет создан для этого раздела.
Все параметры, определенные CustomTextMessageBindingElement
, представлены как свойства в CustomTextMessageEncodingBindingSection
.
ConfigurationPropertyAttribute помогает сопоставить атрибуты элемента конфигурации со свойствами и задать значения по умолчанию, если атрибут не задан. После загрузки и применения значений из конфигурации к свойствам типа CreateBindingElement вызывается метод, который преобразует свойства в конкретный экземпляр элемента привязки.
Этот обработчик конфигурации соответствует следующему представлению в App.config или Web.config для службы или клиента.
<customTextMessageEncoding encoding="utf-8" contentType="text/xml" messageVersion="Soap11Addressing1" />
В примере используется кодировка ISO-8859-1.
Чтобы использовать этот обработчик конфигурации, его необходимо зарегистрировать с помощью следующего элемента конфигурации.
<extensions>
<bindingElementExtensions>
<add name="customTextMessageEncoding" type="
Microsoft.ServiceModel.Samples.CustomTextMessageEncodingBindingSection,
CustomTextMessageEncoder" />
</bindingElementExtensions>
</extensions>