Wie verbrauchen nicht-IIS gehostet, WCF, C# web service von Delphi 2007?
Ich geschrieben habe, eine ziemlich einfache, kleine C# - web service, gehostet von einem standalone-EXE via WCF. Die code - etwas vereinfacht - wie folgt aussieht:
namespace VMProvisionEXE
{
class EXEWrapper
{
static void Main(string[] args)
{
WSHttpBinding myBinding = new WSHttpBinding();
myBinding.Security.Mode = SecurityMode.None;
Uri baseAddress = new Uri("http://bernard3:8000/VMWareProvisioning/Service");
ServiceHost selfHost = new ServiceHost(typeof(VMPService), baseAddress);
try
{
selfHost.AddServiceEndpoint(typeof(IVMProvisionCore), myBinding, "CoreServices");
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy12;
selfHost.Description.Behaviors.Add(smb);
//Add MEX endpoint
selfHost.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
selfHost.Open();
Console.WriteLine("The service is ready.");
Console.ReadLine();
Den rest der C# - code; die Klasse VMPService oben implementiert VMProvisionCore.IVMProvisionCore.
namespace VMProvisionCore
{
[ServiceContract(Namespace = "http://Cisco.VMProvision.Core", ProtectionLevel = System.Net.Security.ProtectionLevel.None)]
public interface IVMProvisionCore
{
[OperationContract]
bool AuthenticateUser(string username, string password);
}
Ich kann einfach erstellen Sie ein Visual Studio 2008-client-Anwendung, verbraucht dieses service. Keine Probleme. Aber mit Delphi 2007, ist eine andere Frage. Ich kann die WSDL-importer in Delphi zum abrufen der WSDL aus (in diesem Fall) http://bernard3:8000/VMWareProvisioning/Service?wsdl Die import-unit kompiliert einwandfrei. Ich habe zum initialisieren der proxy von hand, da die WSDL nicht eine URL enthalten (man beachte das zusätzliche "/CoreServices", wie gezeigt, in der C# - code):
var
Auth: AuthenticateUser;
AuthResponse: AuthenticateUserResponse;
CoreI: IVMProvisionCore;
begin
CoreI:= GetIVMProvisionCore(False, 'http://bernard3:8000/VMWareProvisioning/Service/CoreServices');
Auth:= AuthenticateUser.Create;
try
Auth.username:= 'test';
Auth.password:= 'test';
AuthResponse:= CoreI.AuthenticateUser(Auth);
finally
FreeAndNIL(Auth);
end;
Der obige code erzeugt eine Fehlermeldung, wenn es Sie trifft die "CoreI.AuthenticateUser(Auth);". Der Fehler ist "Nicht verarbeiten kann, die Nachricht, da der content-Typ " text/xml; charset="utf-8" war nicht die erwarteten Typ 'application/soap+xml; charset=utf-8."
Ich vermute, ich habe einen dummen kleinen Fehler irgendwo, vielleicht beim import der WSDL oder in der Verbindung Optionen oder etwas. Kann mir jemand helfen?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die Lösung gefunden. Es ist mehrteilig und erfordert ein paar änderungen an der C# - Seite, mehr auf der Delphi-Seite. Beachten Sie, dass dies wurde getestet mit Delphi 2007 und Visual Studio 2008.
C# Seite:
Verwenden BasicHttpBinding statt WSHttpBinding.
Fix Schritt 1
Ändern, wird die Behebung des application/soap+xml-Fehler, die auf der Delphi-Seite.
Delphi 2007-Seite:
Läuft gegen den modifizierten C# web service generiert nun Fehler wie diese:
Um dieses problem zu beheben, fügen Sie SOAPActions alle Ihre Schnittstellen. Hier ist das Beispiel aus meinem code, dies muss getan werden, NACHDEM alle InvRegistry änderungen durch den import von WSDL-PAS-Datei der initialization-Abschnitt:
Update Schritt 2
Den Namen eingeben und die URL sollte erhältlich sein, die von Delphi erzeugte import-Datei aus der WSDL-und/oder eine Inspektion der eigentlichen WSDL. Das obige Beispiel war für mein eigenes Projekt. Nachdem diese änderungen am code, dann wirst du den Fehler:
Dieser Fehler behoben ist, indem Sie den folgenden code (credits http://www.bobswart.nl/weblog/Blog.aspx?RootId=5:798). Wieder, dieser neue code muss nach all den InvRegistry Zeug in der Initialisierung des WSDL-zu-PAS-Datei.
Update Schritt 3
Zu diesem Zeitpunkt, Pakete hin und her gehen zwischen Delphi-und C# - aber die Parameter nicht mehr richtig funktioniert. Die C# erhalten Sie alle Parameter, die als Nullen und Delphi scheint es nicht zu sein, empfangen von Parametern zur Antwort auf " richtig. Der endgültige code-Schritt verwenden Sie eine leicht angepasste THTTPRIO-Objekt erlauben, literal Parameter. Der trick an diesem Teil ist, um sicherzustellen, dass die option angewendet wird, NACHDEM die Schnittstelle erhalten hat; es zu tun, bevor Sie nicht funktionieren. Hier der code aus meinem Beispiel (nur Beispiele).
Beheben Schritt 4
Nun hat mein Delphi 2007-app sprechen können, um den C# -, stand-alone, nicht-IIS, WCF-service!
Dies ist verursacht durch eine SOAP-version überein. Die C# - Dienst erwartet ein SOAP12-Nachricht und Empfang einer SOAP11 Nachricht von Ihrem Delphi-app. Je nach Ihrer situation, die Sie ändern müssen, entweder von den beiden Seiten. Ich kann nicht wirklich kommentieren die Delphi-Seite. Auf der WCF-Seite können Sie das "BasicHttpBinding", die standardmäßig auf SOAP11 oder, wenn Sie mehr Kontrolle benötigen, verwenden Sie ein CustomBinding die Angabe einer message-Typ der SOAP11.
Habe ich vor demselben problem beim Verzehr von C# - web service in delphi.
Delphi 7.0/2005/2007 nicht unterstützt neue WSDL-Definitionen.
Für diese, müssen Sie den download der aktuellen WSDL-Importer (WSDLImp.exe). Es wird auch source code für aktualisierte delphi-source-code-pass-Dateien.
Dank - das hat mir sehr geholfen. Ich hatte Probleme mit ein paar mehr Falten. Für mich, Ausgabe #2 (SOAPAction) war alles verrußt, weil die "OperationName" nicht übereinstimmen. Die .Net-Gruppe standardisiert auf die Platzierung "In" am Ende des SOAPAction -, aber nicht der Vorgang.
So yadda.yadda.com/whatever/services/%operationName%
wirklich sein muss
yadda.yadda.com/whatever/services/%operationName%In
In diesem speziellen Fall.
Es dauerte eine Weile zu erkennen, doch bemerkte ich schließlich durch Tests parallel mit SoapUI, dass es hatte verschiedene SOAPActions als die Rückkehr in die error-response. Ich behoben, und es funktionierte. Aber das war nach dem Kampf ziemlich eine Weile, um herauszufinden, was sollte in der DefaultSOAPAction in den ersten Platz. Wieder, SoapUI war hier hilfreich.
So jedenfalls, wenn Sie feststellen, dass Sie diese Fehlermeldung erhalten:
"Aktion (was auch immer) kann nicht verarbeitet werden, an den Empfänger aufgrund einer ContractFilter Fehlanpassung auf die EndpointDispatcher..."
Der erste Schritt ist das Auffüllen der DefaultSOAPAction, und falls die Probleme weiterhin bestehen, zu vergleichen, den man in der Fehler gemeldet, gegen das, was wirklich da sein sollte.
HTH, Chris