2009-03-16 10 views
8

Nous avons une interface de service Web SOAP existante que nous voulons implémenter en utilisant WCF pour une nouvelle application. Cela semble fonctionner correctement, sauf pour un petit détail. L'espace de noms XML du type de retour d'une fonction doit être différent de l'espace de noms XML du service Web lui-même. Et pour la vie de moi, je ne peux pas le faire fonctionner.Comment personnaliser la sérialisation XML WCF

J'ai recréé le même problème avec un petit projet d'exemple. L'interface 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; } 
} 

La mise en œuvre de services Web:

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

Une réponse de ce Webservice est alors sérialisé comme: (Omettre choses SOAP)

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

Mais nous voulons le <DoStuffResult> être de xmlns = "urn: inner-namespace".

J'ai essayé d'ajouter un [return: XmlElement (...)] sur la fonction d'interface ou la fonction de service Web, mais cela ne fonctionne pas. Un [XmlType] ou [XmlRoot] sur la définition de classe MyClass ne fonctionne pas non plus.

Est-ce que quelqu'un a une idée sur la façon de changer l'espace de noms XML sérialisé (ou le nom de l'élément) de l'objet qui est la valeur de retour d'une fonction de service Web WCF?

Répondre

3

Définissez des espaces de noms avec les attributs de définition de contrat de données Sérialisation XML (ou mieux).

par exemple. avec sérialisation XML:

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

par exemple. avec sérialisation contrat de données:

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

EDIT

Basé sur le premier commentaire, la volonté fonctionne pas, parce que le désir est de définir l'espace de noms sur l'emballage SOAP autour du message, non sur le message lui-même.

OperationContractAttribute n'offre aucun contrôle sur les espaces de noms et je ne vois aucun autre attribut WCF au niveau d'une méthode. Deux possibilités: (1) Vous pouvez avoir assez de contrôle en supprimant un niveau d'abstraction et en utilisant un contrat de message. (2) Obtenez le WSDL en cours pour le service (en utilisant svcutil.exe), en l'ajustant manuellement pour obtenir les espaces de noms souhaités, puis en utilisant à nouveau svcutil.exe pour générer le code et examinez le code résultant. Après des jours de recherche et d'essai, des douzaines de solutions recommandées;

+0

Comme je l'ai déjà dit dans la question, je l'ai essayé d'ajouter un attribut XmlRoot et cela n'a pas fonctionné. Il ajoute seulement l'espace de noms aux champs dans MyClass, mais pas à MyClass lui-même. Le DataContract ne fonctionne pas non plus, et je préfère le XmlSerializer à cause du renommage et l'ordre n'est pas important alors. –

+0

J'ai utilisé svcutil, mais sans spécifier un sérialiseur et il a généré une combinaison de MessageContract et ServiceContract avec XmlSerializer. Donc, il a un ou deux wrappers et je pourrais toujours utiliser les attributs XML pour que tout fonctionne. –

1

J'ai finalement réussi à obtenir que WCF cesse de forcer un nom de conteneur wrapper à ajouter Result au nom de la méthode de service Web. L'astuce est d'ajouter l'attribut décorateur suivant à l'interface de service Web:

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

Cet attribut doit être placé/situé directement après l'attribut [OperationContract] (et juste avant le talon de la méthode réelle) dans l'interface.

(je aussi besoin d'ajouter un attribut XmlSerializerFormat à tous les attributs ServiceContract et OperationContract.)

Questions connexes