web-dev-qa-db-fra.com

Parfois, l'ajout d'une référence de service WCF génère un fichier reference.cs vide

Parfois, l'ajout d'une référence de service WCF génère un fichier reference.cs vide et je ne peux pas faire référence au service nulle part dans le projet.

Quelqu'un at-il rencontré cela?

151
Matt

En général, j’ai trouvé qu’il s’agissait d’un problème de génération de code et que la plupart du temps, c’est parce que j’ai un conflit de noms de types qu’il ne pouvait pas résoudre.

Si vous cliquez avec le bouton droit de la souris sur votre référence de service, cliquez sur Configurer, puis sur décochez "Réutiliser les types dans les assemblages référencés" cela résoudra probablement le problème.

Si vous utilisiez certains aspects de cette fonctionnalité, vous devrez peut-être vous assurer que vos noms sont nettoyés.

367
Anderson Imes

Comme le souligne la réponse acceptée, un problème de référence de type lors de la réutilisation de types est probablement le coupable. J'ai constaté que, lorsque vous ne parveniez pas à déterminer facilement le problème, utiliser la ligne de commande svcutil.exe vous aidera à révéler le problème sous-jacent (comme le souligne John Saunders).

Voici un exemple rapide d'utilisation de svcutil à titre d'amélioration.

svcutil /t:code https://secure.myserver.com/services/MyService.svc /d:test /r:"C:\MyCode\MyAssembly\bin\debug\MyAssembly.dll"

Où:

  • / t: code génère le code à partir de l'URL donnée
  • / d: pour spécifier le répertoire pour la sortie
  • / r: pour spécifier une assemblée de référence

Référence complète de la ligne de commande svcutil ici: http://msdn.Microsoft.com/en-us/library/aa347733.aspx

Une fois que vous avez exécuté svcutil, vous devriez voir l’exception levée par l’importation. Vous pouvez recevoir ce type de message concernant l’un de vos types: "le type référencé ne peut pas être utilisé car il ne correspond pas à DataContract importé".

Cela pourrait simplement être spécifié en ce sens qu'il existe une différence entre l'un des types de l'assembly référencé et celle générée dans le DataContract pour le service. Dans mon cas, le service que j'importais avait des types plus récents et mis à jour par rapport à ceux que j'avais dans l'Assemblée partagée. Cela n’était pas évident car le type mentionné dans l’exception semblait être le même. Ce qui était différent était l'un des types complexes imbriqués utilisés par le type.

Il existe d'autres scénarios plus complexes pouvant déclencher ce type d'exception et les références vide.cs résultantes. Voici un exemple .

Si vous rencontrez ce problème et que vous n'utilisez pas de types génériques dans vos contrats de données ni avec IsReference = true, je vous recommande de vérifier avec certitude que vos types partagés sont exactement les mêmes sur votre client et votre serveur. Sinon, vous rencontrerez probablement ce problème.

36
dblood

Je me suis cogné la tête pendant une journée entière avec ce problème précis. Je viens de le réparer. Voici comment...

