C# 所有操作的 WCF WSDL Soap Header
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/986455/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WCF WSDL Soap Header on all operations
提问by Linefeed
By defining an attribute that implements IContactBehavior and IWsdlExportExtension and set that attribute on your service contract, you can easily add Soap Headers to your wsdl(see http://wcfextras.codeplex.com/for more information)
通过定义实现 IContactBehavior 和 IWsdlExportExtension 的属性并在您的服务合同中设置该属性,您可以轻松地将Soap 标头添加到您的 wsdl(有关更多信息,请参阅http://wcfextras.codeplex.com/)
But now I need to set a Soap Header contract in the wsdl on all Operationcontracts and this time I cannot set an attribute.
但是现在我需要在所有 Operationcontracts 的 wsdl 中设置一个 Soap Header 合同,这次我无法设置属性。
Following code (called from IWsdlExportExtension.ExportEndPoint) doesn't work, but does work when called from the SoapHeaderAttributes (that executes an IWsdlExportExtension.ExportContract)
以下代码(从 IWsdlExportExtension.ExportEndPoint 调用)不起作用,但在从 SoapHeaderAttributes(执行 IWsdlExportExtension.ExportContract)调用时起作用
foreach (OperationDescription operationDescription in context.ContractConversionContext.Contract.Operations)
{
AddSoapHeader(operationDescription, "SomeHeaderObject", typeof(SomeHeaderObject), SoapHeaderDirection.InOut);
}
internal static void AddSoapHeader(OperationDescription operationDescription, string name, Type type, SoapHeaderDirection direction)
{
MessageHeaderDescription header = GetMessageHeader(name, type);
bool input = ((direction & SoapHeaderDirection.In) == SoapHeaderDirection.In);
bool output = ((direction & SoapHeaderDirection.Out) == SoapHeaderDirection.Out);
foreach (MessageDescription msgDescription in operationDescription.Messages)
{
if ((msgDescription.Direction == MessageDirection.Input && input) ||
(msgDescription.Direction == MessageDirection.Output && output))
msgDescription.Headers.Add(header);
}
}
internal static MessageHeaderDescription GetMessageHeader(string name, Type type)
{
string headerNamespace = SoapHeaderHelper.GetNamespace(type);
MessageHeaderDescription messageHeaderDescription = new MessageHeaderDescription(name, headerNamespace);
messageHeaderDescription.Type = type;
return messageHeaderDescription;
}
Anyone has an idea how to apply this code on all operations (without using attributes) and by doing this, adding the contract of the header to the wsdl ?
任何人都知道如何将此代码应用于所有操作(不使用属性),并通过这样做将标头的合同添加到 wsdl ?
采纳答案by Linefeed
The IEndpointBehavior has the following interface:
IEndpointBehavior 具有以下接口:
ApplyDispatchBehavior(ServiceEndpoint endPoint, EndPointDispatcher endpointDispatcher);
You can add Soap Headers to the wsdl for operations by iterating over the endpoint.Contract.Operations in the ApplyDispatchBehavior.
您可以通过遍历 ApplyDispatchBehavior 中的 endpoint.Contract.Operations 将 Soap Headers 添加到 wsdl 以进行操作。
Here you have the complete solution that worked for me:
在这里,您拥有对我有用的完整解决方案:
void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
foreach (OperationDescription operationDescription in endpoint.Contract.Operations)
{
foreach (MessageDescription msgDescription in operationDescription.Messages)
{
AddSoapHeader(operationDescription, "SomeHeaderObject", typeof(SomeHeaderObject), SoapHeaderDirection.InOut);
}
}
}
internal static void AddSoapHeader(OperationDescription operationDescription, string name, Type type, SoapHeaderDirection direction)
{
MessageHeaderDescription header = GetMessageHeader(name, type);
bool input = ((direction & SoapHeaderDirection.In) == SoapHeaderDirection.In);
bool output = ((direction & SoapHeaderDirection.Out) == SoapHeaderDirection.Out);
foreach (MessageDescription msgDescription in operationDescription.Messages)
{
if ((msgDescription.Direction == MessageDirection.Input && input) ||
(msgDescription.Direction == MessageDirection.Output && output))
msgDescription.Headers.Add(header);
}
}
internal static MessageHeaderDescription GetMessageHeader(string name, Type type)
{
string headerNamespace = SoapHeaderHelper.GetNamespace(type);
MessageHeaderDescription messageHeaderDescription = new MessageHeaderDescription(name, headerNamespace);
messageHeaderDescription.Type = type;
return messageHeaderDescription;
}
The SoapHeaderHelper can be found in the WcfExtras.
SoapHeaderHelper 可以在WcfExtras 中找到。
回答by marc_s
You might want to have a look at the WCFExtrasproject on CodePlex - it has some support for custom SOAP headers and stuff like that. Not 100% sure if it's capable of filling your need, but check it out!
您可能想看看CodePlex上的WCFExtras项目——它对自定义 SOAP 标头和类似的东西有一些支持。不能 100% 确定它是否能够满足您的需求,但请检查一下!
Marc
马克
UPDATE: have you looked into creating a WCF extension, e.g. something like a message inspector, on both the client and the server side?
更新:您是否考虑过在客户端和服务器端创建 WCF 扩展,例如类似消息检查器的东西?
The client side IClientMessageInspector defines two methods BeforeSendRequest
and AfterReceiveReply
while the server side IDispatchMessageInspector has the opposite methods, i.e. AfterReceiveRequest
and BeforeSendReply
.
客户端 IClientMessageInspector 定义了两个方法BeforeSendRequest
,AfterReceiveReply
而服务器端 IDispatchMessageInspector 具有相反的方法,即AfterReceiveRequest
和BeforeSendReply
。
With this, you could add headers to every message going across the wire (or selectively only to a few).
有了这个,您可以为通过线路的每条消息添加标头(或选择性地仅添加到少数)。
Here's a snippet from a IClientMessageInspector implementor we use to automagically transmit the locale information (language and culture info) across from the clients to the server - should give you an idea how to get started:
这是 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;
}
回答by Ramunas
Easiest way is to use WCFExtrasPlus "https://wcfextrasplus.codeplex.com/wikipage?title=SOAP%20Headers&referringTitle=Documentation", just add dll as reference to your project and edit your service in such way:
最简单的方法是使用 WCFExtrasPlus " https://wcfextrasplus.codeplex.com/wikipage?title=SOAP%20Headers&referringTitle=Documentation",只需添加 dll 作为对您项目的引用并以这种方式编辑您的服务:
[DataContract(Name="MyHeader", Namespace="web")]
public class MyHeader
{
[DataMember(Order=1)]
public string UserName {get; set;}
[DataMember(Order=2)]
public string Password { get; set; }
}
[SoapHeaders]
[ServiceContract]
public interface IMyService
{
[SoapHeader("MyHeader", typeof(MyHeader), Direction = SoapHeaderDirection.In)]
[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Wrapped)]
bool MyMethod(string input);
}
Then Soap request looks like:
然后 Soap 请求看起来像:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="web" xmlns:tem="http://tempuri.org/">
<soapenv:Header>
<web:MyHeader>
<web:UserName>?</web:UserName>
<web:Password>?</web:Password>
</web:MyHeader>
</soapenv:Header>
<soapenv:Body>
<tem:MyMethod>
<tem:input>?</tem:input>
</tem:MyMethod>
</soapenv:Body>
</soapenv:Envelope>
If you need Soap and JSON at same service here is example: https://stackoverflow.com/a/23910916/3667714
如果您在同一服务中需要 Soap 和 JSON,则示例如下:https: //stackoverflow.com/a/23910916/3667714