Czasami dodanie odwołania do usługi WCF generuje puste odwołanie. Cs

159

Czasami dodanie odwołania do usługi WCF generuje pusty plik reference.cs i nie mogę odwoływać się do usługi w dowolnym miejscu w projekcie.

Czy ktoś to spotkał?

Matt
źródło

Odpowiedzi:

377

Ogólnie uważam, że jest to problem z genem kodu i przez większość czasu jest to spowodowane konfliktem nazwy typu, którego nie można rozwiązać.

Jeśli klikniesz prawym przyciskiem myszy odniesienie do usługi, klikniesz konfiguruj i odznaczasz opcję „Ponowne użycie typów w zestawach, do których istnieją odniesienia” , prawdopodobnie rozwiąże to problem.

Jeśli korzystałeś z jakiegoś aspektu tej funkcji, być może będziesz musiał upewnić się, że twoje nazwy są wyczyszczone.

Anderson Imes
źródło
5
Kiedy mi się to przydarzyło, stwierdziłem, że muszę również zmienić typ kolekcji z ObjectModel.ObservableCollection na Generic.List
Yossi Dahan
2
Zdarzyło mi się to, ponieważ dodałem do klasy częściowej.
Makotosan
2
Jeśli jednak chcesz użyć typów z konkretnego zestawu, możesz wybrać tylko ten zestaw i działa równie dobrze (przynajmniej w moim przypadku), ta
Dead.Rabit
26
Wprawia mnie w zakłopotanie, że nawet 6 lat później dostaję z tego pytania średnio 50 punktów tygodniowo. Chodź stwardnienie rozsiane, napraw to. Przynajmniej daj programistom trochę informacji zwrotnych, gdy sytuacja idzie źle, zamiast patrzeć na pusty plik.
Anderson Imes
1
9 lat później i nadal pomagasz. Dziękuję Ci!
parametr
38

Jak wskazuje zaakceptowana odpowiedź, prawdopodobnie przyczyną jest problem z odniesieniem do typu podczas ponownego wykorzystywania typów. Zauważyłem, że kiedy nie możesz łatwo określić problemu, użycie wiersza poleceń svcutil.exe pomoże ci ujawnić podstawowy problem (jak wskazuje John Saunders).

Jako ulepszenie tutaj jest szybki przykład użycia svcutil.

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

Gdzie:

  • / t: kod generuje kod z podanego adresu URL
  • / d: aby określić katalog dla danych wyjściowych
  • / r: aby określić zestaw odniesienia

Pełne odniesienie do wiersza poleceń svcutil tutaj: http://msdn.microsoft.com/en-us/library/aa347733.aspx

Po uruchomieniu svcutil powinieneś zobaczyć wyjątek zgłaszany przez import. Możesz otrzymać wiadomość tego typu dotyczącą jednego z Twoich typów: „typ, do którego się odwołujesz, nie może być użyty, ponieważ nie pasuje do zaimportowanego kontraktu DataContract”.

Może to być po prostu określone w tym, że istnieje różnica w jednym z typów w przywoływanym zestawie od tego, co zostało wygenerowane w DataContract dla usługi. W moim przypadku usługa, którą importowałem, miała nowsze, zaktualizowane typy z tego, co miałem w zestawie współdzielonym. Nie było to łatwo widoczne, ponieważ typ wymieniony w wyjątku wydawał się być ten sam. Jedyną różnicą był jeden z zagnieżdżonych typów złożonych używanych przez ten typ.

Istnieją inne, bardziej złożone scenariusze, które mogą wywołać tego typu wyjątek i wynikający z niego pusty plik reference.cs. Oto jeden przykład .

Jeśli masz ten problem i nie używasz typów ogólnych w kontraktach danych ani nie używasz IsReference = true, zalecam sprawdzenie, czy twoje udostępnione typy są dokładnie takie same na kliencie i serwerze. W przeciwnym razie prawdopodobnie napotkasz ten problem.

