Dela via


Anpassad meddelandekodare: Anpassad textkodare

Textexemplet visar hur du implementerar en anpassad textmeddelandekodare med hjälp av Windows Communication Foundation (WCF).

TextMessageEncodingBindingElement WCF stöder endast UTF-8-, UTF-16- och big-endian Unicode-kodningar. Den anpassade textmeddelandekodaren i det här exemplet stöder alla teckenkodningar som stöds av plattformen och som kan krävas för samverkan. Exemplet består av ett klientkonsolprogram (.exe), ett tjänstbibliotek (.dll) som hanteras av Internet Information Services (IIS) och ett textmeddelandekodarbibliotek (.dll). Tjänsten implementerar ett kontrakt som definierar ett kommunikationsmönster för begäran-svar. Kontraktet definieras av ICalculator gränssnittet, som exponerar matematiska åtgärder (Lägg till, Subtrahera, Multiplicera och Dividera). Klienten gör synkrona begäranden till en viss matematisk åtgärd och tjänsten svarar med resultatet. Både klienten och tjänsten använder CustomTextMessageEncoder i stället för standardvärdet TextMessageEncodingBindingElement.

Implementeringen av den anpassade kodaren består av en meddelandekodarfabrik, en meddelandekodare, ett bindningselement för meddelandekodning och en konfigurationshanterare, och visar följande:

  • Skapa en anpassad kodare och kodarfabrik.

  • Skapa ett bindningselement för en anpassad kodare.

  • Använda den anpassade bindningskonfigurationen för att integrera anpassade bindningselement.

  • Utveckla en anpassad konfigurationshanterare för att tillåta filkonfiguration av ett anpassat bindningselement.

Så här konfigurerar du, skapar och kör exemplet

  1. Installera ASP.NET 4.0 med hjälp av följande kommando.

    %windir%\Microsoft.NET\Framework\v4.0.XXXXX\aspnet_regiis.exe /i /enable
    
  2. Kontrollera att du har utfört engångsinstallationsproceduren för Windows Communication Foundation-exempel.

  3. Skapa lösningen genom att följa anvisningarna i Skapa Windows Communication Foundation-exempel.

  4. Om du vill köra exemplet i en konfiguration med en eller flera datorer följer du anvisningarna i Köra Windows Communication Foundation-exempel.

Message Encoder Factory och Meddelandekodaren

ServiceHost När klientkanalen eller öppnas skapar designtidskomponenten CustomTextMessageBindingElementCustomTextMessageEncoderFactory. Fabriken skapar CustomTextMessageEncoder. Meddelandekodaren fungerar både i strömningsläge och i buffrat läge. Den använder XmlReader och XmlWriter för att läsa respektive skriva meddelandena. I motsats till de optimerade XML-läsare och författare av WCF som endast stöder UTF-8, UTF-16 och big-endian Unicode, stöder dessa läsare och författare all plattformsstödd kodning.

I följande kodexempel visas 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();
    }
}

Följande kodexempel visar hur du skapar meddelandekodarfabriken.

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

Bindningselement för meddelandekodning

Bindningselementen tillåter konfigurationen av WCF-körningsstacken. Om du vill använda den anpassade meddelandekodaren i ett WCF-program krävs ett bindningselement som skapar meddelandekodarfabriken med lämpliga inställningar på lämplig nivå i körningsstacken.

CustomTextMessageBindingElement Härleds från basklassen BindingElement och ärver från MessageEncodingBindingElement klassen. På så sätt kan andra WCF-komponenter identifiera det här bindningselementet som ett meddelandekodningsbindningselement. Implementeringen av CreateMessageEncoderFactory returnerar en instans av den matchande meddelandekodarfabriken med lämpliga inställningar.

Visar CustomTextMessageBindingElement inställningarna för MessageVersion, ContentTypeoch Encoding via egenskaper. Kodaren stöder både Soap11Addressing- och Soap12Addressing1-versioner. Standardvärdet är Soap11Addressing1. Standardvärdet för ContentType är "text/xml". Med Encoding egenskapen kan du ange värdet för den önskade teckenkodningen. Exempelklienten och -tjänsten använder kodningen ISO-8859-1 (Latin1), som inte stöds av TextMessageEncodingBindingElement WCF.

Följande kod visar hur du programmatiskt skapar bindningen med hjälp av den anpassade textmeddelandekodaren.

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

Lägga till metadatastöd till bindningselementet för meddelandekodning

Alla typer som härleds från MessageEncodingBindingElement ansvarar för att uppdatera versionen av SOAP-bindningen i det WSDL-dokument som genereras för tjänsten. Detta görs genom att implementera ExportEndpoint metoden i IWsdlExportExtension gränssnittet och sedan ändra den genererade WSDL:n. I det här exemplet CustomTextMessageBindingElement använder WSDL-exportlogik från TextMessageEncodingBindingElement.

För det här exemplet är klientkonfigurationen hand konfigurerad. Du kan inte använda Svcutil.exe för att generera klientkonfigurationen eftersom CustomTextMessageBindingElement den inte exporterar en principkontroll för att beskriva dess beteende. Du bör vanligtvis implementera IPolicyExportExtension gränssnittet på ett anpassat bindningselement för att exportera en anpassad principkontroll som beskriver beteendet eller funktionen som implementeras av bindningselementet. Ett exempel på hur du exporterar en principkontroll för ett anpassat bindningselement finns i exemplet Transport: UDP .

Meddelandekodningskonfigurationshanterare för bindning

I föregående avsnitt visas hur du använder den anpassade textmeddelandekodaren programmatiskt. Implementerar CustomTextMessageEncodingBindingSection en konfigurationshanterare som gör att du kan ange användningen av en anpassad textmeddelandekodare i en konfigurationsfil. Klassen CustomTextMessageEncodingBindingSection härleds från BindingElementExtensionElement klassen. Egenskapen BindingElementType informerar konfigurationssystemet om vilken typ av bindningselement som ska skapas för det här avsnittet.

Alla inställningar som definieras av CustomTextMessageBindingElement exponeras som egenskaperna i CustomTextMessageEncodingBindingSection. Hjälper ConfigurationPropertyAttribute till med att mappa konfigurationselementattributen till egenskaperna och ange standardvärden om attributet inte har angetts. När värdena från konfigurationen har lästs in och tillämpats på egenskaperna för typen CreateBindingElement anropas metoden, som konverterar egenskaperna till en konkret instans av ett bindningselement.

Den här konfigurationshanteraren mappar till följande representation i App.config eller Web.config för tjänsten eller klienten.

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

Exemplet använder ISO-8859-1-kodningen.

Om du vill använda den här konfigurationshanteraren måste den registreras med hjälp av följande konfigurationselement.

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