2011-04-20 99 views
5

情況:系統A應該公開SOAP 1.2 Web服務以供系統B調用。爲了讓A知道消息的內容,B向描述消息內容的A發送了XSD。使用.NET xsd.exe工具生成存根,創建簡單的web服務並完成工作。.NET WCF序列化問題

但是;當B調用這個Web服務時,A拒絕將SOAP/XML內容序列化到生成的代理類實例中。我意識到這必須是系統A在Web服務端定義的序列化方式,但一直無法準確找到問題所在。

從B消息的樣子(匿名) - 失敗:

<ns2:Set_Out xmlns:ns2="http://a.a/1.0" xmlns:ns1="http://b.b/1.0" xmlns:ns0="http://c.c"> 
<Context xmlns=""> 
    <Foo>test</Foo> 
    <Bar>test</Bar> 
    ... 
</Context> 

什麼從測試客戶端(基於WSDL)測試消息看起來像 - WORKS:

<Set_Out xmlns="http://a.a/1.0"> 
<Context xmlns:b="http://schemas.datacontract.org/2004/07/x.x" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 
    <b:Foo>TEST</b:Foo> 
    <b:Bar>test</b:Bar> 
    ... 
</Context> 

當由A構建的Web服務接收到來自B的消息時,它根本不序列化消息。代理的對象(例如Context)是null。當它從測試客戶端收到消息時,一切都會正確生成。

序列化屬性在代理:

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")] 
[System.SerializableAttribute()] 
[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.ComponentModel.DesignerCategoryAttribute("code")] 
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://a.a/1.0")] 
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://a.a/1.0", IsNullable=false)] 
[System.ServiceModel.MessageContract] 
public partial class Set_Out { 
    [System.Xml.Serialization.XmlElementAttribute(Namespace="http://a.a/1.0", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] [System.ServiceModel.MessageBodyMember(Order=0)] 
    public ContextType Context; 
    ... 

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")] 
[System.SerializableAttribute()] 
[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.ComponentModel.DesignerCategoryAttribute("code")] 
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://a.a/1.0")] 
public partial class ContextType { 
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] 
    public string Foo; 

事情,我覺得奇怪:

  1. 在生成該服務的WSDL,WSDL中增加了自己的命名空間的WSDL定義(例如上例中的xmlns:b)。
  2. WSDL不尊重代理中定義的unqualified註釋,並使所有內容都符合要求。

我已經嘗試過註釋的各種組合,但似乎沒有任何幫助;來自B的消息沒有被正確地反序列化到由A生成的代理。任何想法/指針/幫助將不勝感激!

+0

注:XML實例以上是從整個消息摘錄,顯然這包括了很多SOAP相關的東西,但我已經離開了這一點贅述。 – tmbrggmn 2011-04-20 13:08:02

+1

爲什麼要發送XSD?爲什麼不使用「添加服務參考」? – 2011-04-20 14:10:05

+0

我也有同樣的反應,但我正在諮詢一家公司,而且這家公司在我的故事中是B系統,所以我避免了衝突並且隨之而去。 – tmbrggmn 2011-04-21 07:02:32

回答

5

在「提出問題,5分鐘後自己解決」的典型案例中,我設法解決了我的問題。

問題在於,顯然,使用WCF .NET時,數據合同中涉及的類使用默認的序列化程序。這個默認的序列化程序(我相信它是DataContractSerializer)顯然沒有真正允許配置的方式。我不得不告訴WCF使用XmlSerializer來序列化消息。要做到這一點,我必須將[XmlSerializerFormat()]註釋添加到服務合約界面(顯然它也可以用於操作)。例如:

[ServiceContract(Namespace = "http://a.a/1.0")] 
[XmlSerializerFormat()] 
public interface IMyWebService 
{ 
    [OperationContract()] 
    void DoStuff(Set_Out message); 
} 

添加[XmlSerializerFormat()]註釋後,將WSDL顯著(適當的命名空間)改變,並且消息被正確串行化。

論壇的職位,讓我在正確的軌道上:http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/c7fede29-56c2-4ff3-bd02-48e3e0b2cec1/

+0

感謝您回答這個問題。它解決了我的問題! – 2015-02-12 00:43:42

2

(這其實是一個評論,但它不適合)

嘗試添加System.Diagnostics程序到你的web.config,以瞭解錯誤的詳細信息:

<system.diagnostics> 
    <trace autoflush="true" /> 
    <sources> 
     <source name="System.ServiceModel" 
       switchValue="Information, ActivityTracing" 
       propagateActivity="true"> 
      <listeners> 
       <add name="sdt" 
        type="System.Diagnostics.XmlWriterTraceListener" 
        initializeData= "C:\MyLog.svclog" /> 
      </listeners> 
     </source> 
    </sources> 
    </system.diagnostics> 

你可以使用C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\SvcTraceViewer.exe(或類似)查看svclog。把它添加到這兩個服務(當然不同的日誌文件名),看看哪一個失敗了,到底是爲什麼。

我會懷疑序列化是好的,但某些服務的綁定/設置會導致呼叫失敗。

+0

好的,典型的,但我認爲我找到了一個似乎可行的解決方案,需要做更多的測試,BRB :) – tmbrggmn 2011-04-20 13:19:39