如何解决从.NET 调用WCF 服务时如何以编程方式添加soap 标头? AuthHeaderHttpHeaderMessageInspectorAddHttpHeaderMessageEndpointBehavior客户
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://stackoverflow.com/a/53208601/255966 的解决方案,但我得到了范围被设置在另一个线程上的异常,可能是因为我调用了 WCF 服务 Async。
解决方法
您可以通过实现 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;
}
}
将 clientmessagelogger 添加到 clientruntime:
[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,ClientRuntime clientRuntime)
{
clientRuntime.ClientMessageInspectors.Add(new ClientMessageLogger());
}
public void ApplyDispatchBehavior(ContractDescription contractDescription,DispatchRuntime dispatchRuntime)
{
}
public void Validate(ContractDescription contractDescription,ServiceEndpoint endpoint)
{
return;
}
}
向接口添加属性:
[CustContractBehavior]
public interface IService {
}
这是服务器收到的soap消息:
要了解有关 IClientMessageInspector 的更多信息,请参阅以下 link。
,感谢对这个问题的评论/答案和这些额外的资源:
- How to add custom soap headers in wcf?
- How to add a custom HTTP header to every WCF call?
- Custom MessageHeaders in WCF
我的解决方法如下:
AuthHeader
创建 AuthHeader 类,它扩展 MessageHeader 以创建带有用户名和密码的 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
创建可用于向请求消息添加 MessageHeader
的 HttpHeaderMessageInspector。
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;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。