Le service devait fonctionner sous SSL (c'est-à-dire à https://mydomain.com/MyService.svc )

L'ajout d'une référence de service au service WCF sur un serveur de développement a parfaitement fonctionné.

Le déploiement de la même version du service WCF sur le serveur de production réel exact, puis le basculement vers l'application cliente et la configuration de la référence de service pour pointer vers le service réel ne présentaient aucune erreur, mais l'application ne se créait pas que le fichier Reference.cs de la référence de service était complètement vide! La mise à jour de la référence de service ne faisait aucune différence. Nettoyer la solution n'a pas aidé. Le redémarrage de VS2010 n'a fait aucune différence. Créer une nouvelle solution vierge, démarrer un projet de console et ajouter une référence de service au service réel posait exactement le même problème.

Je ne pensais pas que c'était dû à des types en conflit ou à quoi que ce soit, mais bon sang - j'ai reconfiguré la référence du service WCF en décochant "Réutiliser les types dans tous les assemblys référencés". Pas de joie; Je remets la coche.

L'étape suivante consistait à essayer svcutil sur l'URL de référence pour voir si cela aiderait à résoudre le problème. Voici la commande: 

svcutil /t:code https://mydomain.com/MyService.svc /d:D:\test

Cela a donné les résultats suivants:

Microsoft (R) Service Model Metadata Tool
[Microsoft (R) Windows (R) Communication Foundation, Version 4.0.30319.1]
Copyright (c) Microsoft Corporation.  All rights reserved.

Attempting to download metadata from 'https://mydomain.com/MyService.svc' using WS-Metadata Exchange or DISCO.
Error: Cannot import wsdl:portType
Detail: An exception was thrown while running a WSDL import extension: System.ServiceModel.Description.DataContractSerializerMessageContractImporter
Error: Schema with target namespace 'http://mynamespace.com//' could not be found.
XPath to Error Source: //wsdl:definitions[@targetNamespace='http://mynamespace.com//']/wsdl:portType[@name='IMyService']


Error: Cannot import wsdl:binding
Detail: There was an error importing a wsdl:portType that the wsdl:binding is dependent on.
XPath to wsdl:portType: //wsdl:definitions[@targetNamespace='http://mynamespace.com//']/wsdl:portType[@name='IMyService']
XPath to Error Source: //wsdl:definitions[@targetNamespace='http://tempuri.org/']/wsdl:binding[@name='WSHttpBinding_IMyService']


Error: Cannot import wsdl:port
Detail: There was an error importing a wsdl:binding that the wsdl:port is dependent on.
XPath to wsdl:binding: //wsdl:definitions[@targetNamespace='http://tempuri.org/']/wsdl:binding[@name='WSHttpBinding_IMyService']
XPath to Error Source: //wsdl:definitions[@targetNamespace='http://tempuri.org/']/wsdl:service[@name='MyService']/wsdl:port[@name='WSHttpBinding_IMyService']


Generating files...
Warning: No code was generated.
If you were trying to generate a client, this could be because the metadata documents did not contain any valid contracts or services
or because all contracts/services were discovered to exist in /reference assemblies. Verify that you passed all the metadata documents to the tool.

Warning: If you would like to generate data contracts from schemas make sure to use the /dataContractOnly option.

Cela m'a complètement bouleversé. En dépit de la lourdeur des recherches sur Google et du fait que je me crois vraiment assez rétrograde, et que je repense à une carrière de chauffeur de bus, j’ai enfin réfléchi au pourquoi cela fonctionnait bien sur le boîtier de développement. Pourrait-il s'agir d'un problème de configuration IIS?

J'ai transféré simultanément dans les boîtes de développement et de production simultanément et, dans chaque cas, j'ai lancé le gestionnaire IIS (exécutant IIS 7.5). Ensuite, je suis passé en revue chaque paramètre de configuration sur chaque boîte, en comparant les valeurs sur chaque serveur.

Et puis, il y a le problème: sous "Paramètres SSL" pour le site, assurez-vous que "Requérir SSL" est coché, puis cochez la case d'option "Certificats clients" pour "Accepter". Problème résolu!

11
Matt Kane

Lorsque cela se produit, consultez la fenêtre Erreurs et la fenêtre Sortie pour voir s'il existe des messages d'erreur. Si cela ne vous aide pas, essayez d'exécuter svcutil.exe manuellement et voyez s'il y a des messages d'erreur.

9
John Saunders

J'ai constaté que cela se produisait souvent à chaque fois que j'ajoutais une référence, que je la supprimais puis que je rajoutais un service du même nom. Les conflits de types semblent être dus aux anciens fichiers qui restent quelque part que Visual Studio peut toujours voir. Tout ce que j'ai à faire pour résoudre ce problème, c'est un nettoyage avant d'ajouter la nouvelle référence.

  1. Supprimez la référence de service ayant des problèmes.
  2. Cliquez sur le nom du projet dans l'Explorateur de solutions pour mettre le projet en surbrillance.
  3. Cliquez avec le bouton droit sur la référence du projet.
  4. En haut de la liste de contextes, cliquez sur l’élément Nettoyer .
  5. Ajoutez votre référence de service comme vous le feriez normalement.

J'espère que cela t'aides.

4
user1353936

J'ai eu ce problème avec un Silverlight 5 mis à jour à partir d'une version précédente.

Même en rajoutant la référence de service, cela me donnait encore un Reference.cs vide.

J'ai fini par devoir créer un nouveau projet et recréer la référence de service . C'est quelque chose à essayer si vous avez passé plus d'une demi-heure à ce sujet. Même si vous êtes déterminé à résoudre le projet d'origine, vous pouvez essayer ceci uniquement pour voir ce qui se passe, puis revenir en arrière pour tenter de résoudre le problème.

Je n'ai jamais compris exactement quel était le problème - mais il est possible que quelque chose dans le fichier .csproj n'ait pas été mis à niveau ou qu'un paramètre ne fonctionne pas correctement.

3
Simon_Weaver

Si vous avez récemment ajouté une collection à votre projet lorsque cela a commencé à se produire, le problème peut être causé par deux collections qui ont le même CollectionDataContract attribut:

[CollectionDataContract(Name="AItems", ItemName="A")]
public class CollectionA : List<A> { }

[CollectionDataContract(Name="AItems", ItemName="A")]  // Wrong
public class CollectionB : List<B> { }

J'ai corrigé l'erreur en parcourant mon projet et en veillant à ce que chaque attribut Name et ItemName soit unique:

[CollectionDataContract(Name="AItems", ItemName="A")]
public class CollectionA : List<A> { }

[CollectionDataContract(Name="BItems", ItemName="B")]  // Corrected
public class CollectionB : List<B> { }

Ensuite, j'ai actualisé la référence de service et tout a fonctionné à nouveau. 

1
Jon Person

La technique qui a fonctionné pour moi dans mon cas, après avoir lu ces réponses en vain, consistait simplement à commenter l'intégralité de mon contrat, et à supprimer les éléments de commentaire jusqu'à ce que cela ne fonctionne plus, en mode de recherche binaire. Cela réduit le peu de code incriminé.

Ensuite, vous devez juste deviner ce qui ne va pas avec ce code.

Un retour d’erreur dans l’outil aurait bien sûr été utile.

J'écris un contrat de service Web. J'ai eu un enum de placeholder sans membres. C'est bon. Mais si je l'utilise dans une propriété d'une autre classe et que je réutilise la dll du contrat sur le client, le codegen explose sans message d'erreur. Exécuter svcutil.exe n'a pas aidé, il n'a pas réussi à générer un fichier cs sans préciser pourquoi.

1
JoshuaLawrence

Ce qui suit n'est pas répertorié ici, et c'était la solution que j'ai adoptée (SvcUtils était utile pour voir le message d'erreur. Cependant, l'erreur que j'ai eu était wrapper type message cannot be projected as a data contract type since it has multiple namespaces. Cela signifie que j'ai suivi cette piste et que j'ai appris wsdl.exe via this post).

