Literatura Wprowadzenie Programowanie Systemów Rozproszonych - WCF Paweł Paduch Politechnika Świętokrzyska 15 kwietnia 2016 Paweł Paduch Programowanie Systemów Rozproszonych - WCF 1 z 57
Plan wykładu Literatura Wprowadzenie 1 Literatura Wprowadzenie 2 Serwis Program Hostujący Klient 3 IIS - Automatycznie IIS - Ręcznie Usługa Windows 4 Web Site Przekazywanie informacji o błędzie do klienta Komunikacja dwukierunkowa - Duplex Paweł Paduch Programowanie Systemów Rozproszonych - WCF 2 z 57
Literatura Literatura Wprowadzenie Strony dokumentacji MS https://msdn.microsoft.com/enus/library/dd456779(v=vs.110).aspx Andrew Troelsen - Język C# 2010 i platforma.net 4 Paweł Paduch Programowanie Systemów Rozproszonych - WCF 3 z 57
Literatura Wprowadzenie WCF (ang. Windows Communication Foundation) framework do budowania aplikacji opartej o serwisy. Używając WCF można wysyłać dane jako asynchroniczne komunikaty z jednego punktu końcowego (ang. Endpoint) do drugiego. To samo API wykorzystuje się do stworzenia komunikacji pomiędzy aplikacjami na tym samym komputerze, komputerami lokalnej czy globalnej sieci. Paweł Paduch Programowanie Systemów Rozproszonych - WCF 4 z 57
Zastosowania Literatura Wprowadzenie y zastosowań: Bezpieczne serwisy do przetwarzania informacji biznesowych Serwisy dostarczające bieżące dane np. o ruchu ulicznym czy serwisy monitorujące Komunikatory Aplikacje analityczne pobierające dane z wielu serwisów Wystawienie obiegu zleceń (workflow) Aplikacje silverlight zasilane z danych wystawionych przez serwis. Paweł Paduch Programowanie Systemów Rozproszonych - WCF 5 z 57
Model Literatura Wprowadzenie WCF bazuje na pojęciu komunikacji opartej na przesyłaniu wiadomości i wszystko co może być wymodelowane jako komunikat (np. żądanie http lub kolejka komunikatów MSMQ) może być reprezentowane w uniwersalnym modelu programowania. Dlatego można wykorzystać jedno API do różnego mechanizmu transportowego. Paweł Paduch Programowanie Systemów Rozproszonych - WCF 6 z 57
Model Literatura Wprowadzenie W modelu możemy wyróżnić: klientów, którzy inicjują komunikację serwisów, aplikacji które czekają i odpowiadają na zgłoszenia klientów. pojedyncza aplikacja może działać jednocześnie jako klient i serwer np. Duplex Services lub Peer-to-Peer Networking. Paweł Paduch Programowanie Systemów Rozproszonych - WCF 7 z 57
Endpoints Literatura Wprowadzenie Endpoints to punkty pomiędzy którymi komunikaty są wymieniane (wysyłka i/lub odbiór). Definiują one wszystkie informacje potrzebne do wymiany wiadomości. Serwis zwykle wystawia jeden lub kilka punktów końcowych aplikacji jak również 0 lub więcej punktów końcowych infrastruktury. Paweł Paduch Programowanie Systemów Rozproszonych - WCF 8 z 57
Endopoint Literatura Wprowadzenie Endopoint - może być częścią serwisu działającego ciągle np. osadzonego na IIS lub hostowany w aplikacji. Endpointem może być też klient zgłaszający się do serwera. Klient generuje endpoint kompatybilny z jednym z endpointów serwisu. Paweł Paduch Programowanie Systemów Rozproszonych - WCF 9 z 57
Nowy projekt Serwis Program Hostujący Klient Tworzymy nową solucję WCFWyklad a w niej projekt CalcServiceLibrary typu WCF Library Rysunek: Nowy projekt Paweł Paduch Programowanie Systemów Rozproszonych - WCF 10 z 57
Modyfikacje Serwis Program Hostujący Klient Zmieniamy nazwy IService1 i Service na ICalc i Calc Modyfikujemy linijkę a App.config: Listing 1: Zmiana w app.config 1 <add baseaddress="http://localhost:8733 /Design_Time_Addresses/CalcServiceLibrary/Calc/" /> Usuwamy wygenerowany przykład Echa Paweł Paduch Programowanie Systemów Rozproszonych - WCF 11 z 57
Interfejs Serwis Program Hostujący Klient Tworzymy nowy interfejs Listing 2: ICalc.cs 1 [ServiceContract(Namespace ="http://achilles.tu.kielce.pl")] 2 public interface ICalc 3 { 4 [OperationContract] 5 double Add(double a, double b); 6 7 [OperationContract] 8 double Sub(double a, double b); 9 10 [OperationContract] 11 double Mul(double a, double b); 12 13 [OperationContract] 14 double Div(double a, double b); 15 } Paweł Paduch Programowanie Systemów Rozproszonych - WCF 12 z 57
Implementacja interfejsu Serwis Program Hostujący Klient Tworzymy implementację Listing 3: Calc.cs 1 public double Add(double a, double b) 2 { return a + b; } 3 4 public double Div(double a, double b) 5 { if (b == 0) throw new DivideByZeroException(" parametr b nie moze byc 0"); 6 return a / b; } 7 8 public double Mul(double a, double b) 9 { return a * b; } 10 11 public double Sub(double a, double b) 12 { return a - b; } Można przetestować serwis (F5) Paweł Paduch Programowanie Systemów Rozproszonych - WCF 13 z 57
Nowy projekt Serwis Program Hostujący Klient Dodajemy nowy projekt do solucji typu Console Application Dodajemy referencję do projektu Dodajemy referencję do System.ServiceModel Dodajemy odpowiednie using do Program.cs: Listing 4: Dodatkowe przestrzenie nazw 1 using CalcServiceLibrary; 2 using System.ServiceModel; 3 using System.ServiceModel.Description; 4 Paweł Paduch Programowanie Systemów Rozproszonych - WCF 14 z 57
Main Serwis Program Hostujący Klient Listing 5: Adres oraz instancja serwisu 1 Uri baseaddress = new Uri("http://localhost:8000/CalculatorService/") ; 2 3 ServiceHost selfhost = new ServiceHost(typeof(Calc), baseaddress); Paweł Paduch Programowanie Systemów Rozproszonych - WCF 15 z 57
Main Serwis Program Hostujący Klient Ustanawiamy punkt końcowy usługi oraz umożliwiamy wymianę metadanych: Listing 6: Endpoint i wymiana danych 1 // Dodajemy Endopoint uslugi 2 selfhost.addserviceendpoint(typeof(icalc), new WSHttpBinding(), "CalculatorService"); 3 4 // Umozliwiamy wymiane metadanych 5 ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); 6 smb.httpgetenabled = true; 7 selfhost.description.behaviors.add(smb); Paweł Paduch Programowanie Systemów Rozproszonych - WCF 16 z 57
Main Serwis Program Hostujący Klient Startujemy i zamykamy serwis Listing 7: Start i zamknięcie serwisu 1 selfhost.open(); 2 Console.WriteLine("Serwis dziala..."); 3 Console.WriteLine("Nacisnij <ENTER> by zakonczyc."); 4 Console.WriteLine(); 5 Console.ReadLine(); 6 7 selfhost.close(); Można ustawić startup na bieżący projekt i uruchomić (F5) Paweł Paduch Programowanie Systemów Rozproszonych - WCF 17 z 57
Nowy projekt Serwis Program Hostujący Klient Dodajemy nowy projekt WPF Z Toolboxa po lewej dodajemy 3 razy textbox (textboxa, textboxb, textboxwynik) Ten ostatni można dać Disabled Dodajemy 4 guziki (buttonplus, buttonminu, buttonmnoz, buttondziel ja na rysunku 2 Paweł Paduch Programowanie Systemów Rozproszonych - WCF 18 z 57
Referencje i implementacja Serwis Program Hostujący Klient Uruchamiamy hosta z usługą w trybie bez debugowania (ctrl+f5) Dodajemy referencje do System.ServiceModel oraz service reference podając adres gdzie host wystawił naszą usługę Dodajemy using CalculatorClient.CalcServiceReference; do MainWindowXaml.cs Paweł Paduch Programowanie Systemów Rozproszonych - WCF 19 z 57
Implementacja Serwis Program Hostujący Klient W konstruktorze MainWindow dodajemy: Listing 8: Start serwisu 1 public MainWindow() 2 { 3 InitializeComponent(); 4 try 5 { 6 klient = new CalcServiceReference.CalcClient(); 7 } 8 catch (Exception ex) 9 { 10 MessageBox.Show("nie udalo sie stworzyc klienta CalcServiceReference. " + ex.message); 11 } 12 } dodajemy prywatne pole CalcClient klient = null; dodajemy obsługę ClosingWindow gdzie umieszczamy klient.close(); Paweł Paduch Programowanie Systemów Rozproszonych - WCF 20 z 57
Pobierz liczby Serwis Program Hostujący Klient Piszemy funkcję pobierającą dane z Textboxów Listing 9: pobierzliczby 1 bool pobierzliczby(out double a, out double b) 2 { 3 b = 0; 4 a = 0; 5 6 if (!double.tryparse(textboxparama.text, out a)) 7 { 8 MessageBox.Show("niepoprawna liczba a"); 9 return false; 10 } 11 if (!double.tryparse(textboxparamb.text, out b)) 12 { 13 MessageBox.Show("niepoprawna liczba b"); 14 return false; 15 } 16 return true; 17 } Paweł Paduch Programowanie Systemów Rozproszonych - WCF 21 z 57
Obsługa guzików Serwis Program Hostujący Klient Dodajemy i podpinamy funkcje do obsługi zdarzeń kliknięć Listing 10: Obsługa kliknięcia na guziku dodawania 1 private void buttonplus_click(object sender, RoutedEventArgs e) 2 { 3 double a, b; 4 if (pobierzliczby(out a, out b)) 5 { 6 textboxwynik.text = klient.add(a, b).tostring(); 7 } 8 } Jeżeli program hostujący uruchomiony możemy uruchomić naszego klienta (F5) Paweł Paduch Programowanie Systemów Rozproszonych - WCF 22 z 57
Przygotowanie nowej strony IIS - Automatycznie IIS - Ręcznie Usługa Windows Otwieramy menadżera IIS Dodajemy nową stronę Rysunek: Nowa strona Paweł Paduch Programowanie Systemów Rozproszonych - WCF 23 z 57
Zmiana architektóry IIS - Automatycznie IIS - Ręcznie Usługa Windows Dwukrotnie klikamy na puli aplikacji Zmieniamy na.net 4.0 Rysunek: Zmiana architektury na.net 4.0 Paweł Paduch Programowanie Systemów Rozproszonych - WCF 24 z 57
Deploy automatyczny IIS - Automatycznie IIS - Ręcznie Usługa Windows Tworzymy nowy projekt WCF Service App Wybieramy publikuj i klikamy custom. Rysunek: Publikacja serwisu Paweł Paduch Programowanie Systemów Rozproszonych - WCF 25 z 57
Deploy automatyczny IIS - Automatycznie IIS - Ręcznie Usługa Windows Wpisujemy odpowiednie dane... Rysunek: Dane do publikacji Paweł Paduch Programowanie Systemów Rozproszonych - WCF 26 z 57
Deploy automatyczny - problem IIS - Automatycznie IIS - Ręcznie Usługa Windows...i mamy pierwszy problem Rysunek: Nie można połączyć Należy włączyć Usługę zarządzania siecią Web - wmsvc Doinstalować też Web Deployment Tool https://technet.microsoft.com/plpl/library/dd569059(v=ws.10).aspx co spowoduje dodanie usługi Web Deployment Agent Service msdepsvc. Otworzyć na firewallu port 8172 Paweł Paduch Programowanie Systemów Rozproszonych - WCF 27 z 57
Deploy ręczny IIS - Automatycznie IIS - Ręcznie Usługa Windows Do CalcServiceLibrary dodaje plik Service.svc Listing 11: Service.svc 1 <%@ServiceHost language="c#" Debug="true" Service=" CalcServiceLibrary.Calc"%> Dodajemy też Web.config Paweł Paduch Programowanie Systemów Rozproszonych - WCF 28 z 57
Deploy ręczny IIS - Automatycznie IIS - Ręcznie Usługa Windows Listing 12: Web.config 1 <?xml version="1.0" encoding="utf-8"?> 2 <configuration> 3 <system.servicemodel> 4 <services> 5 <!-- This section is optional with the default configuration 6 model introduced in.net Framework 4 --> 7 <service name="calcservicelibrary.calc" behaviorconfiguration="defaultbehavior"> 8 <!-- This endpoint is exposed at the base address provided by host: http://localhost/webservices/service.svc --> 9 <endpoint address="" 10 binding="wshttpbinding" 11 contract="calcservicelibrary.icalc" /> 12 <!-- The mex endpoint is exposed at http://localhost/webservices/service.svc/mex --> 13 <endpoint address="mex" 14 binding="mexhttpbinding" 15 contract="imetadataexchange" /> 16 </service> 17 </services> 18 <behaviors> 19 <servicebehaviors > 20 <behavior name="defaultbehavior"> 21 <!-- To avoid disclosing metadata information, 22 set the values below to false before deployment --> 23 <!-- <servicemetadata httpgetenabled="true" httpsgetenabled="true"/>--> 24 <servicemetadata httpgetenabled="true" /> 25 26 <!-- To receive exception details in faults for debugging purposes, 27 set the value below to true. Set to false before deployment 28 to avoid disclosing exception information --> 29 <servicedebug includeexceptiondetailinfaults="true"/> 30 </behavior> 31 </servicebehaviors> 32 </behaviors> 33 </system.servicemodel> 34 </configuration> Paweł Paduch Programowanie Systemów Rozproszonych - WCF 29 z 57
Deploy ręczny IIS - Automatycznie IIS - Ręcznie Usługa Windows W katalogu gdzie wskazuje strona np. C:\inetpub\wwwroot\webservices\TestService wgrać pliki service.svc, Web.config oraz katalog bin. Jeżeli web config jest ok to powinno zadziałać. Uruchamiamy Developer Command Prompt for VS2015 i tam wpisujemy wcftestclient.exe podajemy adres naszej strony svc. Paweł Paduch Programowanie Systemów Rozproszonych - WCF 30 z 57
Nowy projekt usługi windows IIS - Automatycznie IIS - Ręcznie Usługa Windows Tworzymy nowy projekt nazwa CalcWindowsService Rysunek: Nowy projekt usługi windows Zmieniamy Service1 na CalcWinService Paweł Paduch Programowanie Systemów Rozproszonych - WCF 31 z 57
Nadanie nazwy usłudze IIS - Automatycznie IIS - Ręcznie Usługa Windows W CalcWindowsService.Designer.cs zmieniamy nazwę usługi Listing 13: CalcWindowsService.Designer.cs 1 private void InitializeComponent() 2 { 3 components = new System.ComponentModel.Container(); 4 this.servicename = "CalcWindowsService"; 5 } W CalcWinService.cs dodajemy referencje do System.ServiceModel i System.ServiceModel.Description i zmienną Listing 14: CalcWinService.cs 1 private ServiceHost m_svchost = null; Dodajemy referencje do proj CalcServiceLibrary i wstawiamy using o tej samej nazwie. Paweł Paduch Programowanie Systemów Rozproszonych - WCF 32 z 57
Metoda OnStart IIS - Automatycznie IIS - Ręcznie Usługa Windows Wypełniamy metodę OnStart w CalcWinService.cs Listing 15: CalcWinService.cs 1 protected override void OnStart(string[] args) 2 { 3 if (m_svchost!= null) m_svchost.close(); 4 5 string stradrhttp = "http://localhost:9001/calcservice"; 6 string stradrtcp = "net.tcp://localhost:9002/calcservice"; 7 8 Uri[] adrbase = { new Uri(strAdrHTTP), new Uri(strAdrTCP) }; 9 m_svchost = new ServiceHost(typeof(Calc), adrbase); 10 11 ServiceMetadataBehavior mbehave = new ServiceMetadataBehavior(); 12 m_svchost.description.behaviors.add(mbehave); 13 14 BasicHttpBinding httpb = new BasicHttpBinding(); 15 m_svchost.addserviceendpoint(typeof(icalc), httpb, stradrhttp); 16 m_svchost.addserviceendpoint(typeof(imetadataexchange), 17 MetadataExchangeBindings.CreateMexHttpBinding(), "mex"); 18 19 NetTcpBinding tcpb = new NetTcpBinding(); 20 m_svchost.addserviceendpoint(typeof(icalc), tcpb, stradrtcp); 21 m_svchost.addserviceendpoint(typeof(imetadataexchange), 22 MetadataExchangeBindings.CreateMexTcpBinding(), "mex"); 23 24 m_svchost.open(); 25 } Paweł Paduch Programowanie Systemów Rozproszonych - WCF 33 z 57
Metoda OnStop IIS - Automatycznie IIS - Ręcznie Usługa Windows Wypełniamy metodę OnStop w CalcWinService.cs Listing 16: CalcWinService.cs 1 protected override void OnStop() 2 { 3 if (m_svchost!= null) 4 { 5 m_svchost.close(); 6 m_svchost = null; 7 } 8 } Paweł Paduch Programowanie Systemów Rozproszonych - WCF 34 z 57
Dodanie instalatora usługi IIS - Automatycznie IIS - Ręcznie Usługa Windows Otworzyć CalcWinService w trybie designera Prawym klawiszem otworzyć menu kontekstowe i wybrać add installer Rysunek: Dodanie instalatora Zmieniamy nazwę ProjectInstaller na CalcServiceInstaller Paweł Paduch Programowanie Systemów Rozproszonych - WCF 35 z 57
CalcServiceInstaller IIS - Automatycznie IIS - Ręcznie Usługa Windows Kalwiszem F7 przełączmy się na kod i uzupełniamy go Listing 17: CalcServiceInstaller.cs 1 public CalcServiceInstaller() 2 { 3 // InitializeComponent(); 4 serviceprocessinstaller1 = new ServiceProcessInstaller(); 5 serviceprocessinstaller1.account = ServiceAccount.LocalSystem; 6 serviceinstaller1 = new ServiceInstaller(); 7 serviceinstaller1.servicename = "CalcWinService"; 8 serviceinstaller1.displayname = "Kalkulator Serwis"; 9 serviceinstaller1.description = "WCF Kalkulator Serwis, przykladowy serwis hostowany w usludze windows"; 10 serviceinstaller1.starttype = ServiceStartMode.Automatic; 11 Installers.Add(serviceProcessInstaller1); 12 Installers.Add(serviceInstaller1); 13 } Paweł Paduch Programowanie Systemów Rozproszonych - WCF 36 z 57
Instalacja i start usługi IIS - Automatycznie IIS - Ręcznie Usługa Windows Otwieramy Command Prompt z uprawnieniami administratora i przechodzimy do katalogu gdzie znajduje się CalcWindowsService.exe Wykonujemy polecenie: InstallUtil CalcWindowsService.exe Start usługi: sc start CalcWinService lub z menadżera usług: Rysunek: Zarządzanie usługami usługa powinna być widoczna pod http://localhost:9001/calcservice Paweł Paduch Programowanie Systemów Rozproszonych - WCF 37 z 57
Zatrzymanie i usunięcie usługi IIS - Automatycznie IIS - Ręcznie Usługa Windows Zatrzymanie sc stop CalcWinService Usunięcie InstallUtil /u CalcWindowsService.exe Mamiętaj! Gdy zmieniamy nazwę usługi należy ją najpierw odinstalować przed skompilowaniem nowej wersji ponieważ deinstalator posługując się plikiem exe nie znajdzie usługi o starej nazwie Można ewentualnie też tak: net stop ServiceName sc delete ServiceName Gdyby był błąd 1072 to trzeba sprawdzić czy nie ma uruchomionego menadżera usług, mmc lub ProcessExplorera Paweł Paduch Programowanie Systemów Rozproszonych - WCF 38 z 57
Nowy projekt Web Site Web Site Przekazywanie informacji o błędzie do klienta Komunikacja dwukierunkowa - Duplex Do solucji dodajemy nowy web site (z menu kontekstowego wybieramy add new web site) Rysunek: Nowy Web Site Do projektu dodajemy nowy formularz Web Form i zostawiamy nazwę Default.aspx Paweł Paduch Programowanie Systemów Rozproszonych - WCF 39 z 57
Formatka Web Site Przekazywanie informacji o błędzie do klienta Komunikacja dwukierunkowa - Duplex Uzupełniamy kod dodanej formatki Default.aspx Listing 18: Default.aspx 1 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> 2 3 <!DOCTYPE html> 4 5 <html xmlns="http://www.w3.org/1999/xhtml"> 6 <head runat="server"> 7 <title></title> 8 </head> 9 <body> 10 <form id="form1" runat="server"> 11 <div> 12 <asp:label ID="Label1" runat="server" 13 Text="Wartosc 1 : "></asp:label> 14 <asp:textbox ID="txtVal1" runat="server"></asp:textbox> 15 <br /> 16 <asp:label ID="Label2" runat="server" 17 Text="Wartosc 2 : "></asp:label> 18 <asp:textbox ID="txtVal2" runat="server"></asp:textbox> 19 <br /> 20 <asp:button ID="btnCalc" runat="server" 21 onclick="btncalc_click" Text="Oblicz" 22 Width="91px" /> 23 <br /> 24 <asp:label ID="lblOutput" runat="server" 25 BorderStyle="None" Height="152px" 26 Width="606px"></asp:Label> 27 </div> 28 </form> 29 </body> 30 </html> Paweł Paduch Programowanie Systemów Rozproszonych - WCF 40 z 57
Service Reference Web Site Przekazywanie informacji o błędzie do klienta Komunikacja dwukierunkowa - Duplex Dodajemy referencje do serwisu Rysunek: Nowy Web Site Stworzy nam to katalog App WebReferences oraz zmodyfikuje web.config Paweł Paduch Programowanie Systemów Rozproszonych - WCF 41 z 57
Default.aspx.cs Web Site Przekazywanie informacji o błędzie do klienta Komunikacja dwukierunkowa - Duplex Listing 19: Default.aspx.cs 1 protected void btncalc_click(object sender, EventArgs e) 2 { double dblx = 0, dbly = 0; 3 bool b1 = double.tryparse(txtval1.text, out dblx); 4 bool b2 = double.tryparse(txtval2.text, out dbly); 5 6 if ((b1) && (b2)) 7 { StringBuilder sbtmp = new StringBuilder("<font size=3 color=#000080>"); 8 9 sbtmp.append("<p>wprowadzono<br>wartosc 1 : " + dblx.tostring("f2")); 10 sbtmp.append("<br>wartosc 2 : " + dbly.tostring("f2")); 11 sbtmp.append("<p>obliczam za pomoca HTTP Binding"); 12 13 ServiceReferenceCalc.CalcClient calcproxy1 = new ServiceReferenceCalc.CalcClient("BasicHttpBinding_ICalc"); 14 double dblresult = calcproxy1.add(dblx, dbly); 15 sbtmp.append("<br>wolam Add >"); 16 sbtmp.append(dblresult.tostring()); 17 dblresult = calcproxy1.sub(dblx, dbly); 18 sbtmp.append("<br>wolam Sub >"); 19 sbtmp.append(dblresult.tostring()); 20 dblresult = calcproxy1.mul(dblx, dbly); 21 sbtmp.append("<br>wolam Mul >"); 22 sbtmp.append(dblresult.tostring()); 23 dblresult = calcproxy1.div(dblx, dbly); 24 sbtmp.append("<br>wolam Div >"); 25 sbtmp.append(dblresult.tostring()); 26 ServiceReferenceCalc.CalcClient calcproxy2 = new ServiceReferenceCalc.CalcClient("NetTcpBinding_ICalc"); 27 sbtmp.append("<p>obliczam za pomoca NetTcp Binding"); 28 dblresult = calcproxy2.add(dblx, dbly); 29 sbtmp.append("<br>wolam Add >"); 30 sbtmp.append(dblresult.tostring()); 31 dblresult = calcproxy2.sub(dblx, dbly); 32 sbtmp.append("<br>wolam Sub >"); 33 sbtmp.append(dblresult.tostring()); 34 dblresult = calcproxy2.mul(dblx, dbly); 35 sbtmp.append("<br>wolam Mul >"); 36 sbtmp.append(dblresult.tostring()); 37 dblresult = calcproxy2.div(dblx, dbly); 38 sbtmp.append("<br>wolam Div >"); 39 sbtmp.append(dblresult.tostring()); 40 lbloutput.text = sbtmp.tostring(); 41 } 42 } Paweł Paduch Programowanie Systemów Rozproszonych - WCF 42 z 57
Przekazywanie wyjątków do klienta Web Site Przekazywanie informacji o błędzie do klienta Komunikacja dwukierunkowa - Duplex Jeżeli chcemy przekazać klientowi wyjątek wygenerowany po stronie serwera należy zmodyfikować zachowanie serwisu Można to zrobić z poziomu kodu Listing 20: Włączenie przekazywania szczegółów wyjątków 1 ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); 2 smb.httpgetenabled = true; 3 selfhost.description.behaviors.find<servicedebugbehavior>(). IncludeExceptionDetailInFaults = true; 4 selfhost.description.behaviors.add(smb); Paweł Paduch Programowanie Systemów Rozproszonych - WCF 43 z 57
Przekazywanie wyjątków do klienta Web Site Przekazywanie informacji o błędzie do klienta Komunikacja dwukierunkowa - Duplex Można to zrobić w konfiguracji serwisu Listing 21: Włączenie przekazywania szczegółów wyjątków 1 <!-- To receive exception details in faults for debugging purposes, 2 set the value below to true. Set to false before deployment 3 to avoid disclosing exception information --> 4 <servicedebug includeexceptiondetailinfaults="true"/> 5 </behavior> 6 </servicebehaviors> 7 </behaviors> 8 </system.servicemodel> 9 10 </configuration> Paweł Paduch Programowanie Systemów Rozproszonych - WCF 44 z 57
Zwracanie błędu Web Site Przekazywanie informacji o błędzie do klienta Komunikacja dwukierunkowa - Duplex Aby przekazać bład do klienta można posłużyć się klasą FaultException Listing 22: Przekazywanie błedów do klientów 1 throw new FaultException("Nie dziel przez 0!", new FaultCode("Zle parametry wejsciowe!")); Paweł Paduch Programowanie Systemów Rozproszonych - WCF 45 z 57
Duplex Contract Web Site Przekazywanie informacji o błędzie do klienta Komunikacja dwukierunkowa - Duplex Duplex Service Contract jest paternem dwukierunkowej wymiany komunikatów pomiędzy dwoma endpointami Duplex Service może odesłać wiadomość do klienta poprzez kanał zwrotny, który klient udostępnia serwisowi. Żeby stworzyć kontrakt typu duplex potrzebujemy pary interfejsów. Pierwszym jest Service Contract Interface, który opisuje operacje jaki klient może wywoływać na serwisie. W tym kontrakcie definiujemy też interfejs dla klienta tzw. Callback Contract w atrybucie ServiceContractAttribute.CallbackContract Callback Contract jest interfejsem opisującym co może serwis zrobić u klienta. Paweł Paduch Programowanie Systemów Rozproszonych - WCF 46 z 57
Nowy projekt Web Site Przekazywanie informacji o błędzie do klienta Komunikacja dwukierunkowa - Duplex Dodajemy nowy projekt WCF Service Application o nazwie WCFTestApp Rysunek: Nowy projekt WCF Paweł Paduch Programowanie Systemów Rozproszonych - WCF 47 z 57
Zmiana nazw Web Site Przekazywanie informacji o błędzie do klienta Komunikacja dwukierunkowa - Duplex Service1 zmieniamy na DuplexTest modyfikujemy zawartość DuplexTest.svc (prawy klawisz myszy,,view Markup ) Zamieniamy Service1 na DuplexTest usuwamy domyślną zawartość w plikach *.cs Paweł Paduch Programowanie Systemów Rozproszonych - WCF 48 z 57
Definicja Interfejsów Web Site Przekazywanie informacji o błędzie do klienta Komunikacja dwukierunkowa - Duplex W pliku IDuplexText.cs Definiujemy dwa interfejsy wraz z odpowiednimi atrybutami: Listing 23: Interfejsy 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Runtime.Serialization; 5 using System.ServiceModel; 6 using System.ServiceModel.Web; 7 using System.Text; 8 9 namespace DuplexTestApp 10 { 11 public interface IKontraktZwrotny 12 { 13 [OperationContract(IsOneWay = true)] 14 void FunkcjaZwrotna(string str); 15 } 16 [ServiceContract (CallbackContract = typeof(ikontraktzwrotny))] 17 public interface IDuplexTest 18 { 19 [OperationContract(IsOneWay = true)] 20 void DodajSlowo(string str); 21 } 22 } Paweł Paduch Programowanie Systemów Rozproszonych - WCF 49 z 57
Implementacja DuplexTest.cs Web Site Przekazywanie informacji o błędzie do klienta Komunikacja dwukierunkowa - Duplex W pliku DuplexTest realizujemy zadany interfejs. Listing 24: DuplexTest.svc.cs 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Runtime.Serialization; 5 using System.ServiceModel; 6 using System.ServiceModel.Web; 7 using System.Text; 8 9 namespace DuplexTestApp 10 { 11 12 public class DuplexTest : IDuplexTest 13 { 14 IKontraktZwrotny callback = null; 15 List<string> listaslow = null; 16 public DuplexTest() 17 { 18 listaslow = new List<string>(); 19 callback = OperationContext.Current.GetCallbackChannel<IKontraktZwrotny>(); 20 } 21 public void DodajSlowo(string str) 22 { 23 if (listaslow!= null) listaslow.add(str); 24 callback.funkcjazwrotna("otrzymalem slowo: " + str + ". Liczba slow: " + listaslow.count()); 25 } 26 } 27 } Paweł Paduch Programowanie Systemów Rozproszonych - WCF 50 z 57
Implementacja DuplexTest.cs Web Site Przekazywanie informacji o błędzie do klienta Komunikacja dwukierunkowa - Duplex W pliku Web.config modyfikujemy konfiguracje tak by serwis obsługiwał tryb duplex, dodajemy nasz serwis Listing 25: Web.config 1 <system.servicemodel> 2 <behaviors> 3 <servicebehaviors> 4 <behavior name ="duplexbehav"> 5 <!-- To avoid disclosing metadata information, set the values below to false before deployment --> 6 <servicemetadata httpgetenabled="false" httpsgetenabled="false"/> 7 <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information --> 8 <servicedebug includeexceptiondetailinfaults="true"/> 9 </behavior> 10 </servicebehaviors> 11 </behaviors> 12 <services> 13 <service name="duplextestapp.duplextest" behaviorconfiguration="duplexbehav"> 14 <host> 15 <baseaddresses> 16 <add baseaddress="http://localhost:9000/duplextest"/> 17 </baseaddresses> 18 </host> 19 <endpoint name ="duplexendpoint" 20 address="" 21 binding="wsdualhttpbinding" 22 contract="duplextestapp.iduplextest"/> 23 <endpoint name ="MetaDataTcpEndpoint" 24 address="mex" 25 binding="mexhttpbinding" 26 contract="imetadataexchange"/> 27 </service> 28 </services> 29 <!--<protocolmapping> 30 <add binding="basichttpsbinding" scheme="https"/> 31 </protocolmapping>--> 32 <servicehostingenvironment aspnetcompatibilityenabled="true" multiplesitebindingsenabled="true"/> 33 </system.servicemodel> Paweł Paduch Programowanie Systemów Rozproszonych - WCF 51 z 57
Uruchomienie Web Site Przekazywanie informacji o błędzie do klienta Komunikacja dwukierunkowa - Duplex Można prawym klawiszem myszy otworzyć menu kontekstowe na pliku e i wybrać View in Browser Możemy też hostawać serwis na IIS jak pokazano na innych slajdach. Paweł Paduch Programowanie Systemów Rozproszonych - WCF 52 z 57
Klient Web Site Przekazywanie informacji o błędzie do klienta Komunikacja dwukierunkowa - Duplex Mając uruchomiony serwis, tworzymy nową aplikację konsolową: Dodaj nowy projekt o nazwe DuplexTestProgram Dodaje referencje do System.ServiceModel oraz service reference do naszej usługi Np. http:anakin.kin.tu.kielce.pl:8002duplextest.svc Nadajemy przestrzeń nazw dla nowej referencji DuplexTestRef Do programu dodajemy nową klasę Odpowiadacz Paweł Paduch Programowanie Systemów Rozproszonych - WCF 53 z 57
Klasa Odpowiadacz Web Site Przekazywanie informacji o błędzie do klienta Komunikacja dwukierunkowa - Duplex Listing 26: Odpowiadacz.cs 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.ServiceModel; 7 using DuplexTestProgram.DuplexTestRef; 8 9 namespace DuplexTestProgram 10 { 11 class Odpowiadacz : IDuplexTestCallback, IDisposable 12 { 13 DuplexTestClient proxy; 14 15 public void FunkcjaZwrotna(string str) 16 %{ 17 Console.WriteLine("Zwrotnie dostalem: " + str); 18 } 19 20 public void zawolajserwis(string str) 21 { 22 InstanceContext context = new InstanceContext(this); 23 proxy = new DuplexTestClient(context); 24 proxy.dodajslowo(str); 25 } 26 27 public void Dispose() 28 { 29 proxy.close(); 30 } 31 } 32 } Paweł Paduch Programowanie Systemów Rozproszonych - WCF 54 z 57
Główny program Web Site Przekazywanie informacji o błędzie do klienta Komunikacja dwukierunkowa - Duplex Listing 27: Program.cs 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace DuplexTestProgram 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 Odpowiadacz odp = new Odpowiadacz(); 14 odp.zawolajserwis("kuku"); 15 Console.ReadLine(); 16 odp.dispose(); 17 } 18 } 19 } Paweł Paduch Programowanie Systemów Rozproszonych - WCF 55 z 57
Pytania Web Site Przekazywanie informacji o błędzie do klienta Komunikacja dwukierunkowa - Duplex? Paweł Paduch Programowanie Systemów Rozproszonych - WCF 56 z 57
koniec Web Site Przekazywanie informacji o błędzie do klienta Komunikacja dwukierunkowa - Duplex Dziękuję Państwu za uwagę. Paweł Paduch Programowanie Systemów Rozproszonych - WCF 57 z 57