WCF分布式开发常见错误(30):Start element 'Binary' expected(期望的初始元素是'Binary' )

Posted on 2010-03-28 18:23 Frank Xu Lei 阅读(727) 评论(4)   编辑 收藏 所属分类: SOA and EAI, WCF分布式开发常见错误

       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.BodyWriter Class

2.《WCF技术内幕》绑定


老徐的博客
【作      者】:Frank Xu Lei
【地      址】:http://www.cnblogs.com/frank_xl/
【中文论坛】:微软WCF中文技术论坛
【英文论坛】:微软WCF英文技术论坛

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值