【问题标题】:WCF WSDL Soap Header on all operations所有操作上的 WCF WSDL Soap 标头
【发布时间】:2009-06-12 12:46:59
【问题描述】:

通过定义一个实现 IContactBehavior 和 IWsdlExportExtension 的属性并在您的服务合同上设置该属性,您可以轻松地将 Soap 标头添加到您的 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 中?

【问题讨论】:

    标签: c# wcf wsdl


    【解决方案1】:

    IEndpointBehavior 有如下接口:

    ApplyDispatchBehavior(ServiceEndpoint endPoint, EndPointDispatcher endpointDispatcher);
    

    您可以通过迭代 ApplyDispatchBehavior 中的 endpoint.Contract.Operations 将 Soap 标头添加到 wsdl 以进行操作。

    这里有适合我的完整解决方案:

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

    SoapHeaderHelper 可以在WcfExtras 中找到。

    【讨论】:

    • 您在ApplyDispatchBehavior()AddSoapHeader() 中都有foreach MessageDescription 循环。我认为应该删除ApplyDispatchBehavior() 中的那个。
    【解决方案2】:

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

    马克

    更新:您是否考虑过创建 WCF 扩展,例如在客户端和服务器端都像消息检查器一样?

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

    有了这个,您可以为通过网络的每条消息添加标头(或选择性地仅添加到少数)。

    这是来自 IClientMessageInspector 实现者的 sn-p,我们使用它自动将区域设置信息(语言和文化信息)从客户端传输到服务器 - 应该让您了解如何开始:

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

    【讨论】:

    • 我实际上是在自己指出 WCFExtras,但我不知道如何在不设置属性的情况下在所有操作中向 wsdl 添加soap 标头。
    • 我不明白这如何适用于修改 WSDL 合同。你能澄清一下吗?
    • 我没有。 Inspector 很好,但他们所做的并没有反映在 WSDL 合同中,所以客户必须意识到这一点......
    【解决方案3】:

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

    那么肥皂请求看起来像:

    <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

    【讨论】:

      猜你喜欢
      • 2011-01-09
      • 1970-01-01
      • 2019-08-18
      • 1970-01-01
      • 1970-01-01
      • 2012-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多