[gelöst]Fehler bei Basisclient für WebService automatisch aus WSDL erzeugen
-
Ich habe auf einer lokalen Maschine zum Testen einen IIS, auf diesem befindet sich ein Web Service, welcher u.a. Dateien empfangen kann. Diese empfängt er als DIME, das ganze basiert auf SOAP und Serverseitig wurde die DIME Funktionalität mittels Microsofts WSE implementiert. Der Service als solcher tuckert auf dem Server munter vor sich hin, die WSDL wie auch die über die asmx Seite automatisch erstellte Beispielkommunikation zeigen genau die gewünschte Funktionalität auf.
Nun will ich einen Client implementieren, welcher mit diesem Service kommuniziert, ihm also eine SOAP Message mit einem DIME anhängsel rüberschickt.
Zu deisem Zweck ist in Visual Studio .NET die Möglichkeit implementiert, einen "Webverweis hinzuzufügen". Es wird anhand der WSDL auf dem Server ein Proxy in das Client Projekt integriert und dabei automatisch eine Headerdatei generiert, welche die Methoden des Web Service zur Verfügung stellt. Wenn ich nun diesen Header mittels
#include "WSheader.h"
in meine gewünschte Clientanwendung integriere, kann ich mit der Proxyklasse, welche den Web Service repräsentiert so arbeiten, als sei es eine ganz normale C++ Klasse. So weit die Theorie. Dummerweise hat der Compiler Probleme, den (anhand der WSDL von Visual Studio automatisch generierten)Header zu verstehen...und das verstehe ich nicht ganz. Hier ein Auszug aus dem Header:
#pragma once #using <System.dll> #using <System.Xml.dll> #using <System.Web.Services.dll> #using <mscorlib.dll> // // Der Quellcode wurde von wsdl automatisch generiert. Version=1.1.4322.573. // namespace Server003 { using namespace System::Diagnostics; using namespace System::Xml::Serialization; using namespace System; using namespace System::Web::Services::Protocols; using namespace System::ComponentModel; using namespace System::Web::Services; using namespace System; public __gc class Server003Class; public __gc class DimeAttachment; public __value enum TypeFormat; public __gc class Attachment; public __gc abstract class Stream; public __gc abstract class MarshalByRefObject; //und es geht noch weiter, aber das erspar' ich Euch
So beginnt der Compiler an der (in dem von mir hier geposteten Auszug) vorlertzten Zeile zu mosern:
e:\Clnt003_omega\Server003.h(29) : error C3150: 'abstract': '__gc' kann nur auf eine Klasse, Struktur, Schnittstelle, Array oder Zeiger angewendet werden e:\Clnt003_omega\Server003.h(29) : error C2144: Syntaxfehler: 'Server003::Stream' sollte auf ';' folgen e:\Clnt003_omega\Server003.h(29) : error C2501: 'abstract': Fehlende Speicherklasse oder Typspezifizierer (und so weiter und so fort)
Als ob die Datentypen völlig unbekannt wären. Irgendwelche Vorschläge oder Ideen? Ich tippe darauf, dass die Datentypen aus den MS Web Service Enhancements unbekannt sind und ich die ihm irgendwie beibringen muss. Aber auf dem Server, von dem er sich die WSDL und das MS eigene *.disco Format bezieht kennt er die Dinger doch, kann es sein, dass diese info nicht übermittelt wird?
-
Du solltest "abstract" durch "__abstract" ersetzen...
Siehe: http://msdn.microsoft.com/library/en-us/vcmxspec/html/vcManagedExtensionsSpec_4.asp
-
Danke, das hat funktioniert. Da hätt ich echt ewig suchen müssen! Dickes Dankeschön.
Warum macht VS das nicht von allein? Immerhin wird der Code doch von eben dieser IDE erzeugt?
Trotzdem wurden so immer noch nicht alle Fehler bereinigt (von vorher 27 sind zum Glück nur noch drei übrig
) Hier weiss ich auch nicht wirklich Rat:
Der gleiche Header, nur etwas weiter unten:/// <remarks/> [System::Diagnostics::DebuggerStepThroughAttribute, System::ComponentModel::DesignerCategoryAttribute(S"code"), System::Web::Services::WebServiceBindingAttribute(Name=S"Server003ClassSoap", Namespace=S"http://tempuri.org/"), System::Xml::Serialization::XmlIncludeAttribute(__typeof(Server003::MarshalByRefObject)), System::Xml::Serialization::XmlIncludeAttribute(__typeof(Server003::Attachment))] public __gc class Server003Class : public System::Web::Services::Protocols::SoapHttpClientProtocol { /// <remarks/> public: Server003Class(); /// <remarks/> public: [System::Web::Services::Protocols::SoapDocumentMethodAttribute(S"http://tempuri.org/RecievePDF", RequestNamespace=S"http://tempuri.org/", ResponseNamespace=S"http://tempuri.org/", Use=System::Web::Services::Description::SoapBindingUse::Literal, ParameterStyle=System::Web::Services::Protocols::SoapParameterStyle::Wrapped)] System::Void RecievePDF(Server003::DimeAttachment * dAtt); /// <remarks/> public: System::IAsyncResult * BeginRecievePDF(Server003::DimeAttachment * dAtt, System::AsyncCallback * callback, System::Object * asyncState); /// <remarks/> public: System::Void EndRecievePDF(System::IAsyncResult * asyncResult); }; /// <remarks/> [System::Xml::Serialization::XmlTypeAttribute(Namespace=S"http://tempuri.org/")] public __gc class DimeAttachment : public Server003::Attachment { //******* /// <remarks/> public: System::Int32 ChunkSize; /// <remarks/> public: Server003::TypeFormat TypeFormat; };
In der von mir mit //******* gekennzeichneten Zeile gibt es auch einen Fehler (und Folgefehler):
e:\Clnt003_omega\Server003.h(56) : error C2504: 'Server003::Attachment': Basisklasse undefiniert e:\Clnt003_omega\Server003.h(63) : error C2027: Verwendung des undefinierten Typs "Server003::TypeFormat" e:\Clnt003_omega\Server003.h(27): Siehe Deklaration von Server003::TypeFormat' e:\Clnt003_omega\Server003.h(103) : error C2504: 'Server003::MarshalByRefObject': Basisklasse undefiniert
Server 003 und TypeFormat sind weiter oben im Header (siehe dazu ggf. den Eingangspost) oben wie folgt definiert:
using namespace System; public __gc class Server003Class; public __gc class DimeAttachment; public __value enum TypeFormat; public __gc class Attachment; public __gc __abstract class Stream; public __gc __abstract class MarshalByRefObject;
Wie komm ich da am besten weiter? Vor allen Dingen wird "Server003" auch an anderen Stellen vorher verwendet, ohne dass es dem Compiler "unangenehm" auffallen würde. Nochmal Danke an jeden, der sich bemüht, mir zu helfen. Bin in diesen .NET Dingen noch nicht wirklich fit.
-
Das was Du in der h-Datei gezeigt hast ist nur eine "forward" declaration! Aber die gesamte Klasse muss komplett deklariert sein, bevor sie verwendet wird! Also entweder fehlt noch eine include-Datei oder Du musst die deklaration vor der Verwendung machen!
-
Edit.
-
Nach nochmaliger Programmanalye:
Mittels "Verweise" im Projektmappen Explorer ist die DLL, in der die Klasse "Attachment" definiert ist, dem Projekt hinzugefügt.
Wenn ich nochmal explitit mittels
#using <microsoft.web.services2.dll>
versuche, diese DLL innerhalb des Codes dem Präprozessor anzugeben, bekomme ich einen Fatal Error, von wegen DLL nicht gefunden. Das finde ich ein bisschen Seltsam, denn die DLL ist sehr wohl vorhanden und andere Programme hatten damit bisher auch keine Probleme. Ebenso kann ich per Rechtsklick auf "Attachment" im Code zun dann "Gehe zu Definition" mich auf diese DLL verweisen lassen. Das heisst ja, das VS sie in diesem Programmkontext kennt und auch "Attachment" als Klasse aus dieser DLL auffasst.
Warum versteht der Compiler dann aber "Attachment" in dem hier thematisierten Kontext nicht? Welche Möglichkeit bestehet noch, dem Kompiler die benötigten Informationen mitzuteilen?
LÖSUNG: Fälschlicherweise generiert VS nicht funktionierenden Code. Anstelle Attachment von Server003 abzuleiten (geht nicht) muss man an dieser Stelle den vollen Ableitungspfad angeben:
Microsoft::Web::Services2::Attachments::Attachment
und nicht Server003 : Attachment.