W oknie możemy wybrać między innymi, czy chcemy generować asynchroniczne wywołania operacji z Operation Contract-ów. Ponadto możemy wybrać, na jaki tym mają być rzutowane kolekcje (lista, tablica itd.). Co więcej, w przypadku, gdy strona kliencka i serwerowa znajdują się w jednej solucji, możemy reużywać niektóre typy zdefiniowane po stronie serwerowej.
Serwisy możemy wywoływać tworząc jawnie channele za pomocą klasy ChannelFactory<T> lub korzystając z wygenerowanych klas proxy, które przejmują odpowiedzialność tworzenia channeli.
bool useProxy = new Random().Next()%2 == 0; IEvaluationService channel = null; try { if (!useProxy) { //Transparent proxy ChannelFactory<IEvaluationService> factory = new ChannelFactory<IEvaluationService>("WSHttpBinding_IEvaluationService"); channel = factory.CreateChannel(); } else { //Generated proxy channel = new EvaluationServiceClient("WSHttpBinding_IEvaluationService"); } var eval = new Evaluation() { TimeSent = DateTime.Now, Comments = "Nice", Submitter = "Johnny" }; channel.SubmitEvaluation(new EvaluationRequest() { EvaluationBody = eval }); ((IClientChannel)channel).Close(); } catch (FaultException e) { ((IClientChannel)channel).Abort(); } catch (CommunicationException e) { ((IClientChannel)channel).Abort(); } catch (TimeoutException e) { ((IClientChannel)channel).Abort(); }
Ważne aby odpowiednio obsługiwać wyjątki w WCF.FaultException, to propagacja wyjątku powstałego w kodzie po stronie serwerowej. CommunicationException wynika ze złej konfiguracji endpointu po którejś ze stron (np. źle podana nazwa do konstruktora ChannelFactory). TimeoutException zostanie rzucony, jeżeli serwer nie odpowie przez dłużej niż ustalony przez klienta próg.
Podstawowa różnica pomiędzy poleceniami Close i Abort polega na tym, że pierwsze zamyka połączenie w sposób prawidłowy, natomiast drugie warto wykorzystywać, jeżeli chcemy zamknąć połączenie natychmiast. Polecenie Close zostaje wstrzymane do póki nie zakończą się wszystkie operacje, także te asynchroniczne, może ono także rzucić wyjątkiem typu CommunicationException lub TimeoutException.
Nazwa klasy klienckiej zostaje wygenerowana przez konwencję (odcięcie od nazwy interfejsu pierwszej litery "I" oraz dodanie na końcu "Client"). Również przez konwencję tworzone są metody asynchroniczne, do których podajemy callback, który wywoła się po otrzymaniu odpowiedzi.
var client = channel as EvaluationServiceClient; client.GetEvaluationsCompleted += (e, o) => Console.WriteLine(o.Result.Length); client.GetEvaluationsAsync();
Metadane można pobierać nie tylko przez VS czy svcutil, ale także w kodzie. Przykład poniżej.
var endpoints = MetadataResolver.Resolve(typeof (IEvaluationService), new EndpointAddress("http://localhost:8732/evals/mex/")); foreach (var endpoint in endpoints) Console.WriteLine(endpoint.Name);