Delen via


Custom Message Encoder: Custom Text Encoder

In het tekstvoorbeeld ziet u hoe u een aangepaste coderingsprogramma voor tekstberichten implementeert met behulp van Windows Communication Foundation (WCF).

Het TextMessageEncodingBindingElement wcf ondersteunt alleen de UTF-8-, UTF-16- en big-endian Unicode-coderingen. De aangepaste coderingsprogramma voor tekstberichten in dit voorbeeld ondersteunt alle door het platform ondersteunde tekencoderingen die mogelijk vereist zijn voor interoperabiliteit. Het voorbeeld bestaat uit een clientconsoleprogramma (.exe), een servicebibliotheek (.dll) die wordt gehost door Internet Information Services (IIS) en een bibliotheek voor het coderingsprogramma voor tekstberichten (.dll). De service implementeert een contract dat een communicatiepatroon aanvraagantwoord definieert. Het contract wordt gedefinieerd door de ICalculator interface, die wiskundige bewerkingen weergeeft (optellen, aftrekken, vermenigvuldigen en delen). De client doet synchrone aanvragen voor een bepaalde wiskundige bewerking en de service reageert met het resultaat. Zowel client als service maakt gebruik van de CustomTextMessageEncoder in plaats van de standaardwaarde TextMessageEncodingBindingElement.

De implementatie van de aangepaste encoder bestaat uit een berichtencoderingsfactory, een berichtcoderingsprogramma, een bindingselement voor berichtcodering en een configuratie-handler, en demonstreert het volgende:

  • Een aangepaste encoder- en encoderfactory bouwen.

  • Een bindingselement maken voor een aangepaste encoder.

  • De aangepaste bindingsconfiguratie gebruiken voor het integreren van aangepaste bindingselementen.

  • Het ontwikkelen van een aangepaste configuratie-handler om bestandsconfiguratie van een aangepast bindingselement toe te staan.

Het voorbeeld instellen, compileren en uitvoeren

  1. Installeer ASP.NET 4.0 met de volgende opdracht.

    %windir%\Microsoft.NET\Framework\v4.0.XXXXX\aspnet_regiis.exe /i /enable
    
  2. Zorg ervoor dat u de eenmalige installatieprocedure voor de Windows Communication Foundation-voorbeelden hebt uitgevoerd.

  3. Volg de instructies in Het bouwen van de Windows Communication Foundation-voorbeelden om de oplossing te bouwen.

  4. Als u het voorbeeld wilt uitvoeren in een configuratie met één of meerdere computers, volgt u de instructies in Het uitvoeren van de Windows Communication Foundation-voorbeelden.

Message Encoder Factory en de Message Encoder

Wanneer het ServiceHost of het clientkanaal wordt geopend, wordt het ontwerptijdonderdeel CustomTextMessageBindingElement gemaakt CustomTextMessageEncoderFactory. De fabriek maakt de CustomTextMessageEncoder. De berichtcoderingsprogramma werkt zowel in de streamingmodus als in de buffermodus. Hierbij worden respectievelijk XmlReader de berichten XmlWriter gelezen en geschreven. In tegenstelling tot de geoptimaliseerde XML-lezers en schrijvers van WCF die alleen UTF-8, UTF-16 en big-endian Unicode ondersteunen, ondersteunen deze lezers en schrijvers alle door het platform ondersteunde codering.

In het volgende codevoorbeeld ziet u de 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();
    }
}

In het volgende codevoorbeeld ziet u hoe u de factory voor berichtcoderingsprogramma's bouwt.

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;
        }
    }
}

Bindingselement voor berichtcodering

De bindingselementen maken de configuratie van de WCF-runtimestack mogelijk. Als u de aangepaste berichtcoderingsprogramma in een WCF-toepassing wilt gebruiken, is een bindingselement vereist waarmee de factory voor berichtcoderingsprogramma's met de juiste instellingen op het juiste niveau in de runtimestack wordt gemaakt.

De CustomTextMessageBindingElement waarden zijn afgeleid van de BindingElement basisklasse en overnemen van de MessageEncodingBindingElement klasse. Hierdoor kunnen andere WCF-onderdelen dit bindingselement herkennen als een bindingselement voor berichtcodering. De implementatie van CreateMessageEncoderFactory retourneert een exemplaar van de overeenkomende berichtencoderingsfactory met de juiste instellingen.

