2012-03-29 30 views
2

Ich entwerfe einen WCF-Dienst mit Rückruf, aber meine Implementierung der Rückruffunktion wird nie aufgerufen. Und ich bin verwirrt über den generierten Service-Proxy, also bitte helfen.WCF Callback-Implementierungsfunktion wird nie aufgerufen

Hier ist das Szenario: auf der Serverseite habe ich die Service-Schnittstelle IMyService und Callback-Schnittstelle IMyServiceCallback definiert, ich habe auch den IMyService im Server-Projekt implementiert. Neben dem Server-Projekt habe ich sicherlich noch ein Client-Projekt, dem ich in VS die Service-Referenz hinzugefügt habe. Und ich habe die IMyServiceCallback-Schnittstelle auf der Client-Seite implementiert. So kommt hier das Problem: Wenn ich es debugge, geht die Funktion nie in meine Implementierung von IMyServiceCallback und natürlich kommt das gewünschte Ergebnis nie heraus.

Und das ist ich, wo ich verwirrt wurde: als ich die Service-Referenz in der Client-Seite hinzugefügt, es tatsächlich drei Schnittstellen auf dem lokalen generiert: IMyService, IMyServiceCallback und IMyServiceChannel plus die Client-Proxy-Klasse. Und in meiner lokalen Implementierung von IMyServiceCallback deklarierte ich die Klasse, um die lokale IMyServiceCallback-Schnittstelle zu implementieren, nicht die von der Dienstseite. Könnte das das Problem sein? Warum gibt es zwei Deklarationen der Schnittstelle unter verschiedenen Projekten (und damit unterschiedliche Namespaces)? Der Grund, warum ich die clientseitige Schnittstelle implementiere, wäre, wenn ich von der serverseitigen Schnittstelle implementiert würde, der Fehler: "InstanceContext für die ChannelFactory enthält ein UserObject, das den CallbackContractType-Fehler nicht implementiert", als ich versuchte, den Dienst aufzurufen. Und ein weiterer verwirrender Teil ist, auf der Serverseite, wenn ich den Callback-Interface-Namen als IMyCallback oder irgendetwas anderes anstelle von IMyServiceCallback deklariere, wäre die generierte Schnittstelle auf der Client-Seite immer noch IMyServiceCallback, was der Name der Service-Schnittstelle plus ist Suffix "Rückruf". Und in dieser Situation habe ich auch den "InstanceContext, der der ChannelFactory zur Verfügung gestellt wird, ein UserObject enthält, das den CallbackContractType-Fehler nicht implementiert".

Ich denke, es gibt etwas, das ich missverstanden habe über die "Service-Referenz hinzufügen" und wie ich die Schnittstelle implementieren soll (welche zu implementieren). Könnte mir jemand helfen? Vielen Dank!

Aktualisiert:

Ich reparierte irgendwie das Problem. Erstens ist die zwei Deklarationen in Ordnung ist erwünscht. Der lokale Client muss die lokale Schnittstelle implementieren, die beim Hinzufügen der Servicereferenz generiert wird. Und mein Problem war, dass ich auch einen DataContract definiert habe, aber die generierte Referenzdatei hatte ihn nicht. Entweder weil ich die Assembly des Serviceprojekts als Referenz hinzugefügt hatte (jemand hat in diesem Fall gesagt, dass die Servicereferenz den Datacontact nicht generiert) oder weil mir das DataMember-Attribut fehlte. Aber nachdem ich beide Teile repariert habe, funktioniert die Funktion jetzt.

Antwort

2

Wenn Sie "Service-Referenz hinzufügen" und generieren einen Proxy, ist es völlig getrennt von Ihrer Service-Implementierung. Denken Sie daran, dass Sie möglicherweise einen Service konsumieren, den Sie nicht geschrieben haben, und keinen Zugriff auf den Service-Quellcode haben.

Der Client-Code sollte die vom Client generierten Schnittstellen verwenden. Wenn Sie Ihren Dienst ändern, müssen Sie den Proxy neu generieren.

Wenn Sie dies zu unordentlich finden, und Sie wissen, dass Sie immer beide Enden steuern, können Sie die Service-Schnittstellen in einer allgemeinen Assembly freigeben und eine Proxy-Klasse zur Laufzeit mit DuplexChannelFactory.CreateChannel() generieren.

Bei Ihrem Problem kann ich nur davon ausgehen, dass Sie Ihren Rückruf nicht ordnungsgemäß registrieren. Dies ist abgedeckt here.

+0

Danke für Ihre Antwort. Wie ich bei der Aktualisierung meines ursprünglichen Posts erwähnt habe, ist mir jetzt aufgefallen, dass die lokale Interface-Deklaration erwünscht ist. Und es macht Sinn, dass ich "einen Dienst verwende, den Sie nicht geschrieben haben und keinen Zugriff auf den Dienstquellcode haben". Ich denke, mein Problem war mit einer DataContract-Deklaration, die fälschlicherweise nicht auf der Client-Seite generiert wurde. – tete

0

Wenn Sie veröffentlichen möchten, müssen Sie IMyServiceCallback und IMyService zusammen in demselben Projekt implementieren. Wenn Sie nur subskribieren, müssen Sie die IMyServiceCallback-Schnittstelle implementieren

+0

Vielen Dank für Ihre Antwort. Ich möchte nur abonnieren und deshalb habe ich nur IMyServiceCallback implementiert. – tete

0

Ich habe das Problem behoben, wenn meine Callback-Anweisung in einen Funktionsaufruf eingebettet wurde. Ich habe gelernt, dass die Platzierung des Callbacks in einer Methode, die kein Ergebnis zurückgibt, funktioniert. Wenn jedoch der Callback-Befehl innerhalb einer Funktion platziert wurde, kam es zu einem Timeout-Problem.

ich gelöst es durch einen Background Thread innerhalb der Funktion aufgerufen wird:

public static IMyServiceCallback Callback; 
. 
. 
. 

     TaskStateData taskStateData = GetSomeData(); 

     BackgroundWorker backgroundWorker = new BackgroundWorker(); 

     backgroundWorker.DoWork += (se, ev) => 
      { 
       Tuple<OperationContext, TaskStateData> data = ev.Argument as Tuple<OperationContext, TaskStateData>; 
       var operationContext = data.Item1; 

       if (operationContext != null) 
       { 
        Callback = operationContext.GetCallbackChannel<IMyServiceCallback>(); 
        Callback.OnCallBack(); 
       } 
      }; 

     Tuple<OperationContext, TaskStateData> payload = new Tuple<OperationContext, TaskStateData>(OperationContext.Current, taskStateData); 
     backgroundWorker.RunWorkerAsync(payload); 
Verwandte Themen