Dans mon cas, exécuter simplement wsdl [my-asmx-service-address] a généré un fichier .cs sans problème que j'ai inclus dans mon projet et instancié pour utiliser le service.

1
Veverke

Mon problème était que j'ai laissé le "mex" à la fin de mon lien de service Web.

Au lieu de " http://yeagertech.com/yeagerte/YeagerTechWcfService.YeagerTechWcfService.svc/mex "

Utilisez " http://yeagertech.com/yeagerte/YeagerTechWcfService.YeagerTechWcfService.svc "

1
sagesky36

Dans mon cas, j'avais une solution avec le projet VB Web Forms qui faisait référence à un contrôle utilisateur C #. Le projet VB et le projet CS comportaient tous deux une référence de service au même service. La référence apparaît sous Références de service dans le projet VB et sous le groupe Services connectés dans le projet CS (framework).

Afin de mettre à jour la référence de service (c'est-à-dire d'obtenir que le fichier Reference.vb ne soit pas vide) dans le projet de formulaires Web VB, j'avais besoin de RETIRER LE PROJET CS, puis de mettre à jour le fichier VB Référence de service, puis rajoutez le projet CS dans la solution.

0
INFOequipt

En essayant de résoudre ce problème avec svcutil, j'ai reçu l'erreur mentionnée dans la réponse de dblood ("le type référencé ne peut pas être utilisé car il ne correspond pas à DataContract importé").

Dans mon cas, la cause sous-jacente semblait être un type enum ayant l'attribut DataContract, mais dont les membres n'étaient pas marqués avec l'attribut EnumMember. La classe de problèmes svcutil pointée avait une propriété de ce type enum.

Cela irait mieux comme commentaire à la réponse de dblood, mais pas assez de représentants pour ça ...

0
Platedslicer

J'ai également eu le problème des références de service brisées lorsque je travaillais avec des références de projet des deux côtés (le projet de service et le projet faisant référence au service). Si la .dll du projet référencé, par exemple, s'appelle "Contoso.Development.Common", mais que le nom du projet est simplement abrégé en "Commun", les références de projet à ce projet s'appellent simplement "Commun". Le service attend cependant une référence à "Contoso.Development.Common" pour résoudre les classes (si cette option est activée dans les options de référence du service).

Donc, avec Explorer, j'ai ouvert le dossier du projet qui référence le service et le projet "Common". Là, je modifie le fichier de projet VS (.csproj) avec le bloc-notes. Recherchez le nom du projet référencé ("Common.csproj" dans cet exemple) et vous trouverez rapidement l'entrée de configuration représentant la référence du projet.

J'ai changé 

<ProjectReference Include="..\Common\Common.csproj"> <Project>{C90AAD45-6857-4F83-BD1D-4772ED50D44C}</Project> <Name>Common</Name> </ProjectReference>

à

<ProjectReference Include="..\Common\Common.csproj"> <Project>{C90AAD45-6857-4F83-BD1D-4772ED50D44C}</Project> <Name>Contoso.Development.Common</Name> </ProjectReference>

