Building a RESTful WCF Service - WCF Multi-layer Services Development with Entity Framework Fourth Edition (2014)

WCF Multi-layer Services Development with Entity Framework Fourth Edition (2014)

Chapter 11. Building a RESTful WCF Service

In the previous chapters, we created a 3-layered WCF service, used LINQ to Entities in the data access layer, then turned on distributed transaction support for the service. In this chapter, we will convert this SOAP WCF service to a RESTful WCF service and create two Windows 8 apps to consume this RESTful WCF service.

In this chapter, we will cover the following topics while creating and testing the RESTful WCF service:

· SOAP versus REST

· WCF REST versus the ASP.NET Web API

· Creating the RESTNorthwind solution

· Creating the RESTful service

· Defining RESTful service contracts

· Implementing the RESTful service

· Modifying the configuration file

· Testing the RESTful service in a browser

· Testing the RESTful WCF service with a C#/XAML client

· Testing the RESTful WCF service with a JavaScript

SOAP versus REST

SOAP was originally an acronym for Simple Object Access Protocol. This acronym was dropped from SOAP Version 1.2 and now it is a communication protocol to exchange structured information in a decentralized, distributed environment. The SOAP protocol exclusively relies on XML, and all its messages are in the XML format. It was originally developed by Microsoft and became a W3C recommendation in 2003.

REST is an acronym for Representational State Transfer. It is an architectural style to retrieve/update resources within a distributed computer system. It relies on a stateless, client-server, cacheable communications protocol, and in virtually all cases, the HTTP protocol is used. REST was developed by W3C in parallel with HTTP 1.1, based on the existing design of HTTP 1.0.

SOAP is a resource-heavy choice to build services but it has the following advantages over REST:

· It is transport independent (REST supports HTTP only)

· It supports all WS-* standards (REST does not)

REST is more lightweight and has the following advantages over SOAP:

· It is more efficient (SOAP uses XML for all messages, but REST can use a much smaller message format)

· It is faster (no extensive processing is required)

In general, if you need to build a service for non-HTTP transport protocol or you need to support WS-* standards, use SOAP, otherwise use REST.

WCF REST versus the ASP.NET Web API

The ASP.NET Web API is a framework that makes it easy to build HTTP services to reach a broad range of clients, including browsers and mobile devices. The ASP.NET Web API is an ideal platform to build RESTful applications on the .NET Framework.

Though WCF is now mostly used to create SOAP services, it can also be used to build RESTful services from the very beginning. As a matter of fact, the ASP.NET Web API was initially developed under the umbrella of WCF and it was even called WCF Web API. As REST supports HTTP only and WCF is transport neutral, the WCF Web API was eventually moved outside of WCF and into ASP.NET.

WCF REST is again resource heavy but has the following advantages over the ASP.NET Web API:

· It supports multiple transport protocols and allows switching between them (the ASP.NET Web API supports HTTP only)

· It supports all WS-* standards (the ASP.NET Web API does not)

The ASP.NET Web API is more lightweight and has the following advantages over WCF REST:

· It is more efficient and faster

· It takes advantages of the HTTP protocol, such as caching, conditional requests, and status codes

Again in general, if you need to build a service for non-HTTP transport protocol (or multiprotocols), or you need to support WS-* standards, use WCF REST, otherwise use the ASP.NET Web API.

Creating the RESTNorthwind solution

In this chapter, we will create a new solution based on the LINQNorthwind solution. We will copy all of the source code from the LINQNorthwind directory to a new directory and then customize it to suit our needs.

Follow these steps to create the new solution:

1. Create a new directory named RESTNorthwind under the existing C:\SOAwithWCFandEF\Projects\ directory.

2. Copy all of the files under the C:\SOAwithWCFandEF\Projects\LINQNorthwind directory to the C:\SOAwithWCFandEF\Projects\RESTNorthwind directory.

3. Remove the LINQNorthwindClient folder. We will create a new client for this solution.

4. Change the solution file's name from LINQNorthwind.sln to RESTNorthwind.sln.

