2016-03-26 9 views
12

デフォルトのネームスペースを扱わないように見えますが、SOAPエンベロープレベルで宣言されたグローバルな名前空間と名前空間プレフィックスでうまく動作するSOAPサービスとのインターフェースに取り組んでいます。WCFクライアント:グローバルネームスペースを強制する

問題は、WCFはルートにこれらのグローバル名前空間を作成せず、むしろサービスが明らかに窒息している明示的に接頭されていないデフォルトの名前空間を使用することです。今私はこれが本当にWCFのせいではないことを知っています - 私はWCF生成メッセージが有効なXMLだと信じていますが、それにもかかわらずサービスはそれに悩まされます。このような

使用してWCF出力生成ルックス:動作しません

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> 
    <s:Header> 
    <h:Security xmlns:h="http://docs.oasis-open.org/wss/2004/01/oasis- 
      ... 
    </h:Security> 
    </s:Header> 
    <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <cancelShipmentRequest xmlns="http://www.royalmailgroup.com/api/ship/V2"> 
     <integrationHeader> 
     <dateTime xmlns="http://www.royalmailgroup.com/integration/core/V1">2016-03-26T01:44:37.0493801Z</dateTime> 
     <version xmlns="http://www.royalmailgroup.com/integration/core/V1">2</version> 
     <identification xmlns="http://www.royalmailgroup.com/integration/core/V1"> 
      <applicationId>RMG-API-G-01</applicationId> 
      <transactionId>ozhckwej6sxg</transactionId> 
     </identification> 
     </integrationHeader> 
     <cancelShipments> 
     <shipmentNumber>TTT001908905GB</shipmentNumber> 
     </cancelShipments> 
    </cancelShipmentRequest> 
    </s:Body> 
</s:Envelope> 

が動作しない(手動SOAPUIで)次のSOAPエンベロープを使用する:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:oas="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" 
    xmlns:v2="http://www.royalmailgroup.com/api/ship/V2" 
    xmlns:v1="http://www.royalmailgroup.com/integration/core/V1"> 
    <soapenv:Header> 
    <h:Security xmlns:h="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
     ... 
    </h:Security> 
    </soapenv:Header> 
    <soapenv:Body> 
    <v2:cancelShipmentRequest> 
     <v2:integrationHeader> 
     <v1:dateTime>2016-03-02T14:55:00Z</v1:dateTime> 
     <v1:version>2</v1:version> 
     <v1:identification> 
      <v1:applicationId>RMG-API-G-01</v1:applicationId> 
      <v1:transactionId>wftdaife96gv</v1:transactionId> 
     </v1:identification> 
     </v2:integrationHeader> 
     <v2:cancelShipments> 
     <v2:shipmentNumber>TTT001908905GB</v2:shipmentNumber> 
     </v2:cancelShipments> 
    </v2:cancelShipmentRequest> 
    </soapenv:Body> 
</soapenv:Envelope> 

2つの違いは、v1とv2名前空間は、ドキュメントの先頭にグローバルに宣言されているということではありませんし、何があります2番目のドキュメントのローカルの名前空間宣言

多分、私は何かが欠けているかもしれませんが、WCFが生成したXMLは有効であるように見え、名前空間に関しては同じ文書状態を表します。

唯一の違いは、名前空間が宣言されていることです。 WCFのバージョンは有効で、同じ名前空間を生成しているように見えますが、このサービスは無効な名前空間参照について不平を言っています。