L'important est de changer le nom de la référence en nom de la DLL du projet référencé.

Revenez ensuite à VS. Là, il vous sera demandé de recharger le projet car il a été modifié en dehors de VS. Cliquez sur le bouton de rechargement.

Après cela, l’ajout et la mise à jour de la référence de service ont fonctionné comme prévu.

J'espère que cela aide aussi quelqu'un d'autre.

Cordialement.

0
Martin Jesch

Merci à John Saunders post ci-dessus qui m'a donné une idée de regarder dans la fenêtre d'erreur. Je passais toute la journée dans la poche et je cherchais une erreur dans la fenêtre de sortie. 

Dans mon cas, le coupable était ISerializable. J'ai une classe DataContract avec la propriété DataMember du type Exception. Vous ne pouvez avoir aucun DataMember de type ayant le mot clé ISerializable. Dans cette exception a ISerializable dès que je l'ai enlevé tout a fonctionné comme un charme. 

0
Ziggler

Comme @dblood le souligne, le problème principal réside dans DataContractSerializer, qui ne réutilise pas correctement les types. Il y a déjà quelques réponses ici donc je vais commencer par ajouter quelques avantages et inconvénients à ce sujet:

  • L'indicateur 'IsReference' pose beaucoup de problèmes, mais le supprimer n'est pas toujours la solution (en particulier dans les situations de récursion). 
  • Le problème sous-jacent est que le contrat de données n’est en quelque sorte pas le même que les noms de types, même s’ils le sont parfois (hein? Oui, vous avez bien lu!). Apparemment, le sérialiseur est assez difficile et il est très difficile de trouver le vrai problème.
  • La suppression des "vérifications de références" de la "Configuration de la référence de service" fonctionne, mais vous laisse avec plusieurs implémentations. Cependant, je réutilise souvent les interfaces SOAP sur des DLL. De plus, dans la plupart des SOA matures que je connais, plusieurs interfaces de services implémentent et étendent les mêmes classes d'interfaces. Si vous supprimez les contrôles «Utiliser les types référencés», vous ne pourrez plus simplement transmettre des objets.

Heureusement, si vous contrôlez votre service, il existe une solution simple qui résout tous ces problèmes. Cela signifie que vous pouvez toujours réutiliser des interfaces de service sur plusieurs DLL, ce qui est essentiel pour une solution appropriée. Voici comment fonctionne la solution:

  1. Créez une DLL d'interface séparée. Dans cette DLL, incluez tous les DataContract et ServiceContract; mettez ServiceContract sur vos interfaces.
  2. Dérivez l'implémentation du serveur à partir de l'interface.
  3. Utilisez le même DLL pour construire le client en utilisant votre méthode préférée. Par exemple (IMyInterface est l'interface du contrat de service):

    var httpBinding = new BasicHttpBinding();
    var identity = new DnsEndpointIdentity("");
    var address = new EndpointAddress(url, identity, new AddressHeaderCollection());
    var channel = new ChannelFactory<IMyInterface>(httpBinding, address);
    return channel.CreateChannel();
    

En d'autres termes: N'utilisez pas la fonctionnalité 'ajouter une référence de service' , mais forcez WCF à utiliser les types de services (corrects) en contournant la génération de proxy. Après tout, vous avez déjà ces cours.

Avantages:

  1. Vous contournez le processus svcutil.exe, ce qui signifie que vous n'avez pas de problème IsReference
  2. Les types et noms de DataContract sont corrects par définition; Après tout, le serveur et le client utilisent la même définition.
  3. Si vous étendez l'API ou utilisez des types provenant d'une autre DLL, (1) et (2) sont toujours valables, vous ne rencontrerez donc aucun problème.

Les inconvénients: 

  1. Les méthodes A-sync sont difficiles, car vous ne générez pas de proxy a-sync. Par conséquent, je ne recommanderais pas cela dans les applications Silverlight.
0
atlaste

J'ai rencontré un problème similaire hier lors du développement. J'ai découvert que j'utilisais le même espace de noms dans 2 versions différentes de contrats. 

Nous avons 2 versions de contrats, par exemple version4 et version5. J'ai copié tous les contrats de version4 et renommé tout l'espace de noms de version4 en version5. Ce faisant, j'ai oublié de renommer l'espace de noms de v4 à v5 dans l'un des fichiers. En raison d'un conflit d'espace de noms, le fichier Reference.cs était vide.

Ce problème est difficile à résoudre car vous ne recevez aucun message d'erreur lors de la génération de la référence de service. Pour identifier ce problème, je validerais manuellement tous les nouveaux fichiers que j'avais créés. Il existe d'autres moyens de résoudre ce problème. C’est la première étape à suivre avant d’opter pour d’autres options.

0
arif.khan.b