共用方式為


自訂訊息編碼器:自定義文字編碼器

文字範例示範如何使用 Windows Communication Foundation (WCF) 實作自定義文字訊息編碼器。

WCF 的 TextMessageEncodingBindingElement 僅支援 UTF-8、UTF-16 和大端字節序的 Unicode 編碼。 此範例中的自定義文字訊息編碼器支援所有可能需要互作性的平台支援的字元編碼。 此範例包含用戶端控制台程式(.exe)、由 Internet Information Services (IIS) 裝載的服務連結庫(.dll),以及文字消息編碼器連結庫(.dll)。 服務會實作定義要求-回復通訊模式的合約。 合約是由 ICalculator 介面所定義,其會公開數學運算(Add、Subtract、Multiply 和 Divide)。 用戶端會向指定的數學運算提出同步要求,而服務會以結果回復。 用戶端和服務都會使用 CustomTextMessageEncoder ,而不是預設 TextMessageEncodingBindingElement

自定義編碼器實作包含訊息編碼器處理站、訊息編碼器、訊息編碼綁定項和組態處理程式,並示範下列專案:

  • 建置自定義編碼器和編碼器處理站。

  • 建立自訂編碼器的綁定項。

  • 使用自定義系結組態來整合自定義綁定項。

  • 開發自定義組態處理程式,以允許自定義綁定項的檔案組態。

要設定、建置和執行範例,請執行以下步驟:

  1. 請使用下列命令安裝 ASP.NET 4.0。

    %windir%\Microsoft.NET\Framework\v4.0.XXXXX\aspnet_regiis.exe /i /enable
    
  2. 請確定您已針對 Windows Communication Foundation 範例 執行One-Time 安裝程式。

  3. 若要建置解決方案,請遵循 建置 Windows Communication Foundation 範例中的指示。

  4. 若要在單一或跨計算機組態中執行範例,請遵循執行 Windows Communication Foundation 範例 中的指示。

訊息編碼器處理站和訊息編碼器

ServiceHost或客戶端通道開啟時,設計時間元件CustomTextMessageBindingElement會建立CustomTextMessageEncoderFactory。 工廠製造CustomTextMessageEncoder。 訊息編碼器會在串流模式和緩衝模式中運作。 它會分別使用 XmlReaderXmlWriter 來讀取和寫入訊息。 與僅支援UTF-8、UTF-16和 big-endian Unicode 的 WCF 優化 XML 讀取器和寫入器相反,這些讀取器和寫入器支援所有平臺支援的編碼。

下列程式代碼範例顯示 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 透過屬性公開 MessageVersionContentTypeEncoding 的設定。 編碼器同時支援Soap11Addressing和Soap12Addressing1版本。 預設值為 Soap11Addressing1。 的預設值 ContentType 為 「text/xml」。。 屬性 Encoding 可讓您設定所需字元編碼的值。 範例客戶端和服務使用 ISO-8859-1(Latin1)字元編碼,而這個編碼不受 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 的任何類型都會負責更新針對服務產生的 WSDL 檔中 SOAP 系結的版本。 在介面ExportEndpoint上實施IWsdlExportExtension方法,然後修改生成的WSDL。 在此範例中,CustomTextMessageBindingElement 使用了來自 TextMessageEncodingBindingElement 的 WSDL 導出邏輯。

在此範例中,會手動設定客戶端設定。 您無法使用 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>