2009-11-17 4 views
6

Was ist der beste Weg, um einen neuen (optionalen) Parameter zu einem bestehenden Vorgang hinzuzufügen, ohne dass der Client seine WSDL aktualisieren muss? Ich möchte den Namespace nicht aktualisieren, um eine neue Version der Serviceverträge zu beschreiben, da diese mit älteren Clients abwärtskompatibel sein sollte.Hinzufügen eines neuen Parameters zu einer WCF-Operation: Auswahlen?

Sollte ich eine neue Operation mit einem neuen Parameter als Überladung hinzufügen? Oder sollte ich einfach den Parameter zur bestehenden Operation hinzufügen?

Hier ist mein Betrieb ist:

[OperationContract] 
MyResponse GetData(); 

es sein sollte:

[OperationContract] 
MyResponse GetData(); 

[OperationContract] 
MyResponse GetData(string filter); 

Oder einfacher, es ist einfach zu dies ändern: scheint

[OperationContract] 
MyResponse GetData(string filter); 

Letztere Option am besten, und gemäß meinem Nachschlagewerk "Die Auswirkung auf den Client ist keine. Neue Parameter werden initialisiert zu den Standardwerten am Dienst. "Initialisiert WCF es auf den so genannten Standardwert? Wenn ja, wie lautet der Standardwert?

Antwort

13

One zu beachten ist, dass Sie nicht zwei OperationContracts mit demselben Namen haben können.Die Art, wie es serialisiert wird, wird einen Fehler verursachen.

Der beste Ansatz ist, mit Option 3 zu gehen (nur den neuen Parameter hinzufügen) und innerhalb der Methode Logik-Konto für einen Null-Wert für die Clients, die noch nicht aktualisiert haben. Wenn es sich um eine bahnbrechende Änderung handelt, für die die Clients aktualisieren müssen, stellen Sie sicher, dass nicht die gesamte Anwendung aufgrund der Ausnahme abstürzt.

+2

Es ist eine nicht brechende Änderung. Ich handle, wenn der Filter null oder leer ist. –

+0

@Mike: Ich glaube nicht, dass es nicht bricht - plötzlich erwartet Ihre Methode "GetData" jetzt einen Parameter, der nicht von den ursprünglichen Anrufern geliefert wird. –

+2

@marc_s: aufgrund der Flexibilität von WCF so lange Wenn der Wert null sein kann, funktioniert ein Client, der ihm nichts übergibt. Das ist der Vorteil, wenn Versionsabweichungen in WCF zugelassen werden. –

2

Nun, einen bestehenden Vertrag zu ändern, nachdem er verwendet wurde, ist wirklich gegen alle Regeln der Serviceorientierung; Sie sollten niemals je einen bestehenden Vertrag brechen.

In der Realität geschieht dies recht häufig, und WCF ist ziemlich gut über das für Sie Umgang. Solange Sie nur non-breaking Änderungen einzuführen, werden auch weiterhin bestehende Kunden arbeiten.

Dies kann sein:

  • eine neue Operation Vertrag auf einen bestehenden Servicevertrag
  • ein neues nicht-obligatorisches Feld auf ein Datacontract

Was Sie versuchen zu arbeiten, ist nicht zu tun, gehen obwohl

  1. Sie können nicht zwei Methoden mit demselben Namen in WCF verwenden - WCF ist nicht .NET und Sie können nicht zwei Methoden mit dem gleichen Namen nur durch ihre Signatur unterscheiden. Funktioniert nicht. Sie müssen zwei verschiedene, eindeutige Namen verwenden. Denken Sie daran: Ihre WCF-Methodenaufrufe werden in ein WSDL-Dokument (Web Service Description Language) übersetzt, um den Service zu beschreiben - und WSDL unterstützt einfach nicht zwei Operationen mit demselben Namen - nur ein Unterschied in der Signatur wird nicht unterstützt und wird nicht funktionieren .

  2. Sie können den bestehenden Vertrag nicht ändern, z. Sie können nachträglich keinen neuen Parameter in einen Methodenaufruf einfügen, ohne den Vertrag zu brechen.

Also, was Sie wirklich tun müssen, ist dies:

[OperationContract] 
MyResponse GetData(); 

[OperationContract] 
MyResponse GetFilteredData(string filter); 

Jede andere Änderung, die Sie vorgeschlagen, den Vertrag a) brechen, oder b) einfach nicht in WCF arbeiten:

+0

ich mit Ihrem Vorschlag tatsächlich ging, aber Agent_9191 Antwort war mehr richtig in Bezug auf meine ursprüngliche Frage, so nahm ich seine Antwort und + 1'ed Ihnen. –

3

Sie können dies versuchen:

[OperationContract] 
MyResponse GetData(); 

[OperationContract(Name = "GetDataByFilter")] 
MyResponse GetData(string filter);