Thus far, you've looked at the standard web service files created by the Visual Studio web service template. Now you're ready to explore developing an actual web service with Visual Studio 2005. For this example, you will develop a CustomerProfile web service. This web service will provide methods for retrieving customer information from a data store and saving changes to that information. Along the way, you will look at the finer points of developing a .NET web service. Creating the Web ServiceTo create the web service, you add a new web service item to an ASP .NET application. For this example, you start with a web service project and create the CustomerProfile.asmx service. Next, you remove the HelloWorld sample method and in its place develop your web methods. These sample methods include GetCustomerProfile and SaveCustomer. The GetCustomerProfile method takes a customer ID as a parameter and returns a customer object. The SaveCustomer method takes an instance of this same customer object but does not return a value. Listing 16.1 shows the sample code for the service. Listing 16.1. Customer Profile Web Service
It is important to note that Listing 16.1 references a couple of projects that are outside the web service project. The first is the BusinessEntities project. This project (and namespace) contains the actual definition for the Customer object. You reference this project the same way you add a reference to any other project. The second project referenced is EntityServices. This namespace provides the actual implementation of the code that executes on behalf of the service. In fact, the SaveCustomer web method is actually a proxy for the EntityServices.CustomerProfile.SaveCustomer method. This latter method does the work to actually save the customer. This proxy implementation pattern is optional. You could define all your execution logic right inside the web service. However, we are showing this example for two reasons. The first is that most applications built today leverage some existing code. It can be useful to build a proxy to expose this existing code through web services. The second point is that this is just good design. Having the implementation code inside a separate object can lead to reuse, can enable easier unit testing, and can enable client scenarios that are more traditional (and do not rely on web services). Tip When you're building a web service, it is best to group functionality into course-grained interfaces. You don't want web methods that do a number of fine-grained operations such as setting properties prior to calling a method. This chatty nature can be expensive when communicating across the Internet. Of course, this approach is also contrary to most object-oriented application designs. Therefore, the use of a proxy object to bundle operations around a business object is ideal. The business object can be serialized and passed across the wire. On the other side, it can be deserialized and then worked with in an in-process manner (where chatty calls are not expensive). Now that you have built the sample service, you're ready to look at what makes this class a web service. In addition, the following sections elaborate on the definition of web methods. The WebService Attribute ClassThe WebService attribute class (also called WebServiceAttribute) can be used to provide additional details about a given web service. You may apply this attribute when declaring a class as a web service. However, the attribute is not required. It merely gives context about a web service. For example, we used the WebService attribute on the CustomerProfile class declaration to provide details about the web service's namespace. The following are the descriptive elements you can define with the WebService attribute class:
The WebService ClassThe WebService class represents the base class for .NET web services. This is not to be confused with the WebService attribute class (see the preceding section). You derive from this class in order to use the common ASP.NET objects (Session, Application, Context, and so on). However, it is not mandatory that you do so. Visual Studio enforces this inheritance when you define a new web service, but you can remove this code if you have no intention of leveraging the ASP objects within your web service. If you choose to derive from WebService, then you access these ASP.NET objects the same way you would inside any web application. The WebMethod Attribute ClassThe WebMethod attribute class is used to indicate that a method in your service should be exposed via the web service. This declaration is mandatory for all methods that you intend to make available through the web service. There are a number of parameters you can set when defining a web method. These parameters control how the web method operates. For the example, you will simply set the Description parameter to document a description of the method. However, the following provides a more comprehensive list of parameters on the WebMethod attribute:
Accessing and Invoking the Web ServiceVisual Studio and the .NET Framework enable you to view a given web service inside the web browser. This capability can be useful for both testing a web service and discovering how one works (the messages they require and return). To access a web service, you first build (compile) it in Visual Studio and then access the .asmx file in a browser. Figure 16.4 shows the CustomerProfile web service example in a browser window. Notice that both methods of the service are listed. Each method's description is also provided. This is the same description entered in the web method definition (WebMethodAttribute). Figure 16.4. Navigating to the web service.Viewing the Formal Web Service DescriptionTo see the actual formal description of the web service as it is defined in WSDL, you can select the link Service Description from the page shown in Figure 16.4. When you click this link, the WSDL parameter is passed to the .asmx file on the QueryString. This tells .NET to return the WSDL of the service. This WSDL is generated for you by .NET. It conforms to the WSDL standards and can therefore be used by clients that want to access your service. These clients use this WSDL to understand how your web service operates. Note .NET ships with a tool named Disco.exe. Visual Studio uses this tool to generate files related to the understanding and discovery of web services. You, too, can leverage this tool from the command line to generate these documents and store them for examination and use. The documents created by Disco.exe serve as the input for client applications that consume the web service. These client applications are created using a related tool called WSDL.exe. You can find the complete listing of the WSDL for the CustomerProfile service in Listing 16.2. This listing is easier to view in a browser (where you get color-coding and a tree-like structure to navigate the XML). However, the listing is provided here for your reference. As you scan it, notice how each service is defined. Also notice how the Customer complex type is embedded inside the WSDL. This complex type was generated based on the sample Customer object (BusinessEntities.Customer). Recall that this type is a return value to one method and a parameter to another. You can see that .NET is converting this to an XML type for use by web services. Listing 16.2. The Web Service WSDL
Viewing the Web MethodWhen you click on the web method name, .NET generates a web form for you to use to test the given web service. This form is accessed from the .asmx file (URI) with the QueryString parameter op (operation). You pass the name of the web method to this parameter. For the example, look at the web method named GetCustomerProfile. Figure 16.5 shows this web form. Figure 16.5. The GetCustomerProfile web method.The top part of the form allows you to enter parameters for the web method and then invoke the actual web method using the HTTP POST protocol. This protocol is just one way to invoke the web method. Recall that you also use SOAP over HTTP and so on. This page shows actual examples of a SOAP request and response as well as HTTP. These examples can be useful if you want to see how messages should be constructed for these protocols. As an example, Listing 16.3 shows a SOAP message request for this web method. Notice that it indicates the <customerId> element must be passed to the method. This is of the primitive type int. Listing 16.4 shows the correlated SOAP response from the call. Notice here the SOAP result is contained in the element <GetCustomerProfileResult>. This page also contains examples of SOAP 1.1 and HTTP POST requests and responses. Listing 16.3. SOAP 1.2 Request
Listing 16.4. SOAP 1.2 Response
Invoking the Web MethodTo invoke the web method, you enter a value for the parameters and click the Invoke button (as shown in Figure 16.5). Doing so executes the web service and returns the results. The results are sent back as XML (as defined by the message). Remember, this invocation is HTTP POST. Figure 16.6 shows the results from the example. Figure 16.6. GetCustomerProfile results.Note You can use this method only to invoke web methods that take simple (primitive) data types as parameters. If your web method takes a complex type (SaveCustomer, for example), then you can still see the request/response examples but cannot invoke the web method in this manner. |