2011-04-20 12 views
5

Sytuacja: system A powinien odsłonić usługę sieciową SOAP 1.2, aby system B zadzwonił. Aby A wiedział, jak wygląda wiadomość, B wysłał XSD do A, opisując zawartość wiadomości. Wygenerowano kody pośredniczące za pomocą narzędzia .NET xsd.exe, utworzono prosty serwis internetowy i zadanie zostało wykonane.Problemy z serializacją WCF .NET

Jednak; gdy B wywołuje tę usługę sieciową, odmawia serializacji zawartości SOAP/XML do wygenerowanych instancji klasy proxy. Zdaję sobie sprawę, że musi to wynikać z tego, jak serializacja jest określona po stronie usługi sieciowej w systemie A, ale nie udało się zlokalizować dokładnie tego, co dzieje się nie tak.

Co się komunikat z B wygląda (anonimowe) - NIE:

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

Co wiadomość testowa z klienta testowego (na podstawie WSDL) wygląda - działa:

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

Gdy usługa internetowa zbudowana przez A odbiera wiadomości od B, w ogóle nie tworzy ona serializacji wiadomości. Obiekty proxy (na przykład Context) to null. Po otrzymaniu wiadomości od klienta testowego wszystko jest generowane poprawnie.

Serializacja atrybutów pełnomocnika:

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

Czego znaleźć dziwne:

  1. Podczas generowania WSDL dla tej usługi, WSDL dodaje własne przestrzenie nazw w definicji WSDL (xmlns:b w powyższym przykładzie, na przykład).
  2. Dokument WSDL nie respektuje adnotacji unqualified zdefiniowanych w proxy i sprawia, że ​​wszystko jest kwalifikowane.

Próbowałem różnych kombinacji adnotacji, ale nic nie pomaga; wiadomości od B nie są poprawnie przekształcane do postaci pośredniej generowanej przez serwer pośredniczący A. Wszelkie pomysły/wskazówki/pomoc byłyby mile widziane!

+0

Uwaga: przykłady XML powyżej są fragmenty z całej wiadomości, oczywiście ten zawiera dużo więcej rzeczy związanych z SOAP ale zostawiłem to się dla zwięzłości. – tmbrggmn

+1

Dlaczego wysłać XSD? Dlaczego po prostu nie użyć "Dodaj odniesienie do usługi"? –

+0

Miałem taką samą reakcję, ale konsultuję się z firmą, a ta firma jest systemem B w mojej historii, więc uniknąłem konfliktu i poszedłem z nim. – tmbrggmn

Odpowiedz

5

W typowym przypadku "zadaj pytanie, rozwiązaj to sam 5 minut później" Udało mi się rozwiązać mój problem.

Problem polegał na tym, że najwyraźniej podczas korzystania z WCF .NET korzysta z domyślnego serializera dla klas zaangażowanych w kontrakt danych. Ten domyślny serializer (chyba DataContractSerializer) najwyraźniej nie pozwala na wiele w konfiguracji.Musiałem powiedzieć WCF, aby użyć XmlSerializer do serializacji wiadomości. Aby to zrobić, musiałem dodać adnotację [XmlSerializerFormat()] do interfejsu umowy serwisowej (podobno ma to również działać na operacjach). Przykład:

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

Po dodaniu [XmlSerializerFormat()] adnotacji, WSDL znacząco (odpowiednie przestrzenie nazw) zmieniła i komunikaty są szeregowane poprawnie.

forum post, który postawił mnie na właściwe tory: http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/c7fede29-56c2-4ff3-bd02-48e3e0b2cec1/

+0

Dzięki za odpowiedź. To rozwiązało mój problem! –

2

(to jest rzeczywiście komentarz, ale nie może się zmieścić)

spróbuj dodać System.Diagnostics do web.config, aby dowiedzieć się więcej informacji na temat błędów:

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

Można zobacz svclog używając C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\SvcTraceViewer.exe (lub podobnego). Dodaj to do obu usług (różne nazwy plików dziennika oczywiście) i zobacz, który z nich się nie powiedzie i dlaczego.

Podejrzewam, że serializacja jest OK, ale niektóre powiązanie/ustawienie usługi powoduje niepowodzenie połączenia.

+0

OK, typowy, ale myślę, że znalazłem rozwiązanie, które wydaje się działać, trzeba zrobić więcej testów, BRB :) – tmbrggmn