所有操作的WCF WSDL Soap Header

时间:2009-06-12 12:46:59

标签: c# wcf wsdl

通过定义实现IContactBehavior和IWsdlExportExtension的属性并在服务合同上设置该属性,您可以轻松地将 Soap Headers添加到您的wsdl (有关详细信息,请参阅http://wcfextras.codeplex.com/

但现在我需要在所有Operationcontracts的wsdl中设置Soap Header合约,这次我无法设置属性。

以下代码(从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;
}

任何人都知道如何在所有操作(不使用属性)上应用此代码,并通过这样做,将标头的合同添加到wsdl?

3 个答案:

答案 0 :(得分:5)

IEndpointBehavior具有以下界面:

ApplyDispatchBehavior(ServiceEndpoint endPoint, EndPointDispatcher endpointDispatcher);

您可以通过迭代ApplyDispatchBehavior中的endpoint.Contract.Operations来向wsdl添加Soap Headers以进行操作。

在这里,您拥有适合我的完整解决方案:

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;
}

可以在WcfExtras

中找到SoapHeaderHelper

答案 1 :(得分:4)

您可能希望查看CodePlex上的WCFExtras项目 - 它对自定义SOAP标头和类似的东西有一些支持。不是100%确定它是否能够满足您的需求,但请查看它!

马克

更新:您是否考虑过创建WCF扩展,例如客户端和服务器端的消息检查器之类的东西?

客户端IClientMessageInspector定义了两个方法BeforeSendRequestAfterReceiveReply,而服务器端IDispatchMessageInspector具有相反的方法,即AfterReceiveRequestBeforeSendReply

通过这种方式,您可以为每条通过电汇的消息添加标题(或者有选择地只添加一些消息)。

这是来自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;
}

答案 2 :(得分:0)

最简单的方法是使用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);
}

然后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>

如果您在同一服务中需要Soap和JSON,请参见示例:https://stackoverflow.com/a/23910916/3667714