2013-04-23 16 views
9

Nie mogę znaleźć przykładu generowania serwerów proxy z plików WSDL z typami współużytkowanymi, ale bez żadnych XSD, aby z nimi współpracować. Czy ktoś może oznaczyć to jako duplikat i wskazać mi przykład?Udostępnianie typów WSDL bez XSD

Oto 2 usługi, z których każda ma własną przestrzeń nazw i typ wspólny. Jedyne, co jest publicznie dostępne, to ich WSDL, nie ma typu XSD ani jego. Dll, który przejdzie na wsdl.exe /sharedtypes lub svcutils, a bez niego otrzymam identyczny class Foo, którego nie mogę przekazać do SetFoo i .

Najlepszym mogę wymyślić generuje proxy programowo i wykrywanie duplikatów poprzez CodeDOM, ignorując DataContract/WebServiceBinding nazw, ale jest to ogromny bałagan ...

[WebService(Namespace = "http://tempuri.org/FOO1")] 
public class Service1 : WebService 
{ 
    [WebMethod] 
    public Foo GetFoo() 
    { 
     return new Foo(); 
    } 
} 

[WebService(Namespace = "http://tempuri.org/FOO2")] 
public class Service2 : WebService 
{ 
    [WebMethod] 
    public void SetFoo(Foo foo) 
    { 
    } 
} 

public class Foo 
{ 
    public int Bar { get; set; } 
} 
+0

Jako część definicji WSDL znajdują się XSD definiujące typy. Jeśli nie są zdefiniowane w WSDL, w jaki sposób ma się korzystać z usługi? –

+0

@hugh Są one zdefiniowane dwa razy, w każdym pliku WSDL, dlatego też we \ wsdls 'Service1' i' Service2' nie widzę sposobu na wygenerowanie dla nich proxy ze wspólną definicją 'Foo', która może być przekazywana z' GetFoo' na '' SetFoo'. –

+0

Rozumiem. Zobacz moją odpowiedź poniżej –

Odpowiedz

1

Jest na to sposób to zrobić, który jest opisany here.

W twoim przypadku możesz pominąć pierwszy krok, wygenerować proxy z usługi 1, a następnie użyć flagi/r na svcutil, aby odwołać się do zespołu proxy usługi 1 podczas generowania usługi 2 proxy.

Zapewni to twoją usługę 2 proxy użyje tego samego wystąpienia Foo z twojego serwera proxy usługi 1.

Czy jednak rozważałeś tylko jedną usługę z dwiema operacjami? To zaoszczędziłoby ci dużo pracy.

Edycja: Również spojrzeć na ten post: http://blogs.msdn.com/b/youssefm/archive/2009/10/09/reusing-types-in-referenced-assemblies-with-svcutil-s-r-switch.aspx

+0

