2010-06-11 4 views
5

Dans notre environnement de production, nos services WCF sont sérialisés avec XMLSerializer. Pour ce faire, nos interfaces de service ont l'attribut [XMLSerializerFormat]. Maintenant, nous devons passer à DataContractSerializer mais nous devons rester compatibles avec nos clients existants. Par conséquent, nous devons exposer chaque service avec les deux sérialiseurs.Comment prendre en charge à la fois DataContractSerializer et XMLSerializer pour le même contrat sur le même hôte?

Nous avons une contrainte: nous ne voulons pas redéfinir chaque interface de contrat deux fois, nous avons des interfaces contrat de 50 services et nous ne voulons pas avoir

IIncidentServiceXml 
IIncidentServiceDCS 
IEmployeeServiceXml 
IEmployeeServiceDCS 
IContractServiceXml 
IContractServiceDCS 

Comment pouvons-nous faire cela?


Plus d'info

Voici une description de ce que nous avons essayé jusqu'à présent, mais je suis prêt à essayer des approches complètement différentes:

Nous avons essayé de créer tous les critères d'évaluation par code dans notre propre classe ServiceHostFactory. Fondamentalement, nous créons deux points de terminaison deux fois. Le problème est qu'à l'exécution, WCF se plaint que le service a deux points de terminaison avec le même nom de contact mais avec différentes instances de ContractDescription. Le message indique que nous devrions utiliser différents noms de contrat ou réutiliser la même instance de ContractDescription.

Autre tentative:

Nous avons aussi essayé de le faire en utilisant différents espaces de noms pour chaque instance ContractDescription. De cette façon, nous garderons la même interface contrat (IIncidentService) mais avec deux espaces de noms différents:

http://ourcompany/XML/IIncidentService 
http://ourcompany/DCS/IIncidentService 

Avec que nous avons pu obtenir plus, mais le service est écrasé à une exception bizarre:

An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is: 
System.InvalidOperationException: An exception was thrown in a call to a WSDL export extension: System.ServiceModel.Description.XmlSerializerOperationBehavior 
contract: http://ourcompany.cs/XML:IUserServiceWCF ----> System.NullReferenceException: Object reference not set to an instance of an object. 
    at System.ServiceModel.Description.XmlSerializerMessageContractExporter.ExportFaults(Object state) 
    at System.ServiceModel.Description.MessageContractExporter.ExportMessageContract() 
    at System.ServiceModel.Description.XmlSerializerOperationBehavior.System.ServiceModel.Description.IWsdlExportExtension.ExportContract(WsdlExporter exporter, WsdlContractConversionContext contractContext) 
    at System.ServiceModel.Description.WsdlExporter.CallExtension(WsdlContractConversionContext contractContext, IWsdlExportExtension extension) 

Répondre

1

Court La réponse est, vous ne pouvez pas, pour exactement la raison de votre message d'erreur, vous ne pouvez pas avoir trop de points de terminaison avec le même nom que vous essayez de faire. Je pense que vous devrez faire exactement ce que vous dites que vous ne voulez pas.

This might be your only option

Le problème est que de spécifier un service est d'utiliser le XmlSerializer vous devez déclarer le [XmlSerializerFormat] attribut sur le service ou le contrat. Eh bien depuis nous voulons utiliser le même pour les deux points de terminaison nous ne pouvons pas le placer là, donc il nous reste à placer sur le contrat . Cependant, quand il se résume à lui, les deux points d'extrémité utilisent le même service et vice versa le même contrat droit?

Eh bien, il ne doit pas en être ainsi. Vous pourrait avoir un contrat A dériver de contrat B, alors avoir le service mettre en œuvre le contrat A tel que tout dans les deux contrats est partie du service.Pour cet exemple cependant, le contrat B sera notre contrat standard , et le contrat A sera une interface qui définit simplement l'attribut [XmlSerializerFormat].

Mais je ne peux pas vous promettre que cela fonctionnera avec le code de vos clients existants sans modifications.

+0

J'ai mis à jour ma question ci-dessus avec une autre tentative – Sylvain

0

Qu'en est-il de deux services mettant en œuvre le même contrat?

Comme:

class DcsService : Service 
{} 

[XmlSerializerFormat] 
class XmlService : Service 
{} 

class Service : IServiceContract 
{} 

jamais travaillé avec XmlSerializer mais nous avons utilisé cette construction à d'autres fins.

1

Créez simplement votre objet en utilisant les balises [DataContract] et [DataMember]. XmlSerializer et DataContractSerializer vont à la fois sérialiser l'objet. Ils ont mis à jour XmlSerializer dans la structure 3.0 pour gérer la sérialisation des contrats de données. DataContractSerializer peut gérer les objets [Serializable] mais le comportement n'est pas exact et nécessite quelques modifications.

Créez simplement tous vos objets à l'aide de contrats de données. De cette façon, vous n'avez pas à vous soucier de faire deux appels (un pour chaque). Vous pouvez utiliser XmlSerializer ou DataContractSerializer sans problèmes.

Si vous souhaitez ajouter des attributs de comportement, vous pouvez toujours ajouter à la fois [Serializable] et [DataContract] si vous le souhaitez.

[Serializable] 
[DataContract] 
public class Customer 

{ 
    [DataMember] 
    public int Age { get; set; } 

    [DataMember] 
    public string Name { get; set; } 

    [DataMember] 
    public int Number { get; set; } 

    [DataMember] 
    public string FullName { get; set; } 

    [XmlIgnore] 
    public int IgnoredNumber { get; set; } 
} 

XmlSerializer sérialise comme:

<?xml version="1.0" encoding="utf-16" ?> 
<Customer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Age>88</Age> 
    <Name>Bob</Name> 
    <Number>808</Number> 
    <FullName>Bob Jones</FullName> 
    </Customer> 

sérialisés DataContractSerializer comme:

<?xml version="1.0" encoding="utf-8" ?> 
<Customer xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/ConsoleApplication1"> 
    <Age>88</Age> 
    <FullName>Bob Jones</FullName> 
    <Name>Bob</Name> 
    <Number>808</Number> 
    </Customer> 

Vous pouvez évidemment forcer le Namespace afin qu'ils correspondent exactement à la fois. Ceci est juste à titre d'exemple.

Questions connexes