Typically, enterprises implement Web services using two architectures: SOAP-based services and rest model-based services. These two architectures rely on the HTTP protocol and the Internet-implemented addressing system, but use them in different ways. So far, all the exercises in this book have been focused on the SOAP model, which enables Web service designers to focus on the business processes of the service and expose these business processes externally as service operations. In contrast, the rest model focuses on the data published by the enterprise and implements a system that allows the client program to access and manipulate the data using its own logic. Rest models are becoming more common, and you can use the features, methods, and types provided by WCF to quickly build and access rest Web services. In addition, the Entity Framework provides data Service templates for WCF that you can use to expose data and entities from the Entity Framework model as rest resources to client programs. The purpose of this chapter is to introduce the rest Web service and show how to use WCF to create and access rest Web services.
Understanding the rest model The rest model was first mentioned in 2000 by Roy Fielding in his doctoral dissertation, "Structured styles and architecture design based on Web software." As the name of the paper, rest is an architectural style rather than a pre-defined way to build a Web service, and you can implement rest with any appropriate technology. The key point of rest is that it describes a stateless, conforming architecture similar to www. For example, AdventureWorks provides access to customer and sales information data, placing details of each customer or order as a single resource. For a list of all customers from the AdventureWorks Web site, a website application should have the following URL: http://www.adventure-works.com/sales/customers. Data can be returned in several formats, but the most common patterns include XML and JSON. If AdventureWorks chooses XML, the return result from the above URL query might look like this: Web services that follow the rest model generally allow Web applications to further extract data through additional path parameters. For example, query individual customer details. If the customer's number is 99, then AdventureWorks allows the Web application to specify the following URL address: http://www.adventure-works.com/sales/customers/99. Also, it is useful to allow Web applications to find all orders for a given customer, so the URL should be: Http://www.adventure-works.com/sales/customers/99/orders. The key to design rest-based scenarios is to understand how to divide the business model into resources and how to relate those resources together. In some cases, such as customers and orders, this relationship is relatively straightforward, but it is a daunting task to divide and correlate resources in other scenarios. The rest model relies on applications that send appropriate HTTP actions that form part of the request to access the service's data. For example, the request described above sends an HTTP GET request to the Web service. HTTP also supports other actions, such as post,put and delete, which correspond to the creation, modification, and removal of resources for rest services. Using the rest model, you can create INSERT, update, and delete data using these actions. In contrast to soap, the rest model sends and receives more concise messages. This is primarily because the description of rest WS-* does not need to provide the functionality of routing, policy, or security; you just need to rely on Web server implementations to protectThe underlying transport structure of the REST Web service. You should also remember that the rest model is stateless, and that there is no concept of a session or transaction between the client and the service's interactive conversation. Thus, a restful web service that takes a simple implementation means that it is often more efficient to transmit and receive messages than SOAP Web services.
Implementing a Rest Web service that queries dataImplementing a Rest Web service using WCF is a simple process, and WCF provides many types for you to use in the System.ServiceModel.Model component. The most important part of the process is design services to provide external resources to read the data system. In most cases, resources are grouped into individual collections according to their natural state, and are associated with other resources or collections. The practice in this chapter will use the data system defined in the following table.
Uri |
Describe |
Customers |
AdventureWorks all customers in the database |
Customers/{customerid} |
One of the specified customers |
Orders |
AdventureWorks all orders in the database |
Orders/{orderid} |
One of the specified orders |
Orders/{orderid}/customer |
A customer for an order |
Customers/{customerid}/orders |
All orders for a single customer |
Depending on the number of data in the database, customers and orders URIs may return a large number of data items. Because of this, it makes sense to limit the returned data items according to the additional query parameters specified by the user. In the exercises in this section, you will implement two optional query parameters, skip and top, which users can use in the following ways: orders?top=10 orders?skip=500 orders?skip=9&top=20 The purpose of the top parameter is to obtain only the first n data records, and n is the value of the top of the parameter. The first example above takes the top 10 orders from a database. The purpose of the skip parameter is to ignore the first n data records and then get the data records from the first n+1 record. The second example above is to get all orders starting with No. 501 from the database. The third example is extracting data from 10th and extracting 20, which is the data record from 10 to 30. Merging parameters in this way allows the client to implement a paging mechanism-fetching data in a way that is manageable in a block size. Like the SOAP Web service, the first task of implementing a rest Web service is to define a service contract. A contract specifies an operation that is exposed externally and establishes an association between the operation and the URIs to differentiate between different resources. The Web client program can then invoke these operations through query URIs. Exercise: Define productssales REST Web service Contract 1. Start Visual Studio and create a new solution based on the contents of the following table
Uri |
Describe |
Template |
Blank Solution |
Name |
Productssales |
Position |
Solutions\wcf\step.by.step\chapter15 |
2. Add a new Class library project to the Productssales solution. Name it Productssalesservice, where the item is saved in Solutions\wcf\step.by.step\chapter15\productssales 3. In the Solution Explorer window, add the productssalesmodel.edmx file and the app. Config file to the Productssalesservice project. These two files can be found in the Chapter15 folder in the source code of the original book author. The productssalesmodel.edmx file is an Entity Framework model. It defines two entities, namely contact and SalesOrderHeader. In the AdventureWorks database, the Contacts table contains details of all contacts and customers, and the SalesOrderHeader table contains the customer's order information. The app. Config file contains a connection string for the entity model to connect to the AdventureWorks database. 4. Rebuild the solution. This behavior generates code for the contact class and the SalesOrderHeader class from the entity model. 5. Refer to the System.ServiceModel component and the System.ServiceModel.Web component to the Productssalesservice project. 6. In the Solution browser window, change the name of the Class1.cs file to IProductsSales.cs. and allows Visual Studio to update all references to Class1.cs. 7. Open the IProductsSales.cs file in text-editing mode and add the following using declaration to the top of the file. 8. Change the Iproductssales class to a common interface for adding the ServiceContract attribute. 9. In the Iproductssales interface, add the Getallorders method and add an attribute to the method: The operation returns a collection of SalesOrderHeader objects that contains the data for each order. The OperationContract attribute indicates that the method is a Web service operation. The WebGet attribute indicates that this is a rest operation that responds to an HTTP GET request and the same UriTemplate property specifies the URI that the client program uses to invoke the operation. The URI contains the optional skip query parameter and the top query parameter. The ship and top in curly braces can be replaced by the clientThe value provided when the program is run. The definition of the Getallorders method contains the same name as the two arguments, and the WCF runtime populates the values passed by the client program with the parameters of the Getallorders method. Note that although the order of service operation parameters is not important, the names of these parameters must be the same as those in the UriTemplate attribute value in the WebGet attribute class. Using the description feature, you can specify some simple descriptive text that will appear in the help page of the service. 10. Add the GetOrder method to the Iproductssales interface: When the client program accesses the service through the established URI format Orders/orderid The operation runs, it gets the SalesOrderHeader object that corresponds to the order. As in the previous step, note that the method receives a parameter that matches the booth character in the UriTemplate curly brace. Another area of concern is that the type of the parameter is a string type, although the data type of the corresponding column in the SalesOrderHeader table in the AdventureWorks data is an integer type. This is because the navigation element in the URI must be a string type. This restriction does not apply to query parameters (the skip and top parameters in the Getallorders method are integer types) 11. Add the Getcustomerfororder method to the Iporductssales interface: the operation runs when the client program accesses the service by Orders/{orderid}/customer the URI format that is established. 12. Add Getallcustomers,getcustomer, and Getordersforcustomer method to Iproductssales interface: The actions defined above allow the client program to obtain all the clients individually, Details of an attribute customer, and all orders for a particular customer. 13. Rebuild the solution. Exercise: Implementing Productssales REST Web Service 1. Add a new class file to the project Productssalesservice project and name it ProductsSales.cs. 2. Open the ProductsSales.cs file in text-editing mode. Then add the following using declaration 3 to the head of the file. Modify the definition of the Productssales class so that it implements Iproductssales interface 4. Add the following Getallorders method to the Productssales class for the method from AdventureWorks dataGets the list of orders in the library and returns a collection of SalesOrderHeader objects. The Web application calls the method when it accesses the order by hosting the URI of the service. Web applications may also be able to optionally query orders by using both the skip and top parameters. The default value for these two parameters is 0. Since data may contain hundreds or thousands of data order records. So the service simply extracts the first 100 order data from the database. Of course, the user can specify the exact quantity of the order to be displayed. If the application requires all the orders in the database, it can call the getallorders operation continuously and specify the appropriate values for the skip parameter and the top parameter each time the getallorders is called. The method does not validate parameters and check for errors, for example, it does not verify that the skip and top parameters are negative. If an exception occurs, the method throws a Webfaultexception exception. The exception type is a specific version of the FaultException class, and the only difference is that the exception generates an HTTP error instead of a SOA error. The parameters of the Webfaultexception exception constructor specify the HTTP status code that the HTTP error contains. The HTTP status code is an enumeration type that is located under the System.Net namespace, which defines a list of codes that you can return to a Web application. The code for httpstatuscode.badrequest corresponds to a 400 error message, which returns a 400 error message for all exceptions and does not contain detailed error information. For security reasons, you should avoid returning too much information when an error occurs (although a common best practice is to log the details of the error to the local server, which is typically logged in the program log of the system event log). 5. Add the GetOrder method to the Productssales class The method finds the order based on the incoming parameter (the value of the order number) and returns the SalesOrderHeader object. Note that the order number provided by the Web program is a character type, so in the method we need to convert it to an integer type. If no order is found, a null value is returned. As in the previous method, an error request error is returned if an exception occurs. 6. Add the Getcustomerfororder method to the Productssales class above method to obtain the customer for the specified order. To accomplish this, the LINQ query connects to the Contact table and SalesOrderHeader table in the AdventureWorks database through the Contractid column and the CustomerID column. When the query is complete, a contact object is returned. 7. Add Getallcustomer,getcusTomer, and the Getordersforcustomer method to the Productssales class above three methods are similar to the previous steps, the difference is only focused on the customer rather than the order. 8. Rebuild the solution just like the SOAP Web service, you can use IIS, or create your own program hosting rest Web service. WCF provides the Webservicehost class under the System.ServiceModel.Web namespace, which is a specific version of the ServiceHost class that provides a homestay environment for restful Web services. The Webservicehost class adds an endpoint behavior named WebHttpBehavior for its hosted service. This behavior enables the service to accept and send messages using HTTP requests instead of SOAP requests. You will use this class in the following exercise. Exercise: Homestay productssales REST Web Service 1. Add a new console program project to the Productssales solution and rename it to Productssaleshost, where the project is saved in solutions\wcf\step.by.step\chapter15\ The Productssales folder. 2. Open the Properties page for the Productssaleshost project. Then click the Programs tab, set the Traget framework property to. NET framework 4, and allow Visual Studio to close and reopen the project. 3. Refer to the Productssalesservice project to Productssaleshost. Then reference the System.ServiceModel component and the System.ServiceModel.Web. 4. Open the Program.cs file in text-editing mode and add the following using declaration: 5. In the Programm class, add the following declaration: The code above creates a Webservicehost object based on the Productssalesservice class, and then starts the service and listens for requests. The code above is similar to the code for the hosted SOAP service in the previous section. 6. Delete the Productssaleshost app. Config file and copy the App. Config to the Productssaleshost project from the Chapter15 folder in the code attached to the original book. 7. Use the WCF Service Configuration Manager to open the App. Config file under Productssaleshost. 8. In the configuration panel, on the Service folder, pointRight click and click Create New service. Then in the right panel, in the Name field, enter Productssalesservice.productssales. 9. In the configuration panel, expand the Productssalesservice.productssales Service folder, and then right-click at the end of the folder to select Create a new service endpoint and set the corresponding property for the newly created service endpoint according to the values in the table below.
Property |
value |
address |
http://localhost:8000 /sales |
binding |
webhttpbinding |
contract |
Prod Uctssalesservice.iproductssales |
The UriTemplate attribute in the WebGet attribute class on an operation in the Iproductsservice service specifies that the URIs will be applied to the relative address of the service. For example, the value of the Getcustomerfororder Operation UriTemplate property is Orders/{orderid}/customer. Then the client program can invoke the Getcustomerfororder operation via Http://localhost:8000/Sales/Orders/54545/Customer, where 54545 is the order number. The webhttpbinding binding configuration configures an endpoint for the rest Web service that Grandpa receives an HTTP request instead of a SOAP message. 10. Save the configuration file and launch the WCF service Configuration Manager 11. Rebuild the solution. When you submit an HTTP GET request from a Web reference program, the Productssales service will respond to the request, and you can use a Web browser such as IE to send a request to the service, and in the following exercise we will use IE to productssales the service to send the request. Note that the Webservicehost class disables publishing WSDL metadata externally. However, you can still query the rest service after the rest Web service has started the help. Therefore, in the following exercise, you will configure the Productssalesservice service to provide help information that lists the URLs supported by the service and constructs the return data when you use each URI query. Exercise: Test productssales REST Web Service 1 using a Web browser. In the Solution browser window, set the Productssaleshost project as the startup project for the solution, and then start the solution in non-debug mode. Confirm that the console window of the Productssaleshost program displays the message "Service Running". 2. Start IE, then enter the Address bar http://localhost:8000/sales/orders and press ENTER. The browser accesses the URI to invoke the GetOrders action, which returns a collection of SalesOrderHeader objects that are serialized as XML. IE displays the serialized XML data as shown in the following figure: 3. Specify a different url:http://localhost:8000/slaes/orders?skip=100&top=5, and then check the return result. This time you will find that the first sales order number is 43759. 4. Then you can also separateTest other write URLs to check for various correct and incorrect results
URL |
results |
http://localhost:8000/Sales/Orders?t OP=-10 |
return error also page |
http://localhost:8000/Sales/Orders/43700 |
return Dingbian number to 43700 Order Details |
http://localhost:8000/Sales/Orders/30000 |