Wydaje się nie działać, zachowuje 2 'Foo's w 2 różnych przestrzeniach nazw. Oto konfiguracja (https://github.com/kozhevnikov/WebService1) - "WebService1" z dwiema usługami, 'ClassLibrary1' ze współdzielonym typem' Foo' i 'ConsoleApplication1', która próbuje wywołać' GetFoo'/' SetFoo' za pośrednictwem proxy. Próbowałem 'svcutil Service1.wsdl && csc/t: biblioteka Service1.cs && svcutil Service2.wsdl/r: Service1.dll' i 'svcutil Service1.wsdl/r: .. \ ClassLibrary1 \ bin \ Debug \ ClassLibrary1.dll' ale w obu przypadkach kończy się na 2 niekompatybilnych 'Foo's. –

+0

Czy umieścisz WSDL-y, a ja się obejrzę - może być tak, że dwa Foo są naprawdę oddzielnymi typami zdefiniowanymi w różnych XSD, w takim przypadku nie możesz użyć flagi/r, ponieważ typy nie są prawdziwie równoważne. –

+0

Dokładnie, pochodzą one z tej samej klasy, ale z technicznego punktu widzenia są różne przyczyny, ponieważ autogenerowany wsdl umieszcza dwie kopie w dwóch różnych przestrzeniach nazw (rodzime usługi internetowe, w których są używane), stąd pytanie. Przykładowe wsdls znajdują się na https: // github.com/kozhevnikov/WebService1/tree/master/wsdl –

1

Po pierwsze, trzeba ustawić [DataContract (Namespace = „Niektóre nazw tutaj”)] dla wszystkich typów danych powszechne usługi, w przeciwnym razie, gdy Wygenerowane są WSDL i XSD, wtedy będziesz mieć obiekty z dwóch różnicowych przestrzeni nazw --- jest to absolutnie niezbędne. Wartość przestrzeni nazw będzie miała zastosowanie tylko do typów zdefiniowanych w XSD, a nie do WSDL. XSD = dane, WSDL = usługa.

Pliki XSD i WSDL i wygenerowane, jeśli i tylko jeśli masz ustawione zachowanie usługi META, dodaj to zachowanie, a następnie przejdź do adresu URL. Adres URL zachowania usługi META będzie miał link do twoich WSDL i XSD.

Używam poniższego fragmentu kodu do samodzielnego hostowania usług w systemie Windows zamiast w IIS, jednak mają zastosowanie te same zasady.

/// <summary> 
/// Enables meta data output for a service host. 
/// </summary> 
/// <param name="host">The service host.</param> 
/// <remarks>Must be invoked prior to starting the service host.</remarks> 
public static void SetupMetaDataBehaviour(ServiceHost host) 
{ 
    ServiceMetadataBehavior metaDataBehaviour = host.Description.Behaviors.Find<ServiceMetadataBehavior>(); 
    if (metaDataBehaviour == null) 
    { 
     metaDataBehaviour = new ServiceMetadataBehavior(); 
     metaDataBehaviour.HttpGetEnabled = true; 
     host.Description.Behaviors.Add(metaDataBehaviour); 
    } 
    else 
    { 
     metaDataBehaviour.HttpGetEnabled = true; 
    } 
} 
+0

Dzięki, ale zgodnie z OP nie mogę modyfikować usług ani typów, mam tylko dostęp do surowych, automatycznie generowanych WSDL-ów, tak jakby były publiczne (technicznie odzwierciedliłem typy, z których sam generuję WSDL), usługi mają unikalny [WebService (Namespace)] na nich i typy nie mają nic na nich, z wyjątkiem sporadycznych XmlInclude, bez atrybutów związanych z usługami lub przestrzeniami nazw. –

+0

Podobnie jak w przykładzie 'GetFoo' /' SetFoo', mam WSDL dla 'Service1' i' Service2' i muszę wygenerować dla nich proxy ze współużytkowanym 'Foo', dzięki czemu mogę nazwać' GetFoo' i przekazać go do 'SetFoo ' 'pod inną autogenerowaną przestrzenią nazw (działa, kiedy gram na' CodeDOM', rozpakowuję 'Foo' i usuwam wszelkie przestrzenie nazw, ale to podejście nie jest skalowalne do setek mało znanych starszych usług internetowych). –

1

Po dodaniu dwóch odniesień internetowych:

  1. kliknij dwukrotnie na odniesienie sekund usług internetowych
  2. w przeglądarce obiektu przejdź do definicji Foo
  3. prawym przyciskiem myszy na Foo i wybierz przejdź do definicji
  4. usuń definicję klasy Foo
  5. dodaj instrukcję użycia dla przestrzeni nazw sieci erwis jeden
  6. znaleźć i zastąpić wszystkie wystąpienia <namespace-of-service-reference-2>.Foo z zaledwie Foo

To powinno rozwiązać problem, ponieważ zmusza kod wygenerowany automatycznie na oba odnośniki usługowa używać tego samego deklarację klasy.

+1

Dzięki, ale jest to to samo, co manipulacje CodeDOM po generacji, tylko ręczne. Szukam sposobu, aby zrobić to automatycznie lub programowo (np. CodeDOM) i skalowalne do setek lub starszych usług internetowych z tysiącami wspólnych typów. –

+0

Rozumiem, co chcesz zrobić. Ale ponieważ wizualne studio autogeneruje dwie klasy w różnych przestrzeniach nazw przy użyciu tylko pliku wsdl, nie dostaniesz tego. Moje rozwiązanie zajmuje około 5 minut, aby dokonać zmiany w dużym projekcie. Jest powtarzalny i łatwy do zapamiętania. –

+0

Ponadto nie jest to typowy scenariusz. szczególnie w środowisku z "setkami lub starszymi usługami sieciowymi" możesz napotkać ten problem tylko raz, z jednym interfejsem API innej firmy na setki. Jeśli jest to kod wewnętrzny, nie pisz tego w ten sposób. Jeśli nie jesteś osobą, która wywołuje ujęcia, a ktoś projektuje usługi w ten sposób, musisz usiąść i pokazać im poziom frustracji, jaki powoduje ten projekt. –

Powiązane problemy