从.NET调用WCF服务时如何以编程方式添加soap标头?
Posted
技术标签:
【中文标题】从.NET调用WCF服务时如何以编程方式添加soap标头?【英文标题】:How to programmatically add soap header when calling a WCF Service from .NET? 【发布时间】:2021-05-27 01:54:42 【问题描述】:app.config 中的服务配置包含此设置:
<client>
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_GenerateAndConvert" contract="GenerateAndConvert.MyPortType" name="MyGenerateAndConvert" >
<headers>
<AuthHeader>
<username>abc</username>
<password>xyz</password>
</AuthHeader>
</headers>
</endpoint>
</client>
序列化为:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:MyServer">
<soapenv:Header>
<AuthHeader>
<username>abc</username>
<password>xyz</password>
</AuthHeader>
</soapenv:Header>
<soapenv:Body>
<urn:Convert>
</urn:Convert>
</soapenv:Body>
</soapenv:Envelope>
我的问题是如何在 .NET 应用程序中使用服务引用时以编程方式添加 SOAP 标头(而不是在配置文件中定义用户名和密码)。
我尝试了https://***.com/a/53208601/255966 之类的解决方案,但出现了异常,即作用域被设置在另一个线程上,可能是因为我调用了 WCF 服务 Async。
【问题讨论】:
你看到this了吗? 【参考方案1】:您可以通过实现IClientMessageInspector接口在实现类中添加soap头。
public class ClientMessageLogger : IClientMessageInspector
public void AfterReceiveReply(ref Message reply, object correlationState)
public object BeforeSendRequest(ref Message request, IClientChannel channel)
MessageHeader header = MessageHeader.CreateHeader("MySoapHeader", "http://my-namespace.com", "asdas");
request.Headers.Add(header);
return null;
将客户端消息记录器添加到客户端运行时:
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class, AllowMultiple = false)]
public class CustContractBehaviorAttribute : Attribute, IContractBehavior, IContractBehaviorAttribute
public Type TargetContract => throw new NotImplementedException();
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
return;
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
clientRuntime.ClientMessageInspectors.Add(new ClientMessageLogger());
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
return;
向接口添加属性:
[CustContractBehavior]
public interface IService
这是服务器收到的soap消息:
想了解更多关于IClientMessageInspector,请参考以下link。
【讨论】:
【参考方案2】:感谢有关此问题的 cmets/answers 和这些额外资源,我得到了它的工作:
How to add custom soap headers in wcf? How to add a custom HTTP header to every WCF call? Custom MessageHeaders in WCF我的解决方法如下:
AuthHeader
创建扩展 MessageHeader 的 AuthHeader 类以使用用户名和密码创建 AuthHeader:
public class AuthHeader : MessageHeader
private readonly string _username;
private readonly string _password;
public AuthHeader(string username, string password)
_username = username ?? throw new ArgumentNullException(nameof(username));
_password = password ?? throw new ArgumentNullException(nameof(password));
protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
writer.WriteStartElement("username");
writer.WriteString(_username);
writer.WriteEndElement();
writer.WriteStartElement("password");
writer.WriteString(_password);
writer.WriteEndElement();
public override string Name => "AuthHeader";
public override string Namespace => string.Empty;
HttpHeaderMessageInspector
创建一个 HttpHeaderMessageInspector,可用于将MessageHeader
添加到请求消息中。
public class HttpHeaderMessageInspector : IClientMessageInspector
private readonly MessageHeader[] _headers;
public HttpHeaderMessageInspector(params MessageHeader[] headers)
_headers = headers;
public object BeforeSendRequest(ref Message request, IClientChannel channel)
foreach (var header in _headers)
request.Headers.Add(header);
return null;
public void AfterReceiveReply(ref Message reply, object correlationState)
AddHttpHeaderMessageEndpointBehavior
创建一个使用 HttpHeaderMessageInspector 的特定 EndpointBehavior。
public class AddHttpHeaderMessageEndpointBehavior : IEndpointBehavior
private readonly IClientMessageInspector _httpHeaderMessageInspector;
public AddHttpHeaderMessageEndpointBehavior(params MessageHeader[] headers)
_httpHeaderMessageInspector = new HttpHeaderMessageInspector(headers);
public void Validate(ServiceEndpoint endpoint)
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
clientRuntime.ClientMessageInspectors.Add(_httpHeaderMessageInspector);
客户
创建一个添加自定义 EndpointBehavior 的客户端,以在 Soap 消息中插入 MessageHeader。
private MyTestPortTypeClient CreateAuthenticatedClient()
var client = new MyTestPortTypeClient(_settings.EndpointConfigurationName, _settings.EndpointAddress);
client.Endpoint.EndpointBehaviors.Clear();
var authHeader = new AuthHeader(_settings.UserName, _settings.Password);
client.Endpoint.EndpointBehaviors.Add(new AddHttpHeaderMessageEndpointBehavior(authHeader));
return client;
【讨论】:
以上是关于从.NET调用WCF服务时如何以编程方式添加soap标头?的主要内容,如果未能解决你的问题,请参考以下文章