Now, we have the file structures ready for the new solution. Here, we will reuse the old service to demonstrate how to make an existing WCF service RESTful.

First, we need to make sure this old service in the new solution still works and we also need to create a new IIS application for the service:

1. Start Visual Studio and open the C:\SOAwithWCFandEF\Projects\RESTNorthwind\RESTNorthwind.sln solution.

2. Click on the OK button to close the projects were not loaded correctly warning dialog.

3. From Solution Explorer, remove the LINQNorthwindClient project.

4. Open IIS Manager, add a new application RESTNorthwindService, and set its physical path to C:\SOAwithWCFandEF\Projects\RESTNorthwind\NorthwindService. Choose the application pool NorthwindAppPool, which we have created in a previous chapter, as this service's application pool.

Now, you have finished setting up the service to be hosted in IIS. Open Internet Explorer, go to http://localhost/RESTNorthwindService/ProductService.svc, and you should see the ProductService description in the browser.

Creating the RESTful service

Now we have the solution ready and have hosted the service in IIS. Next, we will modify the existing NorthwindService to be RESTful. We will modify the service contracts, service implementation, and web config file.

Defining RESTful service contracts

In the existing NorthwindService, we have defined two operations for the service, GetProduct and UpdateProduct. To make them RESTful, we need to change their definitions using the following steps:

1. Add a reference of System.ServiceModel.Web to the service project, NorthwindService.

2. Open the IProductService.cs file in the project.

3. Add a using statement:

using System.ServiceModel.Web;

4. Add the following line of code before the GetProduct method:

[WebGet (UriTemplate = "Product/{id}" , ResponseFormat = WebMessageFormat.Json )]

In the preceding line of code, we tell the WCF runtime engine that this operation will be a HTTP Get operation and the UriTemplate maps the parameter name, id, from the HTTP protocol to the service operation parameter, id. Also, the response will be in the JSON format.

5. Now, change the parameter type of the method, GetProduct, from int to string:

Product GetProduct(string id);

This is because for a RESTful service call, the default HTTP protocol parameter will always be of the type string.

For the UpdateProduct method, we need to do a little more as it is a method with complex parameters. There are a few approaches to handle complex parameters for a RESTful WCF service, and here we will take the one that requires a request/response package for the method.

Follow these steps to define the service contract for the UpdateProduct method.

1. Add the following two classes to the IProductService.cs file for the request/response packages:

2. public class UpdateProductRequest

3. {

4. public Product Product { get; set; }

5. }

6.

7. public class UpdateProductResponse

8. {

9. public bool Result { get; set; }

10. public string Message { get; set; }

11. public Product Product { get; set; }

}

The UpdateProductRequest class will be used for the input operation, which contains the Product information to be updated. The UpdateProductResponse class will be used for the output operation, which contains the result of the update, updated product information, and update message.

2. Now, add the following line of code before the UpdateProduct method:

