我是 WCF 新手。我正在托管一个由第三方应用程序 (TPA) 调用的 WCF 服务。 TPA 要求 wcf 服务响应具有自定义 header ,并且响应 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 绑定(bind),如下所示:
var binding = new CustomBinding();
binding.Elements.Add( new TextMessageEncodingBindingElement() { MessageVersion = MessageVersion.Soap12WSAddressing10 } );
binding.Elements.Add( new HttpTransportBindingElement() );
为了向我的响应添加自定义 soap header ,我使用了 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 的预期完全不同。我需要做什么才能使 fiddler 输出看起来更像 TPA 所期望的。为什么不是所有 WS-Address 元素都像 <wsa:Action>
, <wsa:MessageID>
和 <wsa:RelatesTo>
作为标题的一部分呈现。任何帮助将不胜感激。
最佳答案
这是一个例子。我已经使用适当的命名空间和 DataMembers 创建了 DataContract 类。然后我将根类的实例添加到消息头中。为了填充 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>
它的格式不完全相同,但它是相同的消息。
希望这对您有所帮助。
关于c# - 如何在 WCF 服务响应中正确实现自定义 soap 1.2 header 和 WS-Addressing,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15808852/