[英]How to programmatically add soap header when calling a WCF Service from .NET?
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 Header(而不是在配置文件中定義用戶名和密碼)。
我嘗試了像https://stackoverflow.com/a/53208601/255966這樣的解決方案,但我遇到了 scope 被配置在另一個線程上的異常,可能是因為我調用了 ZFB608Z936129FECB2BB59B67 服務。
您可以通過實現 IClientMessageInspector 接口在實現 class 中添加 soap header。
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, 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 的更多信息,請參閱以下鏈接。
由於對此問題的評論/答案以及這些附加資源,我得到了它的工作:
我的解決方案如下:
創建 AuthHeader class 擴展 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
添加到請求消息中。
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)
{
}
}
創建一個使用 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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.