web-dev-qa-db-de.com

Beim Hinzufügen einer WCF-Dienstreferenz wird manchmal eine leere reference.cs generiert

Beim Hinzufügen einer WCF-Dienstreferenz wird manchmal eine leere reference.cs generiert, und ich kann auf den Dienst an keiner Stelle im Projekt verweisen.

Hat jemand das gesehen?

151
Matt

Im Allgemeinen finde ich, dass es sich um ein Problem mit der Codegeneration handelt und am meisten der Zeit, weil ich einen Typnamenskonflikt habe, den ich nicht lösen konnte.

Wenn Sie mit der rechten Maustaste auf Ihre Dienstreferenz klicken und auf Konfigurieren und Deaktivieren"Typen in referenzierten Assemblys wiederverwenden" klicken, wird das Problem wahrscheinlich gelöst.

Wenn Sie einen Aspekt dieser Funktion verwendet haben, müssen Sie möglicherweise sicherstellen, dass Ihre Namen bereinigt werden.

367
Anderson Imes

Wie die akzeptierte Antwort darauf hinweist, ist ein Typ-Referenz-Problem bei der Wiederverwendung von Typen wahrscheinlich der Täter. Ich fand, wenn Sie das Problem nicht leicht feststellen können, dann hilft Ihnen die Verwendung der Befehlszeile "svcutil.exe", das zugrunde liegende Problem aufzudecken (wie John Saunders feststellt).

Als eine Verbesserung ist hier ein schnelles Beispiel für die Verwendung von svcutil.

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

Woher:

  • / t: code generiert den Code aus der angegebenen URL
  • / d: um das Verzeichnis für die Ausgabe anzugeben
  • / r: um eine Referenzbaugruppe anzugeben

Vollständige svcutil-Befehlszeilenreferenz hier: http://msdn.Microsoft.com/en-us/library/aa347733.aspx

Wenn Sie svcutil ausführen, sollte die Ausnahme durch den Import ausgelöst werden. Möglicherweise erhalten Sie diese Art von Nachricht zu einem Ihrer Typen: "Der referenzierte Typ kann nicht verwendet werden, da er nicht mit dem importierten DataContract übereinstimmt".

Dies kann einfach so angegeben werden, dass in einem der Typen in der referenzierten Assembly ein Unterschied besteht zu dem, was in DataContract für den Service generiert wurde. In meinem Fall hatte der Dienst, den ich importierte, neuere, aktualisierte Typen als ich in der gemeinsam genutzten Assembly. Dies war nicht ohne weiteres ersichtlich, da der in der Ausnahme erwähnte Typ derselbe war. Der Unterschied war einer der verschachtelten komplexen Typen, die vom Typ verwendet wurden.

Es gibt andere komplexere Szenarien, die diese Art von Ausnahme und die daraus resultierenden leeren reference.cs auslösen können. Hier ist ein Beispiel .

Wenn dieses Problem auftritt und Sie keine generischen Typen in Ihren Datenverträgen verwenden oder IsReference = true verwenden, empfehle ich Ihnen zu überprüfen, ob Ihre gemeinsam genutzten Typen auf Ihrem Client und Ihrem Server identisch sind. Andernfalls werden Sie wahrscheinlich auf dieses Problem stoßen.

36
dblood

Ich habe mit diesem Problem einen ganzen Tag lang den Kopf geschlagen. Ich habe es gerade behoben. Hier ist wie...