dblood
źródło
W moim przypadku doszło do tego po odwołaniu się do zestawu, który również odwoływał się do mojej usługi WCF. Usunięcie tego zestawu z listy zestawów w celu współużytkowania typów z naprawionym.
xr280xr
Podczas dodawania odwołania do usługi otrzymywałem bezsensowny komunikat o błędzie (tylko przestrzeń nazw) i to wskazało na problem.
bcampolo
12

W takim przypadku spójrz w okno Błędy i okno Dane wyjściowe, aby sprawdzić, czy są jakieś komunikaty o błędach. Jeśli to nie pomoże, spróbuj uruchomić svcutil.exeręcznie i sprawdź, czy są jakieś komunikaty o błędach.

John Saunders
źródło
@ Jak uruchomić svcutil.exe? możesz mi pomóc ?
Arul Sidthan
@Arul: Użyj Google, aby znaleźć informacje o svcutil.exe.
John Saunders
2
Nie jestem pewien, czy Microsoft przeczytał ten post, ale nawet pokazanie okna komunikatu z informacją o błędach i ostrzeżeniach zamiast po prostu po cichu umieszczać je w (zminimalizowanym, w moim przypadku) oknie Lista błędów spowodowałoby to, więc nie potrzebowałem Google to. Alternatywnie, myślę, że przydałoby się, aby karta była wyświetlana na czerwono lub żółto, gdy pojawiają się nowe ostrzeżenia / błędy?
jrh
12

Przez cały dzień waliłem się w głowę z tym właśnie problemem. Właśnie to naprawiłem. Oto jak...

