如何在WCF服务响应中正确实现自定义soap 1.2标头和WS-Addressing

时间:2013-04-04 10:38:57

标签: c# wcf soap

我是一名WCF新手。我正在托管一个由第三方应用程序(TPA)调用的WCF服务。 TPA要求wcf服务响应具有自定义标头,响应soap信封应如下所示:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
               xmlns:stan="http://client/schema/framework/header/standardheaderresponse"
               xmlns:sys="http://client/schema/framework/common/systemidentifier"  >

  <soap:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
    <stan:StandardHeaderResponse>
      <stan:From>
        <sys:Identifier>BUS</sys:Identifier>
        <sys:Name>BuildingEvent</sys:Name>
        <sys:Version>1</sys:Version>
      </stan:From>
      <stan:Timestamp>2013-03-15T03:05:41.000</stan:Timestamp>
      <stan:CorrelationID>uuid:c12c9e48-8164-4074-9c8c-2b979804dbd2</stan:CorrelationID>
    </stan:StandardHeaderResponse>

    <wsa:Action> 
      http://client/service.buildingloc.event.BuildingEvent.SendEvent
    </wsa:Action>
    <wsa:MessageID>uuid:ab4c4001-f089-721c-aae6-f51ec37d3501</wsa:MessageID>
    <wsa:To>http://www.w3.org/2005/08/addressing/anonymous</wsa:To>
    <wsa:RelatesTo>uuid:de9a7007-f056-431c-aae6-f51ec37d3488</wsa:RelatesTo>
  </soap:Header>

  <soap:Body>
    …
  </soap:Body>

</soap:Envelope>

我的服务使用自定义wcf绑定,如下所示:

var binding     = new CustomBinding();   
binding.Elements.Add( new TextMessageEncodingBindingElement() { MessageVersion = MessageVersion.Soap12WSAddressing10 } );
binding.Elements.Add( new HttpTransportBindingElement() );

要在我的响应中添加自定义soap标头,我使用的是IDispatchMessageInspector,它看起来如下:

   public void BeforeSendReply(ref Message reply, object correlationState)
        {
            reply.Headers.Add(new StandardHeaderResponse());
        }

和MessageHeader如下:

[MessageContract]
    public class StandardHeaderResponse : MessageHeader
    {
        #region Overrides of MessageHeaderInfo

        public override string Name
        {
            get { return GetType().Name; }
        }

        public override string Namespace
        {
            get { return "client/schema/framework/header/standardheaderresponse"; }
        }

        #endregion

        #region Overrides of MessageHeader

        protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
        {
            writer.WriteElementString("Key", "Value");
        }

        #endregion
    }

但是当我运行服务并从我的测试客户端发出请求时,我在Fiddler中获得以下输出

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
  <s:Header>
    <a:RelatesTo>urn:uuid:953e0b5b-44c6-4994-aae2-7710c31cb8f0</a:RelatesTo>
    <StandardHeaderResponse>
      <Key>Value</Key>
    </StandardHeaderResponse>
  </s:Header>
  <s:Body> 
   ...   
  </s:Body>
</s:Envelope>

这与TPA的期望完全不同。我需要做些什么来使小提琴输出看起来更像TPA所期望的。为什么所有WS-Address元素(如<wsa:Action><wsa:MessageID><wsa:RelatesTo>都不会呈现为标题的一部分。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:6)

这是一个例子。我已经使用适当的命名空间和DataMembers创建了DataContract类。然后我将根类的实例添加到Message Header。为了填充WSA元素,我在Message.Headers集合上使用了属性。

 class Program
{
    [DataContract( Namespace = "http://client/schema/framework/header/standardheaderresponse" )]
    public class StandardHeaderResponse
    {
        [DataMember( Order = 1 )]
        public FromHeaderResponse From { get; set; }

        [DataMember( Order = 2 )]
        public DateTime Timestamp { get; set; }

        [DataMember( Order = 3 )]
        public Guid CorrelationID { get; set; }
    }

    [DataContract( Namespace = "http://client/schema/framework/common/systemidentifier" )]
    public class FromHeaderResponse
    {
        [DataMember( Order = 1 )]
        public string Identifier { get; set; }

        [DataMember( Order = 2 )]
        public string Name { get; set; }

        [DataMember( Order = 3 )]
        public int Version { get; set; }
    }

    static void Main( string[] args )
    {
        Message message = Message.CreateMessage( MessageVersion.Default, "http://client/service.buildingloc.event.BuildingEvent.SendEvent", "Message body" );

        var header = new StandardHeaderResponse()
        {
            CorrelationID = Guid.NewGuid(),
            Timestamp = DateTime.Now,
            From = new FromHeaderResponse()
            {
                Identifier = "BUS",
                Name = "BuildingEvent",
                Version = 1
            }
        };

        message.Headers.Add( MessageHeader.CreateHeader( "StandardHeaderResponse", "http://client/schema/framework/header/standardheaderresponse", header ) );
        message.Headers.Action = @"http://client/service.buildingloc.event.BuildingEvent.SendEvent";
        message.Headers.To = new Uri( @"http://www.w3.org/2005/08/addressing/anonymous" );
        message.Headers.MessageId = new System.Xml.UniqueId( Guid.NewGuid() );
        message.Headers.RelatesTo = new System.Xml.UniqueId( Guid.NewGuid() );

        Console.WriteLine( message.ToString() );
        Console.WriteLine( "Press any key to exit..." );
        Console.ReadKey();
    }
}

结果消息如下:

<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">
  <s:Header>
    <a:Action s:mustUnderstand="1">http://client/service.buildingloc.event.BuildingEvent.SendEvent</a:Action>
    <StandardHeaderResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://client/schema/framework/header/standardheaderresponse">
      <From xmlns:d4p1="http://client/schema/framework/common/systemidentifier">
        <d4p1:Identifier>BUS</d4p1:Identifier>
        <d4p1:Name>BuildingEvent</d4p1:Name>
        <d4p1:Version>1</d4p1:Version>
      </From>
      <Timestamp>2013-04-10T00:17:13.8001086+02:00</Timestamp>
      <CorrelationID>6fa83bf3-95f2-4101-aa78-b271a9e96aae</CorrelationID>
    </StandardHeaderResponse>
    <a:To s:mustUnderstand="1">http://www.w3.org/2005/08/addressing/anonymous</a:To>
    <a:MessageID>urn:uuid:88bc7f91-1de6-4c08-84bc-de75e029337d</a:MessageID>
    <a:RelatesTo>urn:uuid:6dd90731-5ca3-4c83-949b-194ee9da4b6c</a:RelatesTo>
  </s:Header>
  <s:Body>
    <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">Message  body</string>
  </s:Body>
</s:Envelope>

它的格式不完全相同,但它是相同的消息。

希望这有帮助。