Der Dienst hatte zur Ausführung über SSL (d. H. Um https://mydomain.com/MyService.svc ).

Das Hinzufügen einer Dienstreferenz zum WCF-Dienst auf einem Entwicklungsserver hat gut funktioniert.

Das Bereitstellen des gleichen Builds des WCF-Dienstes exact auf dem Live-Produktionsserver, das Wechseln zur Clientanwendung und das Konfigurieren der Dienstreferenz zum Verweisen auf den Live-Dienst zeigten keine Fehler, aber die App konnte nicht erstellt werden: dass die Reference.cs-Datei der Dienstreferenz vollständig leer war! Das Aktualisieren der Servicereferenz machte keinen Unterschied. Das Reinigen der Lösung hat nicht geholfen. Der Neustart von VS2010 machte keinen Unterschied. Das Erstellen einer neuen leeren Lösung, das Starten eines Konsolenprojekts und das Hinzufügen einer Servicereferenz zum Live-Service hatten genau das gleiche Problem.

Ich dachte nicht, dass dies auf widersprüchliche Typen oder irgendetwas zurückzuführen war, aber zum Teufel - ich habe die WCF-Dienstreferenz neu konfiguriert, indem Sie die Option "Typen in allen referenzierten Baugruppen wiederverwenden" deaktivieren. Keine Freude; Ich setze den Haken zurück.

Der nächste Schritt bestand darin, svcutil mit der Referenz-URL zu testen, um zu sehen, ob dies helfen könnte, das Problem aufzudecken. Hier ist der Befehl: 

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

Dies ergab folgendes:

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.

Das hatte mich völlig verkümmert. Trotz des heftigen Googlings und einer ziemlich verärgerten Haltung und einer Überprüfung der Karriere als Busfahrer überlegte ich schließlich, warum es in der Entwicklungsbox gut funktioniert hat. Könnte es ein IIS -Konfigurationsproblem sein?

Ich habe gleichzeitig in die Entwicklungsbox und in die Live-Box Remoted, und auf jeder habe ich den IIS Manager gestartet (mit IIS 7.5). Als Nächstes ging ich jede Konfigurationseinstellung auf jeder Box durch und verglich die Werte auf jedem Server.

Und es gibt das Problem: Stellen Sie unter "SSL-Einstellungen" für die Site sicher, dass "SSL erforderlich" aktiviert ist, und aktivieren Sie das Optionsfeld "Client-Zertifikate" auf "Akzeptieren". Problem gelöst!

11
Matt Kane

Wenn dies passiert, schauen Sie im Fehlerfenster und im Ausgabefenster nach, ob Fehlermeldungen angezeigt werden. Wenn dies nicht hilft, führen Sie svcutil.exe manuell aus und prüfen Sie, ob Fehlermeldungen angezeigt werden.

9
John Saunders

Ich habe festgestellt, dass dies häufig vorkommt, wenn ich einen Verweis hinzufüge, es entferne und dann einen Dienst mit demselben Namen erneut hinzufüge. Die Typkonflikte scheinen darauf zurückzuführen zu sein, dass die alten Dateien an einem Ort verbleiben, den Visual Studio noch sehen kann. Alles, was ich tun muss, um es zu beheben, ist ein Bereinigen, bevor die neue Referenz hinzugefügt wird.

  1. Entfernen Sie die Dienstreferenz mit Problemen.
  2. Klicken Sie im Solution Explorer auf den Projektnamen, um das Projekt zu markieren.
  3. Klicken Sie mit der rechten Maustaste auf die Projektreferenz.
  4. Klicken Sie oben in der Kontextliste auf das Element Clean .
  5. Fügen Sie Ihre Servicereferenz wie gewohnt hinzu.

Hoffe das hilft.

4
user1353936

Ich hatte dieses Problem mit einem Silverlight 5, das von einer früheren Version aktualisiert wurde.

Selbst das Hinzufügen der Dienstreferenz gab mir immer noch eine leere Reference.cs

Am Ende musste ich ein brandneues Projekt erstellen und die Service-Referenz neu erstellen. Dies ist etwas, was Sie ausprobieren sollten, wenn Sie mehr als eine halbe Stunde damit verbracht haben. Selbst wenn Sie das ursprüngliche Projekt reparieren möchten, können Sie dies einfach ausprobieren, um zu sehen, was passiert, und dann rückwärts zu arbeiten, um das Problem zu beheben.

Ich habe nie genau herausgefunden, was das Problem war - aber möglicherweise wurde etwas in der .csproj-Datei nicht aktualisiert oder eine Einstellung ist schief gegangen.

3
Simon_Weaver

Wenn Sie kürzlich zu Ihrem Projekt eine Sammlung hinzugefügt haben, als dies auftrat, kann das Problem durch zwei Sammlungen verursacht werden, die dasselbe CollectionDataContract -Attribut haben:

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

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

Ich habe den Fehler behoben, indem ich mein Projekt durchgegangen bin und sichergestellt habe, dass jedes Name und ItemName - Attribut eindeutig ist:

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

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

Dann habe ich die Servicereferenz aktualisiert und alles hat wieder funktioniert. 

1
Jon Person

Die Technik, die für mich in meinem Fall funktionierte, nachdem ich diese Antworten erfolglos gelesen hatte, bestand einfach darin, alle meine Verträge auszukommentieren und die unkommentierten Bits auf eine binäre Suchmethode zu setzen, bis sie nicht mehr funktioniert. Dadurch wird das störende Codebeispiel eingegrenzt.

Dann müssen Sie nur raten, was mit diesem Code nicht stimmt.

Einige Fehlerrückmeldungen im Tool hätten natürlich geholfen.

Ich schreibe einen Webservicevertrag. Ich hatte eine Platzhalteraufzählung ohne Mitglieder. Kein Problem. Wenn ich es jedoch in einer Eigenschaft einer anderen Klasse verwende und die Vertrags-DLL auf dem Client erneut verwende, explodiert der Codegen ohne Fehlermeldung. Das Ausführen von "svcutil.exe" hat nicht geholfen, es ist einfach nicht gelungen, eine CS-Datei auszugeben, ohne zu erwähnen, warum.

1
JoshuaLawrence

Das Folgende ist hier nicht aufgeführt, und es war die Lösung, die ich gewählt habe (SvcUtils war hilfreich, um die Fehlermeldung anzuzeigen. Der Fehler, den ich erhielt, war jedoch wrapper type message cannot be projected as a data contract type since it has multiple namespaces. Das heißt, ich folgte dieser Spur und lernte wsdl.exe über this post).

In meinem Fall wurde durch das Ausführen von wsdl [meine-asmx-service-address] eine problemlose .cs-Datei generiert, die ich in mein Projekt aufgenommen und die Verwendung des Dienstes veranlasst habe.

1
Veverke

Mein Problem war, dass ich das "mex" am Ende meines Webservice-Links belassen habe.

Anstelle von " http://yeagertech.com/yeagerte/YeagerTechWcfService.YeagerTechWcfService.svc/mex "

Verwenden Sie " http://yeagertech.com/yeagerte/YeagerTechWcfService.YeagerTechWcfService.svc "

1
sagesky36

In meinem Fall hatte ich eine Lösung mit VB Web Forms-Projekt, die auf ein C # -UserControl verwies. Sowohl das Projekt VB als auch das CS-Projekt hatten eine Dienstreferenz für denselben Dienst. Die Referenz wurde unter Dienstreferenzen im Projekt VB und unter der Gruppierung Connected Services im CS-Projekt (Framework) angezeigt.

Um die Dienstreferenz im Webformularprojekt VB zu aktualisieren (dh die Datei "Reference.vb" darf nicht leer sein), musste das CS-PROJEKT ENTFERNT und anschließend die Dienstreferenz VB aktualisiert werden Fügen Sie dann das CS-Projekt wieder in die Projektmappe ein.

0
INFOequipt

Beim Versuch, dieses Problem mit svcutil zu beheben, habe ich den in dbloods Antwort genannten Fehler erhalten ("referenzierter Typ kann nicht verwendet werden, da er nicht mit importiertem DataContract übereinstimmt").

In meinem Fall schien die zugrunde liegende Ursache ein Aufzählungstyp zu sein, der das DataContract-Attribut hatte, dessen Mitglieder jedoch nicht mit dem EnumMember-Attribut gekennzeichnet waren. Die Problemklasse svcutil hatte eine Eigenschaft mit diesem Aufzählungstyp.

Dies würde besser als Kommentar zu dbloods Antwort passen, aber nicht genug Wiederholungen dafür ...

0
Platedslicer

Ich hatte auch das Problem defekter Servicereferenzen, wenn auf beiden Seiten mit Projektreferenzen gearbeitet wurde (das Serviceprojekt und das Projekt, das auf den Service verweist). Wenn die .dll des referenzierten Projekts beispielsweise "Contoso.Development.Common" heißt, der Projektname jedoch einfach auf "Common" gekürzt wird, heißen Projektverweise auf dieses Projekt nur "Common". Der Dienst erwartet jedoch einen Verweis auf "Contoso.Development.Common" zum Auflösen von Klassen (wenn diese Option in den Dienstreferenzoptionen aktiviert ist).

Also habe ich mit Explorer den Ordner des Projekts geöffnet, der auf den Dienst und das "Common" -Projekt verweist. Dort bearbeite ich die VS-Projektdatei (.csproj) mit dem Editor. Suchen Sie nach dem Namen des referierten Projekts (in diesem Beispiel "Common.csproj"), und Sie finden schnell den Konfigurationseintrag, der die Projektreferenz darstellt.

Ich habe mich verändert 

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

zu

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

Wichtig ist, den Namen der Referenz in den Namen der DLL zu ändern, die das referenzierte Projekt als Ausgabe hat.

Dann zurück zu VS wechseln. Dort werden Sie aufgefordert, das Projekt neu zu laden, da es außerhalb von VS geändert wurde. Klicken Sie auf die Schaltfläche zum erneuten Laden.

Nach dem Hinzufügen und Aktualisieren funktionierte die Servicereferenz wie erwartet.

Hoffe das hilft auch jemand anderem.

GrüßeMH

0
Martin Jesch

Danke an John Saunders Beitrag oben, der mir eine Idee gab, in das Fehlerfenster zu schauen. Ich habe den ganzen Tag meinen Kopf eingepackt und im Ausgabefenster nach Fehlern gesucht. 

In meinem Fall war der Täter ISerialisierbar. Ich habe eine DataContract-Klasse mit der DataMember-Eigenschaft vom Typ Exception. Sie können keinen DataMember des Typs haben, der das Schlüsselwort ISerializable hat. In dieser Ausnahme ist ISerializable, sobald ich es entfernte, alles wie ein Zauber funktioniert. 

0
Ziggler

Wie @dblood darauf hinweist, liegt der Hauptschmerz im DataContractSerializer, der die Typen nicht korrekt wiederverwendet. Hier gibt es bereits einige Antworten, also füge ich zunächst einige Vor- und Nachteile hinzu:

  • Das 'IsReference'-Flag verursacht viele Probleme, aber das Entfernen ist nicht immer die Antwort (speziell: in Situationen mit Rekursion). 
  • Das zugrunde liegende Problem ist, dass der Datenvertrag irgendwie nicht mit den Typnamen identisch ist, auch wenn sie manchmal (ja? Sie haben das richtig gelesen!). Anscheinend ist der Serializer ziemlich wählerisch und es ist sehr schwer, das eigentliche Problem zu finden.
  • Das Entfernen der 'Verweisprüfungen' aus der 'Dienstverweis konfigurieren' funktioniert zwar, aber Sie haben mehrere Implementierungen. Ich verwende jedoch häufig SOAP - Schnittstellen zwischen DLLs. In den meisten ausgereiften SOAs, die ich kenne, implementieren und erweitern mehrere Dienstschnittstellen die gleichen Schnittstellenklassen. Das Entfernen von Überprüfungen der Option "referenzierte Typen verwenden" führt dazu, dass Sie Objekte nicht mehr einfach weitergeben können.

Wenn Sie Ihren Service unter Kontrolle haben, gibt es eine einfache Lösung, die all diese Probleme löst. Dies bedeutet, dass Sie Dienstschnittstellen auch über DLLs hinweg wiederverwenden können. Dies ist ein Muss für eine korrekte Lösung. So funktioniert die Lösung:

  1. Erstellen Sie eine separate Schnittstellen-DLL. Schließen Sie in dieser DLL alle DataContract- und ServiceContract-Dateien ein. setzen Sie ServiceContracts auf Ihre Schnittstellen.
  2. Leiten Sie die Serverimplementierung von der Schnittstelle ab.
  3. Verwenden Sie dasselbe DLL, um den Client mit Ihrer bevorzugten Methode zu erstellen. Zum Beispiel (IMyInterface ist die Servicevertrag-Schnittstelle):

    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();
    

Mit anderen Worten: Verwenden Sie nicht die Funktion "Dienstreferenz hinzufügen" , sondern zwingen Sie WCF, die (richtigen) Servicetypen zu verwenden, indem Sie die Proxy-Generierung umgehen. Schließlich haben Sie diese Klassen bereits.

Pro's:

  1. Sie umgehen den Prozess svcutil.exe, was bedeutet, dass Sie keine IsReference-Probleme haben
  2. DataContract-Typen und -Namen sind per Definition korrekt. Schließlich verwenden sowohl Server als auch Client dieselbe Definition.
  3. Wenn Sie die API erweitern oder Typen aus einer anderen DLL verwenden, halten (1) und (2) immer noch, damit Sie dort keine Probleme haben.

Nachteile: 

  1. A-Sync-Methoden sind schmerzhaft, da Sie keinen a-Sync-Proxy generieren. Daher würde ich dies in Silverlight-Anwendungen nicht empfehlen.
0
atlaste

Gestern war ich während der Entwicklung mit einem ähnlichen Problem konfrontiert. Ich fand heraus, dass ich denselben Namensraum in zwei verschiedenen Vertragsversionen verwendete. 

Wir haben 2 Vertragsversionen für beispielsweise Version 4 und Version 5. Ich habe alle Verträge von Version4 kopiert und den gesamten Namespace von Version4 in Version5 umbenannt. Dabei habe ich vergessen, den Namespace in einer der Dateien von v4 in v5 umzubenennen. Aufgrund eines Namespacekonflikts war die Reference.cs-Datei leer.

Dieses Problem ist schwer zu beheben, da beim Generieren der Servicereferenz keine Fehlermeldung angezeigt wird. Um dieses Problem zu identifizieren, habe ich alle neu erstellten Dateien manuell überprüft. Es gibt andere Möglichkeiten, dieses Problem zu lösen. Dies ist der erste Schritt, den Sie ausführen müssen, bevor Sie andere Optionen wählen.

0
arif.khan.b