2009-03-16 18 views
8

Mamy istniejący interfejs usługi WWW SOAP, który chcemy zaimplementować przy użyciu WCF dla nowej aplikacji. Wydaje się, że działa dobrze, z wyjątkiem jednego małego szczegółu. Przestrzeń nazw XML zwracanego typu funkcji musi być inna niż przestrzeń nazw XML samej usługi WWW. I dla mojego życia, nie mogę zmusić go do działania.Jak dostosować serializację XML WCF

Odtworzyłem ten sam problem z małym przykładowym projektem. Interfejs WCF:

[XmlSerializerFormat] 
[ServiceContract(Namespace = "urn:outer-namespace")] 
public interface IService1 
{ 
    [OperationContract] 
    MyClass DoStuff(int value); 
} 

[Serializable] 
public class MyClass 
{ 
    [XmlElement(ElementName = "DataString")] 
    public string MyString { get; set; } 
} 

Realizacja serwis internetowy:

public class Service1 : IService1 
{ 
    public MyClass DoStuff(int value) 
    { 
     return new MyClass { MyString = "Wooh!" }; 
    } 
} 

Odpowiedź z tym usługa jest następnie szeregowane jako: (pomijając SOAP rzeczy)

<DoStuffResponse xmlns="urn:outer-namespace"> 
    <DoStuffResult> 
     <DataString>Wooh!</DataString> 
    </DoStuffResult> 
    </DoStuffResponse> 

Ale chcemy <DoStuffResult> należy do xmlns = "urn: inner-namespace".

Próbowałem dodać [return: XmlElement (...)] na funkcji interfejsu lub funkcji usługi sieciowej, ale to nie bierze. Również [XmlType] lub [XmlRoot] w definicji klasy MyClass nie działa.

Czy ktoś ma pomysł, jak zmienić spersonalizowaną przestrzeń nazw XML (lub nazwę elementu) obiektu, który jest zwracaną wartością funkcji usługi WWW WCF?

Odpowiedz

3

Definiowanie przestrzeni nazw za pomocą atrybutów XML Serialization (lub, lepiej) Data Contract Contract.

np. z serią XML:

[Serializable, XmlRoot(namespace="http://example.com/eg1")] 
public class MyClass { 
    [XmlElement(ElementName = "DataString")] 
    public string MyString { get; set; } 
} 

np. Dane z abonamentem serializacji:

[DataContract(Namespace="http://example.com/eg2")] 
public class MyClass { 
    [DataMember] 
    public string MyString { get; set; } 
} 

EDIT

na podstawie pierwszego komentarza, powyższe nie zadziała, ponieważ pragnienie jest ustawienie nazw na owinięcia wokół SOAP wiadomości, nie na samej wiadomości.

nie kontroluje przestrzeni nazw i nie widzę żadnych innych atrybutów WCF na poziomie metody.

Dwie możliwości: (1) Możesz mieć wystarczającą kontrolę poprzez obniżenie poziomu abstrakcji i użycie umowy wiadomości. (2) Uzyskaj bieżący plik WSDL dla usługi (używając svcutil.exe), ręcznie dostosowując go, aby uzyskać żądane przestrzenie nazw, a następnie ponownie używając svcutil.exe, aby wygenerować kod i spójrz na wynikowy kod.

+0

Tak jak już wspomniano w pytaniu, próbowałem dodając atrybut XmlRoot i to nie działa. Dodaje tylko przestrzeń nazw do pól w MyClass, ale nie do samej MyClass. DataContract również nie działa, a ja wolę XmlSerializer, ponieważ zmiana nazwy i kolejność nie jest wtedy ważna. –

+0

Użyłem svcutil, ale bez określenia serializera i wygenerowałem kombinację MessageContract i ServiceContract z XmlSerializer. Więc ma jedną lub dwie owijki i wciąż mógłbym używać atrybutów XML, aby wszystko działało. –

1

Po wielu dniach szukania i wypróbowania kilkudziesięciu zalecanych rozwiązań; W końcu udało mi się uzyskać WCF, aby przestać wymuszać nazwę kontenera opakowania dodając Result do nazwy metody usługi sieciowej. Sztuką było dodać następujący atrybut dekorator w interfejsie usługi internetowej:

[return:MessageParameter(Name = "whatIWantItNamed")] 

Ten atrybut powinien być umieszczony/położony bezpośrednio po atrybucie [OperationContract] (i tuż przed metoda rzeczywistej odgałęzienie) w interfejsie.

(Musiałem także dodać atrybut XmlSerializerFormat do wszystkich ServiceContract i OperationContract atrybutów.)

Powiązane problemy