zoukankan      html  css  js  c++  java
  • 2. WCF 消息操作

    原文:http://www.rainsts.net/article.asp?id=429

    WCF 一切都围绕Message进行的,下面我们来看看Message的样子。

    服务端:

    <ServiceContract()> _
    Public Interface IService1

        
    <OperationContract()> _
        
    Function GetData(ByVal value As IntegerAs String
    End Interface

    Public Class Service1
        
    Implements IService1

        
    Public Function GetData(ByVal value As IntegerAs String Implements IService1.GetData

            
    '打印消息
            Dim msg = OperationContext.Current.RequestContext.RequestMessage
            Console.WriteLine(msg.ToString)

            
    Return String.Format("You entered: {0}", value)
        
    End Function


    End Class
    客户端:
       Dim host As System.ServiceModel.ServiceHost
            host 
    = New System.ServiceModel.ServiceHost(GetType(WcfServiceLibrary1.Service1))
            host.AddServiceEndpoint(
    GetType(WcfServiceLibrary1.IService1), New System.ServiceModel.BasicHttpBinding, "http://localhost:8731/Design_Time_Addresses/WcfServiceLibrary1/Service1/mex")
            host.Open()
            Console.WriteLine(host.State.ToString)

            
    Dim factory = New System.ServiceModel.ChannelFactory(Of WcfServiceLibrary1.IService1)(New ServiceModel.BasicHttpBinding, "http://localhost:8731/Design_Time_Addresses/WcfServiceLibrary1/Service1/mex")
            
    Dim o = factory.CreateChannel

            Console.WriteLine(o.GetData(
    10))



            Console.ReadKey()
    输出消息是:
    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
      
    <s:Header>
        
    <To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://localhost:8731/Design_Time_Addresses/WcfServiceLibrary1/Service1/mex</To>
        
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IService1/GetData</Action>
      
    </s:Header>
      
    <s:Body>
        
    <GetData xmlns="http://tempuri.org/">
          
    <value>10</value>
        
    </GetData>
      
    </s:Body>
    </s:Envelope>
    事实上我们可以直接基于Message layer 进行编程,利用operation.action捕获特定的action消息,注意action的定义是区分大小写的
    服务端:
    <ServiceContract()> _
    Public Interface IService1

        
    <OperationContract(action:="add", ReplyAction:="add")> _
        
    Function GetData(ByVal msg As System.ServiceModel.Channels.Message) As System.ServiceModel.Channels.Message
    End Interface

    Public Class Service1
        
    Implements IService1

        
    Public Function GetData(ByVal msg As System.ServiceModel.Channels.Message) As System.ServiceModel.Channels.Message Implements IService1.GetData

            
    Dim data = msg.GetBody(Of CompositeType)()

            Console.WriteLine(data.StringValue)


            
    Return System.ServiceModel.Channels.Message.CreateMessage(System.ServiceModel.Channels.MessageVersion.Soap11, "add"New CompositeType("zqonline"))
        
    End Function


    End Class



    <DataContract()> _
    Public Class CompositeType

        
    Private stringValueField As String = String.Empty

        
    Public Sub New()

        
    End Sub

        
    Public Sub New(ByVal str As String)
            
    Me.StringValue = str
        
    End Sub


        
    <DataMember()> _
        
    Public Property StringValue() As String
            
    Get
                
    Return Me.stringValueField
            
    End Get
            
    Set(ByVal value As String)
                
    Me.stringValueField = value
            
    End Set
        
    End Property

    End Class
    客户端:

        
    Sub Main()
            
    Dim host As System.ServiceModel.ServiceHost
            host 
    = New System.ServiceModel.ServiceHost(GetType(WcfServiceLibrary1.Service1))
            host.AddServiceEndpoint(
    GetType(WcfServiceLibrary1.IService1), New System.ServiceModel.BasicHttpBinding, "http://localhost:8731/Design_Time_Addresses/WcfServiceLibrary1/Service1/mex")
            host.Open()
            Console.WriteLine(host.State.ToString)

            
    Dim factory = New System.ServiceModel.ChannelFactory(Of System.ServiceModel.Channels.IRequestChannel)(New ServiceModel.BasicHttpBinding, "http://localhost:8731/Design_Time_Addresses/WcfServiceLibrary1/Service1/mex")
            
    Dim o = factory.CreateChannel

            
    Dim value = New WcfServiceLibrary1.CompositeType("lily")
            
    Dim msg = System.ServiceModel.Channels.Message.CreateMessage(System.ServiceModel.Channels.MessageVersion.Soap11, "add", value)

            
    Dim r As System.ServiceModel.Channels.Message = o.Request(msg)
            Console.WriteLine(r)
            Debug.WriteLine(r)

            Console.ReadKey()
        
    End Sub
    输出内容是:
    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
      
    <s:Header />
      
    <s:Body>
        
    <CompositeType xmlns="http://schemas.datacontract.org/2004/07/WcfServiceLibrary1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
          
    <StringValue>zqonline</StringValue>
        
    </CompositeType>
      
    </s:Body>
    </s:Envelope>

    正如上面所看到的,所有的调用都被转换成消息后发送。这也符合 SOA 的规范,完全隔离,清晰的边界。(调用 "m.GetBody<Data>()" 后,会导致 Message.State 变更,再次访问会出错,有关详细信息请参考 MSDN 文档。)

    这个,我也不能是太理解,只是先照着做个例子,先熟中间的类库了。

    我们还可以使用 MessageContractAttribute / MessageHeaderAttribute 来控制消息格式,这比 DataContractAttribute 要更加灵活。我们可以设置消息标头、消息体,包括是否对其中某些进行签名和加密处理。

    不过这个我没有实现


    <MessageContract()> _
    Public Class CompositeType


        
    Private boolValueField As Boolean = True
        
    Private stringValueField As String = String.Empty

        
    <MessageHeader()> _
        
    Public int As Integer = 111

        
    Public Sub New()

        
    End Sub

        
    Public Sub New(ByVal str As String)
            
    Me.StringValue = str
        
    End Sub

        
    <MessageHeader()> _
        
    Public Property BoolValue() As Boolean
            
    Get
                
    Return Me.boolValueField
            
    End Get
            
    Set(ByVal value As Boolean)
                
    Me.boolValueField = value
            
    End Set
        
    End Property

        
    <MessageBodyMember()> _
        
    Public Property StringValue() As String
            
    Get
                
    Return Me.stringValueField
            
    End Get
            
    Set(ByVal value As String)
                
    Me.stringValueField = value
            
    End Set
        
    End Property

    End Class

    生成的消息是:


    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
      
    <s:Header />
      
    <s:Body>
        
    <CompositeType xmlns="http://schemas.datacontract.org/2004/07/WcfServiceLibrary1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
          
    <BoolValue>true</BoolValue>
          
    <StringValue>zqonline</StringValue>
          
    <int>111</int>
        
    </CompositeType>
      
    </s:Body>
    </s:Envelope>

    并没有放在Header头。测试后发现,不能针对Message Layer层进行操作,才可以。


    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
      
    <s:Header>
        
    <h:BoolValue xmlns:h="http://tempuri.org/">true</h:BoolValue>
        
    <h:int xmlns:h="http://tempuri.org/">111</h:int>
        
    <To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://localhost:8731/Design_Time_Addresses/WcfServiceLibrary1/Service1/mex</To>
        
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">add</Action>
      
    </s:Header>
      
    <s:Body>
        
    <CompositeType xmlns="http://tempuri.org/">
          
    <StringValue>lily</StringValue>
        
    </CompositeType>
      
    </s:Body>
    </s:Envelope>

    int,BoolValue都放在了Header中了。

    好了,先到这里,虽然照着把代码实现了,但是其中还是不能理解。

  • 相关阅读:
    例行更新,防止被踢
    C语言 遍历磁盘目录
    析构函数的调用
    数组学习笔记
    函数学习笔记
    c++语言 纯虚函数的使用
    c++语言 内联方法
    复制构造函数
    c++语言 覆盖成员函数
    面向对象程序设计
  • 原文地址:https://www.cnblogs.com/zqonline/p/1602384.html
Copyright © 2011-2022 走看看