Jedną z głównych korzyści używania WCF’a jest możliwość łatwego oddzielenie serwisu od aplikacji klienckich. Sprawia to, że klient, który używa takiego serwisu wie jedynie o formacie danych jakie należy przesłać lub odebrać z serwisu a co za tym idzie, aplikacja napisana w innym języku niż serwis może z łatwością z tego serwisu korzystać. Niekiedy zdarza się jednak, że w miarę upływu czasu serwis i aplikacja ewoluują, pewne nowe funkcjonalności lub dodatkowe struktury danych zostają do nich dodane, niektóre usunięte. Celem odpowiedniej komunikacji jest uzyskanie tzw. „version tolerance” poprzez umożliwienie serwisowi i aplikacji klienckiej na rozwijanie swoich własnych wersji kontraktów. Generalnie sprawa sprowadza się do tego iż każda aplikacja kliencka powinna być w stanie komunikować się z każdą wersją serwisu, którego używa. Aby umożliwić taką „tolerancję na wersję”, WCF daje nam narządzie do wspierania czegoś co nazywa się „kompatybilnością w przód i w tył”.
W przypadku gdy nowe typy zostały dodane do kontraktu, DataContractSerializer po prostu takie dane zignoruje przy deserializacji, sprawiając że serwis i klient będzie mógł zaakceptować przychodzące dane, mimo tego iż wiadomość zawiera nowe dane które nie były częścią oryginalnego kontraktu. Działa to w dwie strony – w przypadku gdy kontrakt po stronie klienta został zmieniony a serwis nadal używa oryginalnego kontraktu i vice versa.
W przypadku gdy pewne typy zostały usunięte z kontraktu, domyślnym zachowaniem WCF jest próba zaakceptowania danych lub wysłania danych do klienta z brakującymi danymi. Najczęstszym scenariuszem będzie scenariusz, w którym serwis posiada nową wersję kontraktu a klient starszą. W tym przypadku dla wszystkich właściwości, które w wiadomości mogą pojawić się opcjonalnie ( IsRequired=false), DataContractSerializer będzie starał się zserializować ich wartości do ich wartości domyślnych – null dla typów referencyjnych i zero dla typów wartościowych. W przypadku gdy taka usunięta właściwość była wymagana (IsRequired=true), zostanie wyrzucony wyjątek.
Roundtripping
Weźmy pod uwagę następującą sytuację: Klient używa kontraktu w wersji 1.0, serwis używa kontraktu w wersji 2.0. Wersja 2.0 kontraktu ma dodanych kilka pól i/lub właściwości, o których klient (używając wersji 1.0) nie ma pojęcia. Przypuśćmy dalej, że serwis zwraca dane używając kontraktu w wersji 2.0 do klienta używającego kontraktu w wersji 1.0 i spodziewa się, że klient zmodyfikuje pewne dane i odeśle je dalej do serwisu. Czy jest zatem możliwość, aby klient takie dane, o których nie wie zmodyfikował i następnie odesłał je do serwisu? Odpowiedź brzmi tak! Może być to osiągnięte za pomocą tzw. „versioning roundtrip”, które wspierane jest w WCF.
Taki typ wersjonowania w WCF osiąga się za pomocą interfejsu IExtensibleDataObject
[DataContract]
public class Task: IExtensibleDataObject
{
private ExtensionDataObject extensionData;
[DataMember(IsRequired=true, Order=1)]
public string Description;
public ExtensionDataObject ExtensionData
{
get {return extensionData;}
set { extensionData=value;}
}
}
W powyższym przykładzie extensionData jest “kontenerem” w którego DataContractSerializer może “zapakować” wszystkie nieznane typy. Dzięki temu, że kontrakt implementuje interfejs IExtensibleDataObject, DataContractSerializer wie jak to zrobić. Dzięki powyższej implementacji, klient może odczytać takie „nieznane” dane i odesłać je spowrotem do serwisu.
zbyt skomplikowane dla mnie ;/
OdpowiedzUsuńMoże wydawać się skomplikowane na pierwszy rzut oka, jednak w rzeczywistości takie nie jest. Troszkę praktyki i myślę, że będziesz śmigała w tym temacie;)
OdpowiedzUsuń