在basicHttpBinding中,我是否可以像在ASMX Web服务中添加自定义身份验证标头一样,在WCF传入/传出消息中添加自定义SOAP标头?这些自定义SOAP标头应该可通过.NET 2.0 / 1.1 Web服务客户端访问(可通过WSDL.EXE工具访问)。
在basicHttpBinding中,我是否可以像在ASMX Web服务中添加自定义身份验证标头一样,在WCF传入/传出消息中添加自定义SOAP标头?这些自定义SOAP标头应该可通过.NET 2.0 / 1.1 Web服务客户端访问(可通过WSDL.EXE工具访问)。
请查看WCF Extras在Codeplex上的链接 - 它是一个简单的WCF扩展库,其中包含自定义SOAP头等内容。
另一个选项是在您的WCF服务中使用WCF消息契约 - 这也可以轻松地让您定义和设置WCF SOAP头。
[MessageContract]
public class BankingTransaction
{
[MessageHeader]
public Operation operation;
[MessageHeader]
public DateTime transactionDate;
[MessageBodyMember]
private Account sourceAccount;
[MessageBodyMember]
private Account targetAccount;
[MessageBodyMember]
public int amount;
}
在这里,“operation”和“transactionDate”被定义为SOAP标头。
如果上述方法都无法帮助您,那么您应该了解WCF消息检查器的概念,您可以将其编写为扩展。它们允许您在客户端的每个传出调用中注入某些标头,并从消息中检索这些标头以供您使用。
请参阅此博客文章通过WCF行为处理自定义SOAP标头作为编写消息检查器的起点,以及如何将其包含在项目设置中。
客户端侧的IClientMessageInspector
定义了两个方法BeforeSendRequest
和AfterReceiveReply
,而服务器侧的IDispatchMessageInspector
具有相反的方法,即AfterReceiveRequest
和BeforeSendReply
。
有了这个,您可以向通过网络传输的每个消息添加标头(或仅选择性地添加到其中一些消息)。
下面是我们使用的IClientMessageInspector
实现者的片段,用于自动传输区域设置信息(语言和文化信息)从客户端到服务器,这应该能给您一个开始的想法:
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
International intlHeader = new International();
intlHeader.Locale = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;
MessageHeader header = MessageHeader.CreateHeader(WSI18N.ElementNames.International, WSI18N.NamespaceURI, intlHeader);
request.Headers.Add(header);
return null;
}
在服务器端,您将检查这些标题是否存在,如果存在,则从SOAP信封中提取它们并使用它们。更新:好的消息是,您的客户端正在使用.NET 2.0而且没有使用WCF。此时仍然可以正常工作,请参阅此博客文章“自定义SOAP标头:WCF和ASMX”以获取详细信息。在服务器端仍然可以使用消息检查器来嗅探和提取由.NET 2.0客户端发送的自定义标头。我认为这个解决方案更为简单:
var client = "Your Service Client";
using (var scope = new OperationContextScope(client.InnerChannel))
{
System.Xml.XmlDocument document = new XmlDocument();
XmlElement element = document.CreateElement("wsse", "UsernameToken", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
XmlElement newChild = null;
newChild = document.CreateElement("wsse", "Username", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
newChild.InnerText = "finance";
element.AppendChild(newChild);
newChild = document.CreateElement("wsse", "CorporationCode", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
newChild.InnerText = "387";
element.AppendChild(newChild);
MessageHeader messageHeader = MessageHeader.CreateHeader("UsernameToken", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", element, false);
OperationContext.Current.OutgoingMessageHeaders.Add(messageHeader);
var result = client.GetCorporations(new CorporationType { pageNo = 1 });
}