zoukankan      html  css  js  c++  java
  • 消息(7)——WCF编程模型中控制消息(1)绑定,契约

    WCF服务要通过终结点来进行通信,终结点三大构成元素:ABC,其中的Bbinding是重中之重,它解决了在消息交换过程中的编码,传输协议,安全等问题。

    绑定是分层的,一个绑定对象对应一组有序的绑定元素的集合。每层的元素专门处理其中某领域内的事务,来负责终结点通信中的其中一方面。这里给出绑定对象的绑定元素的层表:

    选项

    是否必需

    事务流

    TransactionFlowBindingElement

    可靠性

    ReliableSessionBindingElement

    安全性

    对称、非对称、传输级

    形状更改

    CompositeDuplexBindingElement

    传输升级

    SSL 流、Windows 流、对等解析程序

    编码

    文本、二进制、MTOM、自定义

    传输

    TCP、命名管道、HTTPHTTPSMSMQ、自定义

     

    其中的编码层和传输层是必须的。系统提供了足够多的绑定类型:

    绑定

    互操作性

    安全模式(默认)

    会话(默认)

    事务

    双工

    BasicHttpBinding

    Basic Profile 1.1

    ()、传输、消息、混合

    无、()

    ()

    n/a

    WSHttpBinding

    WS

    无、传输、(消息)、混合

    ()、传输、可靠会话

    ()、是

    n/a

    WS2007HttpBinding

    WS-SecurityWS-TrustWS-SecureConversationWS-SecurityPolicy

    无、传输、(消息)、混合

    ()、传输、可靠会话

    ()、是

    n/a

    WSDualHttpBinding

    WS

    无、(消息)

    (可靠会话)

    ()、是

    WSFederationHttpBinding

    WS-Federation

    无、(消息)、混合

    ()、可靠会话

    ()、是

    WS2007FederationHttpBinding

    WS-Federation

    无、(消息)、混合

    ()、可靠会话

    ()、是

    NetTcpBinding

    .NET

    无、(传输)、消息、混合

    可靠对话、(传输)

    ()、是

    NetNamedPipeBinding

    .NET

    无、(传输)

    无、(传输)

    ()、是

    NetMsmqBinding

    .NET

    无、消息、(传输)、两者

    ()

    ()、是

    NetPeerTcpBinding

    对等

    无、消息、(传输)、混合

    ()

    ()

    MsmqIntegrationBinding

    MSMQ

    无、(传输)

    ()

    ()、是

    n/a

     

    从这个表中可知:BasicHttpBinding类型只有两层绑定元素。

    验证一下:

    public void TestBindingElements()

    {

        BasicHttpBinding _binding = new BasicHttpBinding();

     

    BindingElementCollection eles=

    _binding.CreateBindingElements();

        foreach (BindingElement ele in eles)

    Console.WriteLine(ele.ToString());

    }

     

    结果:

    System.ServiceModel.Channels.TextMessageEncodingBindingElement

    System.ServiceModel.Channels.HttpTransportBindingElement

     

    因为每种绑定类型的绑定元素构成的不同,在应用中会有很大不同。例如基础绑定类型:它不支持双工通信,不支持事务和会话服务。

     

    (一)  通过绑定对象的属性进行消息的控制

    绑定对象有多个属性用于控制消息。例如基础绑定:

    ·EnvelopeVersio:获取此绑定处理的消息将要使用的 SOAP 版本。

    ·MessageEncoding:获取或设置是使用 MTOM 还是文本对 SOAP 消息进行编码。

    ·MessageVersion:获取由绑定所配置的客户端和服务使用的消息版本。

    ·Name:获取或设置绑定的名称。

    ·Namespace:获取或设置绑定的 XML 命名空间。

    ·Security:获取与此绑定一起使用的安全类型。

    ·TextEncoding:获取或设置用于消息文本的字符编码。

     

    设置绑定的名字:Name。设置可以在配置文件中配置也可以在自托管宿主程序中通过程序设置。

    (二)  契约

    契约提供消息的标准,交换的消息的规则。在WCF中,契约分4类:

    ·服务契约

    ·数据契约

    ·异常契约

    ·消息契约

     

    1)服务契约

    服务契约分2种,

    一种是用在接口或类上的服务契约,

    [ServiceContract(Namespace="www.self001.com")]

    public interface IFirstService

    例如:CallbackContract用于在支持双工交换的绑定里设置回调类型

    SessionMode,用于设置或取得会话的状态

    Name用于设置或取得wsdl上的<portType>元素的名称

     

    另一种是用在方法上的操作契约:

    [OperationContract(Action="selfAction")]

    void DoWork(string strContent);

    例如:设置

    IsOneWay,用于设置或取得是否进行单向消息交换

    Name,用于设置或取得操作的名称

     

    通过对它们的属性修饰达到对服务的约束和设置。

    BasicHttpBinding中,默认的消息交换模式为RR。现在为DoWork添加单向交换标志:

    [OperationContract(IsOneWay=true)]

    void DoWork(string strContent);

    那么在请求服务时,只有去的消息,而不返回消息。

    2)数据契约

    主要用于数据的序列化。对于基元类型,wcf自动序列化并默认拥有数据契约。对复杂类型要进行序列化。(在WCF对复杂类型不用显示添加数据契约,但如果添加了,那么所有的数据契约都要添加)

    数据的序列化为了传输和存储,可见:

    http://www.cnblogs.com/jams742003/archive/2010/03/31/1701184.html

     

    [DataContract]

    public class Customer

    {

        [DataMember]

        public int Unid { get; set; }

        [DataMember]

        public string UserName { get; set; }

        [DataMember]

        public DateTime CreateTime { get; set; }

    }

     

    同样的,数据契约也用于不同的地方:

    [DataContract]

    public class Customer

     

    通过属性的设置来设置数据契约的细节,例如Namespace

    在没设置之前:

    <s:Body>

      <GetCustomerResponse xmlns="www.self001.com">

        <GetCustomerResult

          xmlns:a="http://schemas.datacontract.org/2004/07/"

          xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

          <a:CreateTime>2010-04-01T00:00:00</a:CreateTime>

          <a:Unid>2</a:Unid>

          <a:UserName>Songjiang</a:UserName>

        </GetCustomerResult>

      </GetCustomerResponse>

    </s:Body>

    设置:

    [DataContract(Namespace="selfdata.com")]

    public class Customer

    之后的情况是:

    <s:Body>

      <GetCustomerResponse xmlns="www.self001.com">

        <GetCustomerResult

          xmlns:a="selfdata.com"

          xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

          <a:CreateTime>2010-04-01T00:00:00</a:CreateTime>

          <a:Unid>2</a:Unid>

          <a:UserName>Songjiang</a:UserName>

        </GetCustomerResult>

      </GetCustomerResponse>

    </s:Body>

    可以看到其中的变化。

     

    [DataMember]

    public int Unid { get; set; }

    通过添加DataMember标签,指定这个成员作为数据契约的一部分,且可以被序列化。它的属性例如:

    Order:获取或设置成员的序列化和反序列化顺序

    Name:获取或设置数据成员的名称

    [DataMember(Name="SelfId")]

    public int Unid { get; set; }

     

    <s:Body>

      <GetCustomerResponse xmlns="www.self001.com">

        <GetCustomerResult

          xmlns:a="selfdata.com"

          xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

          <a:CreateTime>2010-04-01T00:00:00</a:CreateTime>

          <a:SelfId>2</a:SelfId>

          <a:UserName>Songjiang</a:UserName>

        </GetCustomerResult>

      </GetCustomerResponse>

    </s:Body>

    3)异常契约

    异常契约用于soap消息的异常。

    [OperationContract]

    [FaultContract(typeof(string))]

    void SelfException();

     

    public void SelfException()

    {

    throw new FaultException<string>

    ("error 007!","reason:Testing!");

    }

     

    客户端:

    public void TestFault()

    {

    FirstInstance.FirstServiceClient client =

    new FirstInstance.FirstServiceClient();

        try

        {

    client.SelfException();

        }

        catch (FaultException<string> ex)

        {

    Console.WriteLine(ex.Reason+" "+

    ex.Detail.ToString());

        }

    }

     

    打印信息:reason:Testing! error 007!

    包信息:

    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">

      <s:Body>

        <s:Fault>

          <faultcode>s:Client</faultcode>

          <faultstring xml:lang="zh-CN">

            reason:Testing!

          </faultstring>

          <detail>

            <string

              xmlns="http://schemas.microsoft.com/2003/10/Serialization/">

              error 007!

            </string>

          </detail>

        </s:Fault>

      </s:Body>

    </s:Envelope>

     

    4)消息契约

    通过消息契约可以设置消息包体的多个选项,用于对包体中的类型进行强制设置。

    [MessageContract(WrapperName="SelfCustomer")]

    public class Customer

    {

        [MessageBodyMember]

        public int Unid { get; set; }

        [MessageBodyMember]

        public string UserName { get; set; }

        [MessageBodyMember]

        public DateTime CreateTime { get; set; }

    }

     

    客户端的用法就不同了:

    public void TestCustomer()

    {

    FirstInstance.Customer customer =

    new FirstInstance.Customer();

    FirstInstance.FirstServiceClient client =

    new FirstInstance.FirstServiceClient();

      

        int iUnid;

        string strUserName;

        client.GetCustomer(out iUnid,out strUserName);

    }

     

    看包:

    <s:Body>

      <SelfCustomer xmlns="www.self001.com">

        <CreateTime>2010-04-01T00:00:00</CreateTime>

        <Unid>2</Unid>

        <UserName>Songjiang</UserName>

      </SelfCustomer>

    </s:Body>

     

     

  • 相关阅读:
    SQL2005四个排名函数(row_number、rank、dense_rank和ntile)的比较
    浅谈数据库索引
    移动网络应用开发中,使用 HTTP 协议比起使用 socket 实现基于 TCP 的自定义协议有哪些优势?
    http协议学习系列
    隐藏帧技术
    第2章:标准输入与输出
    第1章:认识Shell脚本
    Cisco配置单臂路由及静态路由
    Cisco交换机端口聚合(EtherChannel)
    Cisco配置VLAN+DHCP中继代理+NAT转发上网
  • 原文地址:https://www.cnblogs.com/jams742003/p/1702476.html
Copyright © 2011-2022 走看看