Condividi tramite


Codificatore di messaggi personalizzato: codificatore di testi personalizzato

L'esempio Testo mostra come implementare un codificatore di SMS personalizzato usando Windows Communication Foundation (WCF).

TextMessageEncodingBindingElement di WCF supporta solo le codifiche Unicode UTF-8, UTF-16 e big-endian. Il codificatore di messaggi di testi personalizzato in questo esempio supporta le codifiche dei caratteri supportata dalla piattaforma che può essere necessaria per l'interoperabilità. L'esempio è costituito da un programma di console client (.exe) e da una libreria di servizi (.dll) ospitati su Internet Information Services (IIS) e da una libreria del codificatore di SMS (.dll). Il servizio implementa un contratto che definisce un modello di comunicazione richiesta/risposta. Il contratto è definito dall'interfaccia ICalculator, che espone operazioni matematiche (somma, sottrazione, moltiplicazione e divisione). Il client esegue richieste sincrone a un'operazione matematica specificata e il servizio risponde fornendo il risultato. Il client e il servizio utilizzano CustomTextMessageEncoder anziché la classe TextMessageEncodingBindingElement predefinita.

L'implementazione del codificatore personalizzato è costituita da una factory del codificatore di messaggi, un codificatore di messaggi, un messaggio che codifica l'elemento di associazione e un gestore di configurazione, e illustra quanto segue:

  • Compilazione di un codificatore personalizzato e di una factory del codificatore.

  • Creazione di un elemento di associazione per un codificatore personalizzato.

  • Utilizzo della configurazione dell'associazione personalizzata per l'integrazione di elementi di associazione personalizzati.

  • Sviluppo di un gestore di configurazione personalizzato per consentire la configurazione del file di un elemento di associazione personalizzato.

Per impostare, compilare ed eseguire l'esempio

  1. Installare ASP.NET 4.0 usando il comando seguente.

    %windir%\Microsoft.NET\Framework\v4.0.XXXXX\aspnet_regiis.exe /i /enable
    
  2. Assicurarsi di aver eseguito la Procedura di installazione singola per gli esempi di Windows Communication Foundation.

  3. Per compilare la soluzione, seguire le istruzioni in Compilazione degli esempi di Windows Communication Foundation.

  4. Per eseguire l'esempio in un solo computer o tra computer diversi, seguire le istruzioni in Esecuzione degli esempi di Windows Communication Foundation.

Factory di codificatori di messaggi e codificatori dei messaggi.

Quando la classe ServiceHost o il canale client vengono aperti, il componente della fase di progettazione CustomTextMessageBindingElement crea CustomTextMessageEncoderFactory. La factory crea CustomTextMessageEncoder. Il codificatore di messaggi aziona entrambi in modalità di trasmissione e in modalità di memorizzazione nel buffer. Utilizza le classi XmlReader e XmlWriter per leggere e scrivere i messaggi, rispettivamente. Contrariamente ai reader e writer XML ottimizzati di WCF che supportano solo UTF-8, UTF-16 e Big-endian Unicode, questi supportano tutta la codifica supportata dalla piattaforma.

Nel codice seguente viene illustrato il codificatore di messaggio personalizzato.

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

Nell'esempio di codice seguente viene illustrato come compilare la factory del codificatore di messaggi.

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

Elemento di associazione di codifica dei messaggi

Gli elementi di binding consentono la configurazione dello stack di runtime WCF. Per usare il codificatore di messaggi personalizzato in un'applicazione WCF, è necessario un elemento di binding che crea la factory del codificatore messaggi con le impostazioni appropriate, al livello appropriato, nello stack di runtime.

La classe CustomTextMessageBindingElement deriva dalla classe base BindingElement ed eredita dalla classe MessageEncodingBindingElement. Ciò consente ad altri componenti WCF di riconoscere questo elemento di binding come elemento di binding di codifica dei messaggi. L'implementazione del metodo CreateMessageEncoderFactory restituisce un'istanza della factory del codificatore di messaggi corrispondente con le impostazioni appropriate.

CustomTextMessageBindingElement espone impostazioni per MessageVersion, ContentType e Encoding tramite proprietà. Il codificatore supporta le versioni Soap11Addressing e Soap12Addressing1. L'impostazione predefinita è Soap11Addressing1. Il valore predefinito della proprietà ContentType è "text/xml". La proprietà Encoding consente di impostare il valore della codifica dei caratteri desiderata. Il client e il servizio di esempio usano la codifica dei caratteri ISO-8859-1 (Latin1), che non è supportata da TextMessageEncodingBindingElement di WCF.

Nel codice seguente viene illustrato come creare l'associazione a livello di codice utilizzando il codificatore del messaggio di testo personalizzato.

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

Aggiunta del supporto dei metadati per un elemento di associazione di codifica dei messaggi

Qualsiasi tipo che deriva da MessageEncodingBindingElement deve eseguire l'aggiornamento della versione dell'associazione SOAP nel documento WSDL generato per il servizio. Ciò viene fatto implementando il metodo ExportEndpoint sull'interfaccia IWsdlExportExtension e modificando quindi il WSDL generato. In questo esempio, CustomTextMessageBindingElement utilizza la logica di esportazione WSDL di TextMessageEncodingBindingElement.

Per questo esempio, la configurazione del client è manuale. Non è possibile utilizzare Svcutil.exe per generare la configurazione del client perché CustomTextMessageBindingElement non esporta un'asserzione di criteri per descrivere il comportamento. Generalmente si deve implementare l'interfaccia IPolicyExportExtension su un elemento di associazione personalizzato per esportare un'asserzione di criteri personalizzata che descrive il comportamento o la funzionalità implementata dall'elemento di associazione. Per un esempio di come esportare un'asserzione di criteri per un elemento di binding personalizzato, vedere l'esempio Trasporto: UDP.

Gestore di configurazione dell'associazione di codifica dei messaggi

La sezione precedente mostra come utilizzare il codificatore dei messaggi di testo personalizzato a livello di codice. CustomTextMessageEncodingBindingSection implementa un gestore di configurazione che consente di specificare l'utilizzo di un codificatore dei messaggi di testo personalizzato all'interno di un file di configurazione. La classe CustomTextMessageEncodingBindingSection deriva dalla classe BindingElementExtensionElement . La proprietà BindingElementType informa il sistema di configurazione del tipo di elemento di associazione da creare per questa sezione.

Tutte le impostazioni definite da CustomTextMessageBindingElement sono esposte come proprietà in CustomTextMessageEncodingBindingSection. La classe ConfigurationPropertyAttribute assiste nell'eseguire il mapping degli attributi dell'elemento di configurazione alle proprietà e nell'impostazione dei valori predefiniti se l'attributo non è impostato. Dopo i valori della configurazione sono caricati e applicati alle proprietà del tipo, e viene chiamato il metodo CreateBindingElement. Esso converte le proprietà in un'istanza concreta di un elemento di associazione.

Questo gestore di configurazione esegue il mapping alla rappresentazione seguente in App.config o Web.config per il servizio o il client.

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

Nell'esempio viene utilizzata la codifica ISO-8859-1.

Per utilizzare questo gestore di configurazione deve essere registrato utilizzando l'elemento di configurazione seguente.

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