Usługa musiała działać przez SSL (tj. Jest pod adresem https://mydomain.com/MyService.svc )

Dodanie odwołania do usługi do usługi WCF na serwerze deweloperskim działało dobrze.

Wdrożenie dokładnie tej samej kompilacji usługi WCF na serwerze produkcyjnym na żywo, a następnie przełączenie się do aplikacji klienckiej i skonfigurowanie odwołania do usługi tak, aby wskazywało na usługę na żywo, nie wyświetlało żadnych błędów, ale aplikacja nie została zbudowana: Okazuje się, że odwołanie do usługi Plik Reference.cs był całkowicie pusty! Aktualizacja odniesienia do usługi nie spowodowała żadnej różnicy. Czyszczenie roztworu nie pomogło. Ponowne uruchomienie VS2010 nie zrobiło różnicy. Utworzenie nowego pustego rozwiązania, uruchomienie projektu konsoli i dodanie odwołania do usługi na żywo spowodowało dokładnie ten sam problem.

Nie sądziłem, że było to spowodowane konfliktami typów lub czymkolwiek, ale co do cholery - ponownie skonfigurowałem odwołanie do usługi WCF, odznaczając opcję „Ponowne użycie typów we wszystkich przywoływanych zestawach”. Brak przyjemności; Odłożyłem znacznik wyboru.

Następnym krokiem było wypróbowanie svcutil na referencyjnym adresie URL, aby sprawdzić, czy to pomoże wykryć problem. Oto polecenie:

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

Dało to następujące efekty:

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.

To mnie całkowicie zaskoczyło. Pomimo intensywnego googlowania i stawania się naprawdę raczej zła, a także ponownego rozważenia kariery kierowcy autobusu, w końcu zastanowiłem się, dlaczego działało dobrze na pudełku rozwojowym. Czy może to być problem z konfiguracją usług IIS?

Zdalnie przeszedłem jednocześnie do wersji deweloperskiej i wersji na żywo i na każdym uruchomiłem Menedżera IIS (z uruchomionym IIS 7.5). Następnie przeszedłem przez wszystkie ustawienia konfiguracyjne w każdym pudełku, porównując wartości na każdym serwerze.

I tu jest problem: w sekcji „Ustawienia SSL” dla witryny upewnij się, że jest zaznaczona opcja „Wymagaj SSL” i zaznacz opcję „Zaakceptuj” przy opcji Certyfikaty klienta. Problem rozwiązany!

Matt Kane
źródło
5

Zauważyłem, że zdarza się to często, gdy dodam odwołanie, usuwam je, a następnie ponownie dodam usługę o tej samej nazwie. Wydaje się, że konflikty typów są spowodowane pozostawieniem starych plików w miejscu, które program Visual Studio może nadal widzieć. Wszystko, co muszę zrobić, aby to naprawić, to wyczyścić przed dodaniem nowego odniesienia.

  1. Usuń odwołanie do usługi, w którym występują problemy.
  2. Kliknij nazwę projektu w Eksploratorze rozwiązań, aby wyróżnić projekt.
  3. Kliknij prawym przyciskiem myszy odniesienie do projektu.
  4. U góry listy kontekstów kliknij opcję Wyczyść element.
  5. Dodaj numer referencyjny usługi w normalny sposób.

Mam nadzieję że to pomoże.

user1353936
źródło
3

Miałem ten problem z Silverlight 5 zaktualizowanym z poprzedniej wersji.

Nawet ponowne dodanie odwołania do usługi nadal dawało mi pusty plik Reference.cs

Skończyło się na tym, że musiałem stworzyć zupełnie nowy projekt i odtworzyć odniesienie do usługi. Warto spróbować, jeśli poświęciłeś temu więcej niż pół godziny. Nawet jeśli jesteś zdeterminowany, aby naprawić oryginalny projekt, możesz spróbować tego tylko po to, aby zobaczyć, co się stanie, a następnie pracuj wstecz, aby spróbować rozwiązać problem.

Nigdy nie dowiedziałem się dokładnie, na czym polega problem - ale prawdopodobnie coś w pliku .csproj nie zostało zaktualizowane lub niektóre ustawienia poszły nie tak.

Simon_Weaver
źródło
1
ok, okazało się, że odwoływałem się do starej wersji System.Xml.Linq- więc sprawdź wersje wszystkich swoich bibliotek DLL, jeśli
zmieniłeś
1

Jeśli niedawno dodałeś kolekcję do projektu, gdy to zaczęło się pojawiać, problem może być spowodowany przez dwie kolekcje, które mają ten sam atrybut CollectionDataContract :

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

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

Naprawiłem błąd, przeglądając mój projekt i upewniając się, że wszystkie nazwy i pliki atrybut ItemName był unikalny:

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

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

Potem odświeżyłem referencje usługi i wszystko znowu działało.

Jon Person
źródło
1

Technika, która zadziałała w moim przypadku, po przeczytaniu tych odpowiedzi bezskutecznie, polegała po prostu na skomentowaniu całej mojej umowy i odkomentowaniu fragmentów, dopóki nie zadziała, w sposób binarny. To zawęża obraźliwy fragment kodu.

Następnie musisz tylko odgadnąć, co jest nie tak z tym kodem.

Oczywiście pomogłyby informacje o błędach w narzędziu.

Piszę umowę o świadczenie usług internetowych. Miałem zastępczą wyliczenie bez członków. W porządku. Ale jeśli użyję go we właściwości innej klasy i ponownie użyję biblioteki DLL kontraktu na kliencie, kodegen eksploduje bez komunikatu o błędzie. Uruchomienie svcutil.exe nie pomogło, po prostu nie udało się wyprowadzić pliku cs bez podania przyczyny.

JoshuaLawrence
źródło
Komentowanie wszystkich kontraktów operacyjnych zadziałało dla mnie. Szukałem złych metod jako winowajcy. Dziękujemy za powrót do podstaw podejścia do rozwiązywania problemów.
fizch
1

Poniższe nie jest tutaj wymienione i było to rozwiązanie, które zastosowałem (SvcUtils był przydatny w zobaczeniu komunikatu o błędzie. Jednak błąd, który otrzymałem, był wrapper type message cannot be projected as a data contract type since it has multiple namespaces. Znaczenie, podążyłem za tym tropem i dowiedziałem się o tymwsdl.exe przez ten post).

W moim przypadku samo uruchomienie wsdl [ my-asmx-service-address ] wygenerowało bezproblemowy .csplik, który umieściłem w projekcie i uruchomiłem w celu użycia usługi.

Veverke
źródło
0

Jak wskazuje @dblood, głównym problemem jest DataContractSerializer, który nie wykorzystuje poprawnie typów. Tutaj jest już kilka odpowiedzi, więc zacznę od dodania kilku zalet i wad:

  • Flaga „IsReference” powoduje wiele problemów, ale usunięcie jej nie zawsze jest odpowiedzią (w szczególności: w sytuacjach z rekurencją).
  • Podstawową kwestią jest to, że kontrakt danych w jakiś sposób nie jest tym samym, co nazwy typów, mimo że czasami są (tak? Tak, dobrze przeczytałeś!). Najwyraźniej serializator jest dość wybredny i bardzo trudno jest znaleźć prawdziwy problem.
  • Usunięcie „sprawdzeń odwołań” z „Konfiguruj odwołanie do usługi” działa, ale pozostawia wiele implementacji. Jednak często ponownie używam interfejsów SOAP w bibliotekach DLL. Ponadto w większości znanych mi dojrzałych SOA wiele interfejsów usług implementuje i rozszerza te same klasy interfejsów. Usunięcie sprawdzeń „użyj typów, do których istnieją odniesienia” powoduje sytuację, w której nie można już po prostu przekazywać obiektów.

Na szczęście, jeśli kontrolujesz swoje usługi, istnieje proste rozwiązanie, które rozwiązuje wszystkie te problemy. Oznacza to, że nadal możesz ponownie używać interfejsów usług we wszystkich bibliotekach DLL - co jest niezbędnym elementem IMO, aby uzyskać właściwe rozwiązanie. Oto jak działa rozwiązanie:

  1. Utwórz oddzielną bibliotekę DLL interfejsu. W tej bibliotece DLL uwzględnij wszystkie kontrakty DataContract i ServiceContract; umieść ServiceContract na swoich interfejsach.
  2. Wyprowadź implementację serwera z interfejsu.
  3. Użyj tej samej biblioteki DLL, aby skonstruować klienta przy użyciu swojej ulubionej metody. Na przykład (IMyInterface to interfejs umowy serwisowej):

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

Innymi słowy: nie używaj funkcji „dodaj odwołanie do usługi” , ale wymuś programowi WCF używanie (poprawnych) typów usług, pomijając generowanie serwera proxy. W końcu masz już te zajęcia.

Profesjonaliści:

  1. Pomijasz proces svcutil.exe, co oznacza, że ​​nie masz żadnych problemów z IsReference
  2. Typy i nazwy DataContract są z definicji poprawne; w końcu zarówno serwer, jak i klient używają tej samej definicji.
  3. Jeśli rozszerzysz interfejs API lub użyjesz typów z innej biblioteki DLL, (1) i (2) nadal będą działać, więc nie będziesz mieć tam żadnych problemów.

Cons:

  1. Metody synchronizacji są uciążliwe, ponieważ nie generujesz serwera proxy synchronizacji. W rezultacie nie polecałbym tego robić w aplikacjach Silverlight.
atlaste
źródło
0

Miałem również problem z uszkodzonymi referencjami usług podczas pracy z referencjami projektu po obu stronach (projekt usługi i projekt mający odniesienie do usługi). Jeśli na przykład plik .dll przywoływanego projektu nosi nazwę „Contoso.Development.Common”, ale nazwa projektu jest po prostu skrócona do „Wspólne”, również odwołania projektu do tego projektu są nazywane po prostu „Wspólne”. Usługa oczekuje jednak odwołania do „Contoso.Development.Common” w celu rozpoznania klas (jeśli ta opcja jest aktywowana w opcjach odwołania do usługi).

Tak więc w eksploratorze otworzyłem folder projektu, który odwołuje się do usługi i projektu „Common”. Tam edytuję plik projektu VS (.csproj) za pomocą notatnika. Wyszukaj nazwę referencyjnego projektu (w tym przykładzie jest to „Common.csproj”), a szybko znajdziesz wpis konfiguracji reprezentujący odniesienie do projektu.

Zmieniłam

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

do

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

Ważne jest, aby zmienić nazwę odwołania na nazwę biblioteki DLL, do której odwołuje się projekt.

Następnie przełącz się z powrotem na VS. Tam zostaniesz poproszony o ponowne załadowanie projektu, ponieważ został zmodyfikowany poza VS. Kliknij przycisk odświeżania.

Po wykonaniu tej czynności dodanie i zaktualizowanie odwołania do usługi działało zgodnie z oczekiwaniami.

Mam nadzieję, że to pomoże również komuś innemu.

Pozdrawiam MH

Martype
źródło
0

Z podobnym problemem spotkałem się wczoraj podczas tworzenia. Dowiedziałem się, że używam tej samej przestrzeni nazw w 2 różnych wersjach umów.

Mamy 2 wersje kontraktów, na przykład wersję 4 i wersję 5. Skopiowałem wszystkie kontrakty z wersji 4 i zmieniłem nazwę całej przestrzeni nazw z wersji 4 na wersję 5. Robiąc to zapomniałem zmienić nazwę przestrzeni nazw z v4 na v5 w jednym z plików. Z powodu konfliktu przestrzeni nazw plik Reference.cs był pusty.

Ten problem jest trudny do rozwiązania, ponieważ podczas generowania odwołania do usługi nie pojawia się żaden komunikat o błędzie. Aby zidentyfikować ten problem, ręcznie zweryfikowałem wszystkie nowo utworzone pliki. Istnieją inne sposoby rozwiązania tego problemu. Jest to pierwszy krok, który należy wykonać przed przejściem do innych opcji.

arif.khan.b
źródło
0

Podziękowania dla Johna Saundersa w poście powyżej, który dał mi pomysł, aby zajrzeć do okna błędów. Cały dzień pakowałem głowę i patrzyłem na okno wyjściowe pod kątem jakiegokolwiek błędu.

W moim przypadku winowajcą był ISerializable. Mam klasę DataContract z właściwością DataMember typu Exception. Nie można mieć elementu DataMember typu, który ma słowo kluczowe ISerializable. W tym wyjątku ISerializable, gdy tylko go usunąłem, wszystko działało jak urok.

Ziggler
źródło
0

Podczas próby rozwiązania tego problemu z svcutil , otrzymałem błąd, o którym mowa w odpowiedzi dblood („nie można użyć przywoływanego typu, ponieważ nie pasuje do zaimportowanego kontraktu DataContract”).

W moim przypadku przyczyną źródłową wydawał się być typ wyliczeniowy, który miał atrybut DataContract, ale którego elementy członkowskie nie zostały oznaczone atrybutem EnumMember. Klasa problemusvcutil miała właściwość z tym typem wyliczenia.

To lepiej by pasowało jako komentarz do odpowiedzi Dblooda, ale za mało reputacji za to ...

Platedslicer
źródło
0

W moim przypadku miałem rozwiązanie z projektem VB Web Forms, które odwoływało się do C # UserControl. Zarówno projekt VB, jak i projekt CS miały odniesienie do usługi do tej samej usługi. Odniesienie pojawiło się w obszarze Referencje usług w projekcie VB oraz w grupie Connected Services w projekcie CS (framework).

Aby zaktualizować odniesienie do usługi (tj. Aby plik Reference.vb nie był pusty) w projekcie formularzy internetowych VB, musiałem USUNĄĆ PROJEKT CS, a następnie zaktualizować odwołanie do usługi VB, a następnie dodać projekt CS z powrotem do rozwiązanie.

INFOequipt
źródło
0

Wykonaj następujące kroki:

  1. Usuń odniesienie do usługi
  2. Zamknij program Visual Studio
  3. Usuń foldery / Bin i / Obj.
  4. Otwórz program Visual Studio.
  5. Dodaj odwołanie do usługi.
  6. Nie ma za co :)

Wygląda na to, że podczas dodawania usługi w tych folderach pozostają odniesienia, powodując błędy podczas automatycznego generowania kodu.

Exel Gamboa
źródło