程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> WCF分布式開發常見錯誤(30)

WCF分布式開發常見錯誤(30)

編輯:關於.NET

WCF分布式開發常見錯誤(30):Start element 'Binary' expected(期望的初始元素是'Binary' )

WCF分布式開發常見錯誤(30):Start element 'Binary' expected(期望的初 始元素是'Binary' ). Found 'SayHello'.

調試WCF4.0代碼遇到的錯誤,目前網絡上參考的資料很少,我把這個異常的 信息給收集起來,包括解決辦法,整理為一篇文章,供大家參考。這個問題目前 沒什麼參考資料。使用Google也搜索不到相關的英文幫資料。分享出來,應該對 大家有點參考價值。

【1】錯誤描述:

這個問題是在調試今天我在調試WCF自定義綁定實現字節流編碼 ByteStreamMessageEncoding程序例子代碼的時候遇到這個錯誤。客戶端拋出的 異常是:Start element 'Binary' expected(期望的初始元素是'Binary' ). Found 'SayHello'.

綁定的定義如下:

//創建自定義綁定
ByteStreamMessageEncodingBindingElement byteStream = new ByteStreamMessageEncodingBindingElement();
//TcpTransportBindingElement transport = new TcpTransportBindingElement();
HttpTransportBindingElement transport = new HttpTransportBindingElement();
transport.AuthenticationScheme = System.Net.AuthenticationSchemes.Anonymous;
transport.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
CustomBinding binding = new CustomBinding(byteStream, transport);

操作的定義如下:

//2.服務類,繼承接口。實現服務契約定義的操

作

    public class WCFService : IWCFService

    {

        //實現接口定義的方法

        public void SayHello(byte[] b)

        {

            Console.WriteLine("Hello! {0},Calling at {1} 

...", b,DateTime.Now.ToLongTimeString());

            //return b;

        }

    }

【2】錯誤截圖:

運行程序,客戶端調用服務操作,拋出的異常截圖如下:

【3】問題分析:

這個問題應該是由於消息的根節點元素不正確導致的。這裡的SOAP消息的 Body默認根節點應該是<SayHello>。

SOAP消息不符合Schema導致的。WCF裡提供了能夠控制消息序列化的機制就 是使用Message類型來控制序列化。

【4】解決辦法:

首先我們要重新定義一下操作,這裡服務契約不能定義為普通的契約,而要 使用消息契約來代替數據契約。

聲明如下:

//1.服務契約

    [ServiceContract]

    public interface IWCFService

    {

        //操作契約

        [OperationContract(Action = "*", ReplyAction = 

"*")]

        Message UpLoad(Message request);

    }

其次控制Message對象,這是客戶端的請求消息Body,第一個根節點必須為 Binary節點。

這裡比較復雜的一點是要了解WCF的消息序列化機制。在《WCF技術內幕》有 過介紹。我們在實例化Message對象的時候,要提供一個BodyWriter的之類對象 ,它可以負責Message對象的消息體部分的處理工作。我們可以控制節點的添加 。

BodyWriter為抽象類,我們要定義一個類型繼承實現它的抽象方法。定義如 下:

class ByteStreamBodyWriter : BodyWriter

    {

        string testFileName;

        public ByteStreamBodyWriter(string testFileName)

            : base(false)

        {

            this.testFileName = testFileName;

        }

        protected override void OnWriteBodyContents

(XmlDictionaryWriter writer)

        {

            writer.WriteStartElement("Binary");

            //寫數據

            writer.WriteEndElement();

            fs.Close();

        }

    }

OnWriteBodyContents(XmlDictionaryWriter writer)方法裡提供了一個消息 體元素"Binary"的定義,我們把數據放到這個節點下面,就可以解決 問題。這個時候請求消息裡就會包含需要的節點。在此啟動程序基本正常。

【5】總結:

(1)這裡比較值得注意的問題是,根據提示我曾經嘗試把方法名字修改為 "Binary"。

這個做法基於的出發點就是WCF會把方法名默認作為消息的根節點名。但是後 來嘗試失敗。應該是SOAP消息裡包含了新的後綴,我很難控制消息體的根節點元 素名稱。

(2)另外就是ByteStreamMessageEncodingBindingElement的使用只能是基 於自定義綁定,而且對方要求把數據放到消息裡的"Binary"節點裡:

<Binary>字節流數據</Binary>

這裡唯一的辦法就是使用 Message契約來實現,WCF提供的可以控制消息體的方法也就是通過控制SOAP消息 的序列化過程。這裡我們使用的一個重要類型BodyWriter。它是一個抽象類,是 許多消息體處理類型的基類型。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved