Free Trial

Safari Books Online is a digital library providing on-demand subscription access to thousands of learning resources.

  • Create BookmarkCreate Bookmark
  • Create Note or TagCreate Note or Tag
  • PrintPrint
Share this Page URL
Help

8. Talking to WCF and ASMX Services > Invoking a service that exposes data

Invoking a service that exposes data

Invoking a service that exposes data Applies to Silverlight 3, 4 and 5 When working on a Silverlight project that involves services, WCF is the preferred choice for building a service if we have to create both the service and the Silverlight client application that will use it. Using WCF gives us complete control over what types will be sent to the client and for each type. We can also specify whether or not a field should be included in the client-side copy of the type. When we want to build a Silverlight application that works with the data available on the service (perhaps coming from a database or another external service), we need to ask ourselves two questions. How should we design the service that exposes the data so that it can be accessible from Silverlight? Secondly, how should we go about designing the Silverlight application so that it communicates with the service? In this recipe, we'll take a look at finding answers to both these questions. Getting ready We'll build the application in this recipe from scratch. However, the complete code for this recipe can be found in the Chapter08/SilverlightEmployeeBrowser folder in the downloads for this book. How to do it... To show how we can connect from Silverlight to a WCF service that exposes data, we'll start quite logically with designing the service itself. For this recipe, we'll assume that we are building an easy employee overview screen, where the user can see all the employee information. The employee data is exposed by the service. The Silverlight application will connect to the service and work with the data on the client side. The following are the steps we need to execute to get this working: For this recipe, we'll start from an empty Silverlight application. Create a new Silverlight solution in Visual Studio, and name it SilverlightEmployeeBrowser. As usual, Visual Studio will create a solution containing both a Silverlight application called SilverlightEmployeeBrowser and a hosting website called SilverlightEmployeeBrowser.Web.Let's first focus on the web application. The data we want to expose consists of employee data. The following class diagram shows the relation. Add all the classes and the CarType enumeration in a folder called Model within the project. Note that Employee is an abstract base class: The following is the code for the Employee class. Note the attributes added to the class. By specifying the DataContractAttribute, we state that this type can be sent over the wire, therefore becoming available on the client-side. Also, we have marked all fields with the DataMemberAttribute. Every field that is attributed with the DataMemberAttribute will be included in the type being sent over the wire to the client side. Finally, we also add the KnownTypeAttribute in the base class. This attribute marks the types that should be included in the serialization process as follows: [DataContract] [KnownType(typeof(Manager))] [KnownType(typeof(Consultant))] [KnownType(typeof(Maintenance))] public abstract class Employee { [DataMember] public int EmployeeId { get; set; } [DataMember] public string FirstName { get; set; } [DataMember] public string LastName { get; set; } [DataMember] public DateTime DateOfBirth { get; set; } } The new attributes require a new using statement for the System.Runtime.Serialization added at the top of this class. public class Manager : Employee { [DataMember] public CarType LeasedCar { get; set; } [DataMember] public double Bonus { get; set; } } The other classes in the hierarchy are similar and can be found in the completed sample.Next, we will create a class called EmployeeRepository that will load in the sample data. In a real-world scenario, we would load data from a database or an external service. The following is the code for this class. It uses a static List<Employee> that is filled upon first creation of the EmployeeRepository class: public class EmployeeRepository { private static List<Employee> allEmployees; public EmployeeRepository() { FillEmployees(); } private void FillEmployees() { if(allEmployees == null) { allEmployees = new List<Employee>() { new Manager() { EmployeeId=1, FirstName="Gill", LastName="Cleeren", LeasedCar=CarType.SportsCar, Bonus=10000.00, DateOfBirth=new DateTime(1980, 1, 1) }, new Consultant() { EmployeeId=2, FirstName="John", LastName="Smith", LeasedCar=CarType.FamilyCar, DateOfBirth=new DateTime(1976, 11, 9) }, new Consultant() { EmployeeId=3, FirstName="Jeff", LastName="Jones", LeasedCar=CarType.SecondHandCar, DateOfBirth=new DateTime(1983, 3, 12) }, new Consultant() { EmployeeId=4, FirstName="Lindsey", LastName="Clarks", LeasedCar=CarType.FamilyCar, DateOfBirth=new DateTime(1984, 6, 7) }, new Maintenance() { EmployeeId=5, FirstName="Clay", LastName="Richards", DateOfBirth=new DateTime(1960, 9, 22) }, new Maintenance() { EmployeeId=6, FirstName="Marie", LastName="Smith", DateOfBirth=new DateTime(1963, 2, 19) }, }; } } public List<Employee> AllEmployees { get { return allEmployees; } } } Now that we have the model and the repository, we're ready to add a WCF service to this project. Right-click on the SilverlightEmployeeBrowser.Web project node in the Solution Explorer and select Add | New Item.... In the Add New Item dialog, we have two options for adding a WCF service—a regular WCF Service and a Silverlight-enabled WCF Service. Select the latter and name the service EmployeeService. Visual Studio will add a *.svc file, a *.svc.cs file, and make some changes in the web.config file to make the service accessible.The service exposes two methods. The first one retrieves all employees, while the second one retrieves an employee based on the employee's ID. Each method or operation that should be available on the client side needs to be attributed with the OperationContract attribute. In a WCF scenario, the service itself should have the ServiceContract attribute. The service with its two methods is shown in the following code: [ServiceContract(Namespace = "")] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] public class EmployeeService { [OperationContract] public List<Employee> GetAllEmployees() { return new Model.EmployeeRepository().AllEmployees; } [OperationContract] public Employee GetEmployeeById(int employeeId) { return new Model.EmployeeRepository().AllEmployees.Where (e => e.EmployeeId == employeeId).FirstOrDefault(); } } We're now ready on the server side. Build the project before continuing.In the Silverlight application, right-click on the project node in the Solution Explorer and select Add Service Reference.... In the dialog box that appears, click on the Discover button, and if the service can be connected to without errors, it will appear in the list as shown in the following screenshot. Select the service and enter EmployeeService in the Namespace: field. An error will occur if the service wasn't built. After clicking on the OK button, Visual Studio will attempt to build a proxy that is roughly a client-side copy of the service class: The UI of the application is very simple. The complete code list can be found in the code downloads. As shown a bit later in this recipe, it contains a TextBox and a Button, which should trigger a call to the GetEmployeeId service operation. The retrieved details are to be shown in a detailed grid. Also, while loading the application for the first time, a call to the GetAllEmployees method should be triggered and the result of this call should be shown in the DataGrid. Here we'll focus on the latter.When the control has loaded, a call to the LoadEmployees method is invoked. In this method, we create an instance of the proxy class, which was generated by Visual Studio when we connected with the service. Next, we specify the callback method. Communication with a WCF service, similar to all other types of service connections, will take place asynchronously. Finally, we perform the actual invocation of the service method. All this is shown in the following code: private void UserControl_Loaded(object sender, RoutedEventArgs e) { LoadAllEmployees(); } private void LoadAllEmployees() { EmployeeService.EmployeeServiceClient proxy = new SilverlightEmployeeBrowser.EmployeeService .EmployeeServiceClient(); proxy.GetAllEmployeesCompleted += proxy_GetAllEmployeesCompleted; proxy.GetAllEmployeesAsync(); } If no errors occurred in the callback method, we get access to the result of the service call via the Result property of the SilverlighttEmployeeBrowser.EmployeeService.GetAllEmployeesCompletedEventArgs parameter. This property is of the same type as returned by the service method (in this case a List<SilverlighttEmployeeBrowser.EmployeeService.Employee>). For the DataGrid, we set the list as ItemsSource as shown in the following code: void proxy_GetAllEmployeesCompleted(object sender, SilverlightEmployeeBrowser.EmployeeService .GetAllEmployeesCompletedEventArgs e) { if (e.Error == null) EmployeeDataGrid.ItemsSource = e.Result; else ErrorTextBlock.Text = "An error occurred while communicating to the service"; } All employees should now be shown in the DataGrid, as shown in the following screenshot. Calling the GetEmployeeById operation is similar. The code for this can be found in the code downloads: How it works... WCF services are a preferred way of authoring services in the .NET framework. From the Silverlight point of view, the WCF services are also the best choice. Let's take a look at the specifics for both the service and the Silverlight application connecting to the service. The WCF service Adding a WCF service is possible using one of the two item templates available in Visual Studio—the WCF Service template or the Silverlight-enabled WCF Service template. The first one configures the service to use wsHttpBinding, which is the default for WCF. However, Silverlight can't work with this type of binding. So, if we choose to use this template, we need to configure the web.config manually, so that the service uses basicHttpBinding as shown in the following code: <system.serviceModel> <services> <service behaviorConfiguration="SilverlightEmployeeBrowser .Web.EmployeeServiceBehavior" name="SilverlightEmployeeBrowser.Web.EmployeeService"> <endpoint address="" binding="basicHttpBinding" contract="SilverlightEmployeeBrowser .Web.IEmployeeService"> <identity> <dns value="localhost" /> </identity> </endpoint> </service> </services> </system.serviceModel> However, if we use the Silverlight-enabled WCF Service template, the service will get configured automatically, so that it'll work when accessed from a Silverlight application. This is shown in the following code snippet: <system.serviceModel> <behaviors> ... </behaviors> <bindings> <customBinding> <binding name="customBinding0"> <binaryMessageEncoding/> <httpTransport> <extendedProtectionPolicy policyEnforcement="Never"/> </httpTransport> </binding> </customBinding> </bindings> <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/> <services> <service behaviorConfiguration="SilverlighttEmployeeBrowser .Web.EmployeeServiceBehavior" name="SilverlighttEmployeeBrowser.Web.EmployeeService"> <endpoint address="" binding="customBinding" bindingConfiguration="customBinding0" contract="SilverlighttEmployeeBrowser.Web .EmployeeService"/> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> </service> </services> </system.serviceModel> Note that the service is using binary message encoding by default, so that the data will get compressed when sent over the wire, resulting in quicker transfers. When creating a WCF service, we need to specify what will be exposed over the service. In more detail, we need to specify the operations that can be invoked on the service through the use of a service contract and the types that will be sent over the wire for the client application to use. Each class that should be available on the client side needs to be marked with the DataContract attribute. In these classes, we can specify which fields should go over the wire. Only those fields marked with the DataMemberAttribute will be sent to the client. Thus, we have granular control over what will and what will not be sent to the client-side application. Connecting to the service Once the service is in place, we can connect to it from the Silverlight application. This can be done using the Add Service Reference dialog box. Visual Studio will create a proxy class when the connection is made. This class contains a client-side copy of the types exposed by the service (for example, the Employee and the Manager class) and a copy of the service methods among others. However, code is generated for each service method that makes it possible to call the service asynchronously. The actual service code is not copied to the proxy. To view this code, click on the Show All Files button located at the top of the Solution Explorer. Then, select the + sign in front of the service reference and expand it, so that the Reference.cs file is shown, which contains the code for the proxy class. The requirement of calling the service asynchronously can also be seen in the code that's written in the Silverlight application itself. We start by instantiating the proxy class. On this instance, we define the callback method for the XXX_Completed event. Finally, we perform the service invocation by calling the XXX_Async method, which launches the request to the service. If the call is not carried out asynchronously, the application will cause the UI thread to hang until the service returns. The callback method is invoked once the service returns. In this method, we have access to the result via the e.Result property. This property will be of the same type as returned by the service method (using the client-side copy of the data contracts). See also The communication with a WCF service is not very different from the general pattern used for communicating with a service in Silverlight. Take a look at the Connecting and reading from a standardized service recipe in the previous chapter, where we discussed all general aspects of this topic.

  

You are currently reading a PREVIEW of this book.

                                                                                                                    

Get instant access to over $1 million worth of books and videos.

  

Start a Free Trial


  
  • Safari Books Online
  • Create BookmarkCreate Bookmark
  • Create Note or TagCreate Note or Tag
  • PrintPrint