De CustomTextMessageBindingElement instellingen voor MessageVersion, ContentTypeen Encoding via eigenschappen worden weergegeven. De encoder ondersteunt zowel Soap11Addressing- als Soap12Addressing1-versies. De standaardwaarde is Soap11Addressing1. De standaardwaarde van de ContentType waarde is 'text/xml'. Met Encoding de eigenschap kunt u de waarde van de gewenste tekencodering instellen. De voorbeeldclient en -service maken gebruik van de ISO-8859-1 -tekencodering (Latin1), die niet wordt ondersteund door wcf TextMessageEncodingBindingElement .

De volgende code laat zien hoe u de binding programmatisch maakt met behulp van de aangepaste tekstberichtcoderingsprogramma.

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);

Ondersteuning voor metagegevens toevoegen aan het element Berichtcoderingsbinding

Elk type dat is afgeleid van MessageEncodingBindingElement , is verantwoordelijk voor het bijwerken van de versie van de SOAP-binding in het WSDL-document dat voor de service is gegenereerd. Dit wordt gedaan door de ExportEndpoint methode op de IWsdlExportExtension interface te implementeren en vervolgens de gegenereerde WSDL te wijzigen. In dit voorbeeld CustomTextMessageBindingElement wordt de WSDL-exportlogica van de TextMessageEncodingBindingElement.

Voor dit voorbeeld is de clientconfiguratie handmatig geconfigureerd. U kunt Svcutil.exe niet gebruiken om de clientconfiguratie te genereren omdat er CustomTextMessageBindingElement geen beleidsverklaring wordt geëxporteerd om het gedrag ervan te beschrijven. Over het algemeen moet u de IPolicyExportExtension interface implementeren op een aangepast bindingselement om een aangepaste beleidsverklaring te exporteren die het gedrag of de mogelijkheid beschrijft die door het bindingselement is geïmplementeerd. Zie het voorbeeld Transport: UDP voor een voorbeeld van het exporteren van een beleidsverklaring voor een aangepast bindingselement.

Message Encoding Binding Configuration Handler

In de vorige sectie ziet u hoe u de aangepaste coderingsprogramma voor tekstberichten programmatisch gebruikt. Hiermee CustomTextMessageEncodingBindingSection wordt een configuratie-handler geïmplementeerd waarmee u het gebruik van een aangepaste tekstberichtcoderingsprogramma in een configuratiebestand kunt opgeven. De CustomTextMessageEncodingBindingSection klasse is afgeleid van de BindingElementExtensionElement klasse. De BindingElementType eigenschap informeert het configuratiesysteem van het type bindingselement dat voor deze sectie moet worden gemaakt.

Alle instellingen die door CustomTextMessageBindingElement zijn gedefinieerd, worden weergegeven als de eigenschappen in de CustomTextMessageEncodingBindingSection. De ConfigurationPropertyAttribute functie helpt bij het toewijzen van de kenmerken van het configuratie-element aan de eigenschappen en het instellen van standaardwaarden als het kenmerk niet is ingesteld. Nadat de waarden uit de configuratie zijn geladen en toegepast op de eigenschappen van het type, wordt de CreateBindingElement methode aangeroepen, waarmee de eigenschappen worden geconverteerd naar een concreet exemplaar van een bindingselement.

Deze configuratiehandler wordt toegewezen aan de volgende weergave in de App.config of Web.config voor de service of client.

<customTextMessageEncoding encoding="utf-8" contentType="text/xml" messageVersion="Soap11Addressing1" />

In het voorbeeld wordt de ISO-8859-1-codering gebruikt.

Als u deze configuratie-handler wilt gebruiken, moet deze worden geregistreerd met behulp van het volgende configuratie-element.

<extensions>
    <bindingElementExtensions>
        <add name="customTextMessageEncoding" type="
Microsoft.ServiceModel.Samples.CustomTextMessageEncodingBindingSection,
                  CustomTextMessageEncoder" />
    </bindingElementExtensions>
</extensions>