[WebInvoke(Method = "POST", UriTemplate = "/UpdateProduct", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]

Here, we use POST as the web invoke method, and both the request and response will be in the JSON format.

3. Change the definition of the UpdateProduct method to be like this:

UpdateProductResponse UpdateProduct(UpdateProductRequest request);

As you can see, we have passed in a UpdateProductRequest parameter, and the return result will be UpdateProductResponse.

The service contract definitions will be like this now:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Runtime.Serialization;

using System.ServiceModel;

using System.Text;

using System.ServiceModel.Web;

namespace NorthwindService

{

[ServiceContract]

public interface IProductService

{

[WebGet(UriTemplate = "Product/{id}",

ResponseFormat = WebMessageFormat.Json)]

[OperationContract]

[FaultContract(typeof(ProductFault))]

Product GetProduct(string id);

[WebInvoke(Method = "POST",

UriTemplate = "/UpdateProduct",

RequestFormat = WebMessageFormat.Json,

ResponseFormat = WebMessageFormat.Json)]

[OperationContract]

[FaultContract(typeof(ProductFault))]

UpdateProductResponse UpdateProduct(

UpdateProductRequest request);

}

public class UpdateProductRequest

{

public Product Product { get; set; }

}

public class UpdateProductResponse

{

public bool Result { get; set; }

public string Message { get; set; }

public Product Product { get; set; }

}

[DataContract]

public class Product

{

[DataMember]

public int ProductID { get; set; }

[DataMember]

public string ProductName { get; set; }

[DataMember]

public string QuantityPerUnit { get; set; }

[DataMember]

public decimal UnitPrice { get; set; }

[DataMember]

public bool Discontinued { get; set; }

[DataMember]

public byte[] RowVersion { get; set; }

}

[DataContract]

public class ProductFault

{

public ProductFault(string msg)

{

FaultMessage = msg;

}

[DataMember]

public string FaultMessage;

}

}

Implementing the RESTful service

Now, let's implement the service contracts. To reuse the existing code, here we will add two new methods to the existing ProductService.cs file as follows:

1. Open the ProductService.cs file in the NorthwindService project.

2. Add a new method, GetProduct, like this:

3. public Product GetProduct(string id)

4. {

5. return GetProduct(Convert.ToInt32(id));

}

This new method actually just converts the input parameter to an integer, then calls the exiting method to get product details. Note that we didn't check whether the input is really an integer here. In a real situation, you should add appropriate error handling to this method.

3. Add another new method, UpdateProduct, like this:

4. public UpdateProductResponse UpdateProduct(

5. UpdateProductRequest request)

6. {

7. var product = request.Product;

8. var message = "";

9.

10. var result = UpdateProduct(ref product, ref message);

11. var response = new UpdateProductResponse()

12. { Result = result,

13. Message = message,

14. Product = product };

15. return response;

}

Again, this new method just calls the exiting method to update the product. As we couldn't have ref parameters for a RESTful WCF service, we will return the updated product in the response package.

Modifying the configuration file

For the NorthwindService to work as a RESTful WCF service, we need to modify the Web.config file. We need to change the binding and define the behavior of the service endpoint:

1. Open the Web.config file in the NorthwindService project.

2. Change the product service endpoint to be like this:

3. <endpoint address="" binding="webHttpBinding"

4. contract="NorthwindService.IProductService"

behaviorConfiguration="restfulBehavior">

3. Add a new node as a child node of behaviors, right after the existing node, serviceBehaviors:

4. <endpointBehaviors>

5. <behavior name ="restfulBehavior">

6. <webHttp />

7. </behavior>

</endpointBehaviors>

Note

Make sure that this new node is on the same level as the existing node serviceBehaviors, not nested within it.

Testing the RESTful service in a browser

We have finished modifying the existing NorthwindService to be a RESTful WCF service. Before building our own client to test it, let's test it with a browser.

To test the RESTful WCF service, first rebuild the solution, then open Internet Explorer and enter the following URL in the address bar of the browser: http://localhost/RESTNorthwindService/ProductService.svc/Product/5.

Depending on your browser's settings, you might be prompted to open/save the response file, or you might get the following content displayed on your browser:

{"Discontinued":true,"ProductID":5,"ProductName":

"Chef Anton's Gumbo Mix","QuantityPerUnit":"36 boxes","RowVersion":[0,0,0,0,0,0,7,252],

"UnitPrice":21.3500}

This shows the JSON-formatted details of the product with ID 5.

Now if you try to call the UpdateProduct method on the browser, you will get a response that says Method not allowed. As this is a POST method, we have to create a client to submit a POST request to the service to get the response, and in the next section we will create such a client.

Testing the RESTful WCF service with a C#/XAML client

Next, we will create two clients to test the RESTful WCF service. We will create a C#/XAML client to call the RESTful WCF service from the code behind the C# class and create another client to call the RESTful WCF service in JavaScript with jQuery and WinJS. We will create these two clients as Windows 8.1 apps. If you don't have Windows 8.1, you can create the first client as a WPF application, and the second client as an ASP.NET application in Windows 7.

Creating the C#/XAML client

First, let's create a C#/XAML client to call the RESTful WCF service from the code behind the C# class. You can follow these steps to create this client:

1. From the Solution Explorer, right-click on the solution item and add a new project. Go to Visual C# | Store Apps | Windows Apps | Blank App (Windows) as the template, change the name to RESTNorthwindClientXAML, and leave the location to be the default one (C:\SOAwithWCFandEF\Projects\RESTNorthwind).

Creating the C#/XAML client

2. You might be prompted to get a developer's license to create a Windows app. Just follow the instructions to get a new one or renew an existing one and then continue.

3. Delete the MainPage.xaml file from this new project.

4. Right-click on the new project and add a new item. Choose Visual C# | Basic Page as the template and change the name to MainPage.xaml.

5. Click on the Add button to add this new page. A dialog window will pop up to ask you to add some missing files. Click on the Yes button on this dialog window to add those files.

Implementing the GetProduct method of the C#/XAML client

To test the RESTful WCF service, we will add a few controls to the main page of the test client and call the GetProduct method of the service to get product details for the entered product ID. You can follow these steps to implement this functionality:

1. First, from the Solution Explorer, right-click on the test client project RESTNorthwindClientXAML, and add a service reference to the project. Use http://localhost/RESTNorthwindService/ProductService.svc as the address and change the name to be ProductServiceRef. We are not going to call the service using this service reference, instead we are going to use the service interface that is imported to the client application with this service reference, so we don't need to redefine them in the client application.

Note

Instead of adding a service reference to the client application or redefining all of the service interface contracts in the client project, you can also keep the interface in a standalone project and reference this interface DLL in both the service implementation and client projects.

2. In the Solution Explorer, right-click on the client project item, RESTNorthwindClientXAML, select Manage NuGet Packages… | nuget.org | Json.NET, and then install Json.NET to the project. This will add a JSON reference and the JSON library to the project. We will need this library to serialize and deserialize the request and response of the RESTful WCF service calls.

Implementing the GetProduct method of the C#/XAML client

3. Now, open the designer of the main page and add the following items to the designer of the main page:

o A text block named lblProductID with the text, Product ID and font size of 20 px

o A textbox named txtProductID

o A button named btnGetProduct with the content, Get Product Details

o A text block named lblProductDetails with the text, Product Details and font size of 20 px

o A textbox named txtProductDetails

4. Then, on the main page designer, double-click on the Get Product Details button and add an event handler for this button, as follows:

5. private void btnGetProduct_Click(object sender, RoutedEventArgs e)

6. {

7. GetProduct();

}

5. In the MainPage.xaml.cs file, add the following three using statements:

6. using RESTNorthwindClientXAML.ProductServiceRef;

7. using System.Net.Http;

using Newtonsoft.Json;

6. Add the following two class member variables:

7. string service =

8. "http://localhost/RESTNorthwindService/ProductService.svc";

Product product;

The service variable holds the address of the RESTful WCF service and the product variable holds the product we will get from calling the RESTful WCF service. We will reuse both these variables when we update a product.

7. Now, add the following method to this file:

8. private async void GetProduct()

9. {

10. var client = new HttpClient();

11. var url = service + "/Product/" + txtProductID.Text;

12. var response = await client.GetAsync(url);

13. var json = await response.Content.ReadAsStringAsync();

14. product = JsonConvert.DeserializeObject<Product>(json);

15. var sb = new System.Text.StringBuilder();

16. sb.Append("ProductID:"

17. + product.ProductID.ToString() + "\n");

18. sb.Append("ProductName:"

19. + product.ProductName + "\n");

20. sb.Append("UnitPrice:"

21. + product.UnitPrice.ToString() + "\n");

22. sb.Append("RowVersion:");

23. foreach (var x in product.RowVersion.AsEnumerable())

24. {

25. sb.Append(x.ToString());

26. sb.Append(" ");

27. }

28. this.txtProductDetails.Text = sb.ToString();

}

Within this method, we first created a HttpClient object and then called the GetAsync method of this HTTP client object. As we have specified the response format to be JSON in the WCF service, this call returned a JSON string as a result. So we deserialized this string back to aProduct object and printed out the product details on the UI.

Testing the GetProduct method of the C#/XAML client

We have finished implementing the GetProduct functionality of the test client. To test it, first set the RESTNorthwindClientXAML project as the startup project, press Ctrl + F5 to run the client program, enter an integer to the Product Id textbox, and then click on the Get Product Detailsbutton. You will see that the product details are displayed on the bottom text block, as shown in the following screenshot:

Testing the GetProduct method of the C#/XAML client

Implementing the UpdateProduct method of the C#/XAML client

Next, we will implement the UpdateProduct functionality in the client, so we can call the RESTful WCF service to update a product.

1. First, we need to add some more controls to the page. Open the designer's main page in the RESTNorthwindClientXAML project and add the following items to the designer of the main page:

o A text block named lblNewPrice with the text New Price and font size 20 px

o A textbox named txtNewPrice

o A button named btnUpdatePrice with the content, Update Price

o A text block named lblUpdateResult with the text, Update Result and font size 20 px

o A textbox control named txtUpdateResult

2. On the main page of designer, double-click on the Update Price button and add an event handler for this button, as follows:

3. private void btnUpdatePrice_Click(object sender, RoutedEventArgs e)

4. {

5. UpdateProduct();

}

3. Add the following method to the class to update the product:

4. public async void UpdateProduct()

5. {

6. if (product == null)

7. {

8. this.txtProductDetails.Text =

9. "Get product details first";

10. return;

11. }

12.

13. product.UnitPrice =

14. Convert.ToDecimal(this.txtNewPrice.Text);

15. var updateRequest =

16. new UpdateProductRequest() { Product = product };

17. var json = JsonConvert.SerializeObject(updateRequest);

18.

19. var rowVersionArray =

20. product.RowVersion.Select(b => (int)b).ToArray();

21. var jsonRowVersion =

22. JsonConvert.SerializeObject(rowVersionArray);

23. var start = json.IndexOf("\"RowVersion\":") + 13;

24. var end = json.IndexOf(",\"UnitPrice\":");

25. if (end > start && start >= 0)

26. {

27. var binaryRowVersion =

28. json.Substring(start, end - start);

29. json =

30. json.Replace(binaryRowVersion, jsonRowVersion);

31. }

32.

33. using (var client = new HttpClient())

34. {

35. client.BaseAddress = new Uri(service + "/");

36. var response =

37. await client.PostAsync("UpdateProduct",

38. new StringContent(json,

39. System.Text.Encoding.UTF8,

40. "application/json"));

41. using (var content = response.Content)

42. {

43. var responseJson =

44. await content.ReadAsStringAsync();

45. var updateResponse =

46. JsonConvert.DeserializeObject<UpdateProductResponse>

47. (responseJson);

48. product = updateResponse.Product;

49. if (updateResponse.Result)

50. this.txtUpdateResult.Text =

51. "Price updated to "

52. + product.UnitPrice.ToString();

53. else

54. this.txtUpdateResult.Text =

55. "Update failed: "

56. + updateResponse.Message;

57. }

58. }

}

Inside this method, we first created an UpdateProductRequest object, then serialized this object to a JSON string. However, we had a problem with the row version here. By default, JSON.NET selects the binary converter to read and write an array of bytes. It uses the WriteValueoperation on the JsonWriter class with the array of bytes that causes them to be written to as Base-64. So, the row version in the serialized JSON string was in the Base-64 string format. However, the RESTful WCF is expecting an array of integers, so we had to replace the Base-64 string-formatted row version with an array of integers.

Note

You can also supply your own binary converter to JSON.NET, so it will serialize the row version as an array of integers.

After we corrected the row version, we again created a HttpClient object and called the PostAsync method to post the updated product to the service. This call again returned a JSON string to us as we have specified the response format to be JSON in the WCF service. We then deserialized this string to an UpdateProductResponse object and printed out the update result on the UI.

Note

You can also use HttpWebRequest to submit the post request to the service with a slightly different syntax.

Testing the UpdateProduct method of the C#/XAML client

Now we have finished implementing the UpdateProduct functionality of the test client. To test it, just press Ctrl + F5 to run the client program, enter an integer to the Product Id textbox, and then click on the Get Product Details button to get back the product. Enter a new price in theNew Price textbox and then click on the Update Price button. You will see that the product is updated with the new price. You can click on the Get Product Details button to verify that the product is updated correctly with the new price. You can also keep updating the price for the product, as the client always holds the latest product information.

Testing the UpdateProduct method of the C#/XAML client

Testing the RESTful WCF service with a JavaScript client

In the previous sections, we created a C#/XAML client to call the RESTful WCF service from the code behind C# class. In the next sections, we will create a JavaScript client to call the RESTful WCF service. We will first call the service using jQuery and then using WinJS.

Creating the JavaScript client

You can follow these steps to create the JavaScript client:

1. From the Solution Explorer, right-click on the solution item and add a new project. Choose JavaScript | Store Apps | Windows Apps | Blank App (Windows) as the template, change the name to RESTNorthwindClientJS, and leave the location to be the default one (C:\SOAwithWCFandEF\Projects\RESTNorthwind).

Creating the JavaScript client

2. Again, you might be prompted to get a developer's license to create a Windows app. Just follow the instructions to get a new one or renew an existing one and then continue.

3. Now, first add some HTML controls to the default page. Just open the default.html file and replace the body node with the following code:

4. <br />

5. <p>REST Northwind JavaScript Client</p>

6. Product Id <input id="txtProductId" type="text" />

7. <input type="button" id="btnGetProduct" value="Get Product Details" />

8. <br />

9. <textarea id="txtProductDetails" rows="7" cols="61"> </textarea><br />

10.<br />

11.New Price <input id="txtNewPrice" type="text" />

12.<input type="button" id="btnUpdatePrice" value="Update Price" style="width:156px;" />

13.<br />

<textarea id="txtUpdateResult" rows="7" cols="61"> </textarea>

4. Set the client project RESTNorthwindClientJS as the startup project, press Ctrl + F5 to run this client, and you should see a similar UI as in the Testing the UpdateProduct method of the C#/XAML client section.

Testing the service with jQuery

We will first implement this test client with jQuery. We will install jQuery to the client project, call the service with jQuery to get product details, and then call the service with jQuery to update the product.

Installing jQuery to the client project

To use jQuery, we first need to install it to the project. Just right-click on the client project RESTNorthwindClientJS, select Manage NuGet Packages… | nuget.org | JQuery, and then install jQuery to the project.

Implementing the GetProductJQuery method

Now that we have the controls on the UI, we will write some jQuery code to call the GetProduct method of the service to get product details for the entered product ID. You can follow these steps to implement this functionality:

1. Open the default.html file in the RESTNorthwindClientJS project.

2. Add the following line of code to the head node of this file, right after the WinJS scripts are loaded and before the default.js script file is loaded (you should replace 2.1.1 with your project's jQuery version):

<script src="Scripts/jquery-2.1.1.js" type="text/javascript"></script>

3. Then, open the default.js file, which is under the js folder.

4. Add the following two lines of code to the end of the file to define two global variables:

5. var product;

6. var service =

'http://localhost/RESTNorthwindService/ProductService.svc';

The first variable, product, holds the product object that we get back from the service. Later, we will update the price of this product and pass the updated product object to the service to update it. The second variable, service, holds the RESTful service endpoint address. We will connect to the service with this endpoint address.

5. Add the following JavaScript method after the preceding two global variables:

6. function FormatProduct() {

7. var result = "";

8. result += "ProductID:" +

9. product.ProductID + "\r\n";

10. result += "ProductName:" +

11. product.ProductName + "\r\n";

12. result += "QuantityPerUnit:" +

13. product.QuantityPerUnit + "\r\n";

14. result += "UnitPrice:" +

15. product.UnitPrice + "\r\n";

16. result += "Discontinued:" +

17. product.Discontinued + "\r\n";

18. result += "RowVersion:";

19. for (var i = 0; i < 8; i++) {

20. result += product.RowVersion[i] + " ";

21. }

22. return result;

}

As you will see soon, this method will be called to convert a product object to a string, so it can be displayed in a textbox on the UI.

6. Then, add the following JavaScript method to call the RESTful WCF service and get the product details for the entered product ID:

7. function GetProductJQuery() {

8. jQuery.support.cors = true;

9.

10. $.ajax(

11. {

12. type: "GET",

13. url: service + '/Product/' +

14. $('#txtProductId').val(),

15. data: "{}",

16. contentType: "application/json; charset=utf-8",

17. dataType: "json",

18. cache: false,

19. success: function (data) {

20. product = data;

21. $("#txtProductDetails").val(FormatProduct());

22. },

23. error: function (msg, url, line) {

24. $("#txtProductDetails").val(msg.responseText);

25. }

26. });

}

Within this method, we use AJAX to call the RESTful WCF service. We pass in the product ID, get back the product object, format the product object to a string, and then display it on the UI.

7. Finally, we need to add these lines of code to attach the click event handler of the Get Product Details button to the GetProductJQuery method:

8. $(document).ready(function () {

9. $("#btnGetProduct").click(GetProductJQuery);

});

Testing the GetProductJQuery method of the JavaScript client

We have finished implementing the GetProductJQuery functionality of the test client. To test it, first set the RESTNorthwindClientJS project as the startup project, then press Ctrl + F5 to run the client program, enter an integer to the Product Id textbox, and then click on the Get Product Details button. You will see that the product details are displayed on the bottom text block.

Implementing the UpdateProductJQuery method

Now we can get back product details with jQuery; let's update it with jQuery:

1. Open the default.js file in the RESTNorthwindClientJS project.

2. Add the following JavaScript method to this file:

3. function UpdateProductJQuery () {

4. jQuery.support.cors = true;

5.

6. if (product == null) {

7. $("#txtUpdateResult").val("Get product details first");

8. return;

9. };

10.

11. product.UnitPrice = $("#txtNewPrice").val();

12.

13. $.ajax(

14. {

15. type: "POST",

16. url: service + '/UpdateProduct',

17. data: JSON.stringify({ Product: product }),

18. contentType: "application/json; charset=utf-8",

19. dataType: "json",

20. success: function (response) {

21. product = response.Product;

22. if (response.Result)

23. $("#txtUpdateResult").val(

24. "Price updated to " + product.UnitPrice);

25. else

26. $("#txtUpdateResult").val(

27. "Update failed: " + response.Message);

28. },

29. error: function (msg, url, line) {

30. $("#txtUpdateResult").val(msg.responseText);

31. }

32. });

}

3. Add this line of code to the $(document).ready code block to attach the click event handler of the Update Price button to the UpdateProductJQuery method:

$("#btnUpdatePrice").click(UpdateProductJQuery);

Testing the UpdateProductJQuery method of the JavaScript client

Now we have finished implementing the UpdateProductJQuery functionality of the test client. To test it, press Ctrl + F5 to run the client program, enter an integer to the Product Id textbox, and click on the Get Product Details button to get back the product object. Then, enter a new price and click on the Update Price button. You will see the product price is updated with the new price. You can click on the Get Product Details button again to verify that the price is updated correctly.

Testing the UpdateProductJQuery method of the JavaScript client

Testing the service with WinJS

The Windows Store app actually uses WinJS by default. So in this section, we will implement the GetProduct and UpdateProduct functionalities with WinJS.

Implementing the GetProductWinJS method

First, we will write some WinJS code to call the GetProduct method of the service to get product details for the entered product ID. You can follow these steps to implement this functionality:

1. Open the default.js file in the RESTNorthwindClientJS project.

2. Add the following JavaScript method to this file:

3. function GetProductWinJS(mouseEvent) {

4. var xhrOptions = {

5. url: service + "/Product/"

6. + document.getElementById("txtProductId").value,

7. headers: {

8. "Content-Type": "application/json",

9. "If-Modified-Since": "Mon, 27 Mar 1972 00:00:00 GMT"

10. },

11. data: {},

12. };

13. WinJS.xhr(xhrOptions).done(

14. function (req) {

15. product = JSON.parse(req.response); document.getElementById("txtProductDetails").innerHTML =

16. FormatProduct();

17. },

18. function (req) {

19.document.getElementById("txtProductDetails").innerHTML =

20. toStaticHTML(req.response);

21. });

}

As you can see, this method is very similar to the GetProductJQuery method, except that we use WinJS.xhr instead of AJAX to call the service. We also use the document object to get the objects on the UI.

3. We now need to attach the click event handler of the Get Product Details button to the GetProductWinJS method. Just find the following line of code in this file:

args.setPromise(WinJS.UI.processAll());

Replace it with the following line of code:

args.setPromise(WinJS.UI.processAll().done(function () {

document.getElementById("btnGetProduct").addEventListener(

"click", GetProductWinJS, false);

})

);

Testing the GetProductWinJS method of the JavaScript client

We have finished implementing the GetProductWinJS functionality of the test client. However, before we test it we need to comment out the following two lines of code, otherwise the click events of the buttons will be fired twice:

$("#btnGetProduct").click(GetProductJQuery);

$("#btnUpdatePrice").click(UpdateProductJQuery);

Then, press Ctrl + F5 to run the client program, enter an integer to the Product Id textbox, and click on the Get Product Details button. You will see that the product details are displayed on the bottom text block and that this time the service is being called through WinJS, not jQuery.

Implementing the UpdateProductWinJS method

Now we can get back product details with WinJS. Let's update the UpdateProductWinJS method with WinJS:

1. Open the default.js file in the RESTNorthwindClientJS project.

2. Add the following JavaScript method to this file:

3. function UpdateProductWinJS(mouseEvent) {

4.

5. if (product == null) {

6. document.getElementById("txtUpdateResult").innerHTML =

7. "Get product details first";

8. return;

9. };

10.

11. product.UnitPrice =

12. document.getElementById("txtNewPrice").value;

13.

14. var xhrOptions = {

15. type: "POST",

16. url: service + "/UpdateProduct",

17. headers: { "Content-Type": "application/json" },

18. data: JSON.stringify({ Product: product })

19. };

20. WinJS.xhr(xhrOptions).done(

21. function (req) {

22. var updateResponse = JSON.parse(req.response);

23. product = updateResponse.Product;

24. if (updateResponse.Result)

25.document.getElementById("txtUpdateResult").innerHTML =

26. "Price updated to " + product.UnitPrice;

27. else

28.document.getElementById("txtUpdateResult").innerHTML =

29. "Update failed: " + updateResponse.Message;

30. },

31. function (req) {

32.document.getElementById("txtUpdateResult").innerHTML =

33. toStaticHTML(req.response);

34. });

}

3. Again, this method is very similar to the UpdateProductJQuery method, except that we use WinJS.xhr instead of AJAX to call the service. We also use the document object to get the objects on the UI.

4. Finally, add this line of code to the args.setPromise(WinJS.UI.processAll().done code block to attach the click event handler of the Update Price button to the UpdateProductWinJS method:

5. document.getElementById("btnUpdatePrice").addEventListener(

"click", UpdateProductWinJS, false);

Testing the UpdateProductWinJS method of the JavaScript client

Now we have finished implementing the UpdateProductWinJS functionality of the test client. To test it, press Ctrl + F5 to run the client program, enter an integer to the Product Id textbox, and click on the Get Product Details button to get back the product object. Then, enter a new price and click on the Update Price button. You will see that the product price is updated with the new price and this time the service is being called through WinJS, not jQuery. You can also click on the Get Product Details button again to verify that the price is updated correctly.

Summary

In this chapter, we changed the WCF service to be RESTful. We changed the definitions of the service, changed the configuration file of the service, and we tested this service with two Windows app clients. We also learned how to consume a RESTful WCF service with C#/XAML, jQuery, and WinJS.

In the next chapter, we will learn how to secure a WCF service.