スキーマの検証に失敗しました:メッセージはスキーマの検証に失敗しました:スキーマの有効性エラー:要素 'xmlns':この要素は期待されていません。予想されるのは({http://www.royalmailgroup.com/api/ship/V2} integrationHeader)です。

質問は、WCFにインラインではなく上部の名前空間参照を追加するように強制する最良の方法は何ですか?私が今までに見つけた唯一の方法は、メッセージインスペクタを使用して明示的にメッセージを書き換えることですが、もし私がすべてを行っても、手動でメッセージを作成することができます。

WCFにメッセージを手動で書き換えずに明示的な名前空間プレフィックスを使用させようとすることができるアイデアはありますか?

+0

私は最近、既存の名前空間を新しい名前空間にマージしようとしているのと同じ状況でした。私は決定的な答えを与えることはできません。私が見つけたのは、マージ、リビルド、VSを終了して既存のコードを統合しようとする試みを取り除いた後、すべてがうまくいったということでした。不自由な答え、私は同意します。私はそれがVSのバグだと思ったが、再現シナリオを試みるにはあまりに複雑であった。幸運にも、私はあなたの状況に対してより良い解決策/答えを待っています。 – JamieMeyer

+1

[このブログの記事](http://vanacosmin.ro/Articles/Read/WCFEnvelopeNamespacePrefix)または[この回答](http://stackoverflow.com/a/17798306/124386)で提案を試しましたか? –

+0

リチャードに感謝します。ブログの投稿は役に立ちましたし、正しい方向に私を指摘しました。 –

答えて

7

したがって、IClientMessageFormatterMessageというカスタムを作成して、Message.OnWriteStartEnvelope()をオーバーライドして、Soapドキュメントルートにすべての名前空間を明示的に書き出すようにしました。レンダリングされたドキュメントは、子要素に明示的に名前空間を割り当てる代わりに、これらの名前空間を再利用します。

これが機能するために作成される3つのクラスがあります:クライアントの各メソッドに添付するWCF

  • FormatMessageAttributeにフックされる実際のOnWriteStartEnvelope()
  • IClientMessageFormatterを扱う

    • メッセージの実装は、

    ここに3つのコードがあります。

    public class RoyalMailCustomMessage : Message 
    { 
        private readonly Message message; 
    
        public RoyalMailCustomMessage(Message message) 
        { 
         this.message = message; 
        } 
        public override MessageHeaders Headers 
        { 
         get { return this.message.Headers; } 
        } 
        public override MessageProperties Properties 
        { 
         get { return this.message.Properties; } 
        } 
        public override MessageVersion Version 
        { 
         get { return this.message.Version; } 
        } 
    
        protected override void OnWriteStartBody(XmlDictionaryWriter writer) 
        { 
         writer.WriteStartElement("Body", "http://schemas.xmlsoap.org/soap/envelope/"); 
        } 
        protected override void OnWriteBodyContents(XmlDictionaryWriter writer) 
        { 
         this.message.WriteBodyContents(writer); 
        } 
        protected override void OnWriteStartEnvelope(XmlDictionaryWriter writer) 
        { 
         writer.WriteStartElement("soapenv", "Envelope", "http://schemas.xmlsoap.org/soap/envelope/"); 
         writer.WriteAttributeString("xmlns", "oas", null, "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); 
         writer.WriteAttributeString("xmlns", "v2", null, "http://www.royalmailgroup.com/api/ship/V2"); 
         writer.WriteAttributeString("xmlns", "v1", null, "http://www.royalmailgroup.com/integration/core/V1"); 
         writer.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance"); 
         writer.WriteAttributeString("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema");    
        } 
    } 
    
    public class RoyalMailMessageFormatter : IClientMessageFormatter 
    { 
        private readonly IClientMessageFormatter formatter; 
    
        public RoyalMailMessageFormatter(IClientMessageFormatter formatter) 
        { 
         this.formatter = formatter; 
        } 
    
        public Message SerializeRequest(MessageVersion messageVersion, object[] parameters) 
        { 
         var message = this.formatter.SerializeRequest(messageVersion, parameters); 
         return new RoyalMailCustomMessage(message); 
        } 
    
        public object DeserializeReply(Message message, object[] parameters) 
        { 
         return this.formatter.DeserializeReply(message, parameters); 
        } 
    } 
    
    
    [AttributeUsage(AttributeTargets.Method)] 
    public class RoyalMailFormatMessageAttribute : Attribute, IOperationBehavior 
    { 
        public void AddBindingParameters(OperationDescription operationDescription, 
         BindingParameterCollection bindingParameters) 
        { } 
    
        public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) 
        { 
         var serializerBehavior = operationDescription.Behaviors.Find<XmlSerializerOperationBehavior>(); 
    
         if (clientOperation.Formatter == null) 
          ((IOperationBehavior)serializerBehavior).ApplyClientBehavior(operationDescription, clientOperation); 
    
         IClientMessageFormatter innerClientFormatter = clientOperation.Formatter; 
         clientOperation.Formatter = new RoyalMailMessageFormatter(innerClientFormatter); 
        } 
    
        public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) 
        { } 
    
        public void Validate(OperationDescription operationDescription) { } 
    } 
    

    大部分は式典と定型文です。キーコード部分はOnWriteStartEnvelopeで、実際のネームスペースがフックアップされます。SerializeRequestフォーマッタはWCFパイプラインにフックされ、ApplyClientBehaviorメッセージフォーマッタは実際の操作に添付されます。

    これをフックするには、サービスインタフェースのクライアントメソッドに属性を追加しました。この場合、生成されたWCFクライアントのReference.csに属性を追加しました。すべての文書の先頭に定義された名前空間で期待通りWCFから生成

    // CODEGEN: Generating message contract since the operation cancelShipment is neither RPC nor document wrapped. 
        [System.ServiceModel.OperationContractAttribute(Action="cancelShipment", ReplyAction="*")] 
        [System.ServiceModel.FaultContractAttribute(typeof(MarvelPress.Workflow.Business.RoyalShippingApi.exceptionDetails), Action="cancelShipment", Name="exceptionDetails")] 
        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)] 
        [System.ServiceModel.ServiceKnownTypeAttribute(typeof(contactMechanism))] 
        [System.ServiceModel.ServiceKnownTypeAttribute(typeof(baseRequest))] 
        [RoyalMailFormatMessage()] 
        MarvelPress.Workflow.Business.RoyalShippingApi.cancelShipmentResponse1 cancelShipment(MarvelPress.Workflow.Business.RoyalShippingApi.cancelShipmentRequest1 request); 
    

    メッセージは、今見て:

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:oas="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:v2="http://www.royalmailgroup.com/api/ship/V2" xmlns:v1="http://www.royalmailgroup.com/integration/core/V1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
        <s:Header xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> 
        <h:Security>...</h:Security> 
        </s:Header> 
        <soapenv:Body> 
        <v2:cancelShipmentRequest> 
         <v2:integrationHeader> 
         <v1:dateTime>2016-04-02T01:04:50.4122473Z</v1:dateTime> 
         <v1:version>2</v1:version> 
         <v1:identification> 
          <v1:applicationId>RMG-API-G-01</v1:applicationId> 
          <v1:transactionId>fshrxevdnc7n</v1:transactionId> 
         </v1:identification> 
         </v2:integrationHeader> 
         <v2:cancelShipments> 
         <v2:shipmentNumber>TTT001908905GB</v2:shipmentNumber> 
         </v2:cancelShipments> 
        </v2:cancelShipmentRequest> 
        </soapenv:Body> 
    </soapenv:Envelope>  
    

    詳細情報と汎用的な名前空間のためにフォーマッタがここに私の関連ブログ記事をチェックアウト追加:http://weblog.west-wind.com/posts/2016/Apr/02/Custom-Message-Formatting-in-WCF-to-add-all-Namespaces-to-the-SOAP-Envelope

  • 関連する問題