Returning User-Defined Types

It is often necessary to return user-defined types from a method, such as employee or department. When doing so, the WebService serialization will create a generic representation of the data element to return to the client. It is important to understand that WebServices should be used to return data and not objects. Essentially, a memento should be returned rather than trying to instantiate an object and attempt distributed reference counts.

A memento represents the current state of an object or the data necessary to describe an object. In the case of an employee, the basic information such as ID, name, department, and photo ID would represent the data associated with the employee.

The serialization services will serialize all public fields and public properties with GET assessors. To support de-serialization, the corresponding properties must also implement SET as well as GET within the accessory. Each field or property will be mapped to an XML element. This default behavior might serve well enough for simple services and serves as a starting point for using User Defined Types (UDT) within the context of a WebService.

Creating the Service

Start by creating a WebService named UDTWebService using VS.NET and rename the default Service1.asmx file to UDTService.asmx. As with all the WebServices created so far, the actual implementation will reside in the code-behind page.

The WebService will provide a method that will locate a person based on his or her last name; hence, the name of the method will be LocatePerson. Before implementing the method, it will be necessary to create a Person class that can be used to return the information to a WebService client (see Listing 4.4.8).

Listing 4.4.8. The UDTPerson Class
 1: namespace UDTWebService
 2: {
 3:     using System;
 4:
 5:     /// <summary>
 6:     ///  The Person Class represents a basic UDT( User Defined Type )
 7:     /// </summary>
 8:     public class UDTPerson
 9:     {
10:         ///Private Fields
11:         private string    m_FirstName;
12:         private string    m_LastName;
13:
14:         //Public Properties
15:         public string FirstName
16:         {
17:             get {  return m_FirstName; }
18:             set {  m_FirstName = value; }
19:         }
20:
21:         public string LastName
22:         {
23:             get {  return m_LastName; }
24:             set {  m_LastName = value; }
25:         }
26:
27:
28:         //Constructor(s)
29:         public UDTPerson( )
30:         {
31:             //Default Constructor
32:         }
33:
34:         public UDTPerson( string FName, string LName )
35:         {
36:             m_FirstName = FName;
37:             m_LastName = LName;
38:         }
39:     }
40: }
41:

The UDTPerson class represents a basic C# class with no attributes applied to it. So how can it be serialized? Remember the Reflection API? This is the mechanism used to serialize this class. The WebService underpinning will use Reflection to scrape out information from the class and serialize that information. Again, only public fields or properties will be serialized.

With the implementation of UDTPerson completed, the next step is to add the LocatePerson method to the UDTService class. Update the UDTService class using the code appearing in Listing 4.4.9.

Listing 4.4.9. UDTService Source
 1: using System;
 2: using System.Collections;
 3: using System.ComponentModel;
 4: using System.Data;
 5: using System.Diagnostics;
 6: using System.Web;
 7: using System.Web.Services;
 8:
 9: namespace UDTWebService
10: {
11:     /// <summary>
12:     /// Summary description for UDTService.
13:     /// </summary>
14:     public class UDTService : System.Web.Services.WebService
15:     {
16:         private Hashtable    htPeople;
17:
18:         public UDTService()
19:         {
20:              //CODEGEN: This call is required by the ASP.NET Web Services Designer
21:              InitializeComponent();
22:
23:              //Load the hashtable
24:              //Add some people to the hashtable
25:              htPeople = new Hashtable( );
26:              htPeople.Add( "Weeks", new UDTPerson( "Richard", "Weeks" ) );
27:              htPeople.Add( "Powell", new UDTPerson( "Bob", "Powell" ) );
28:              htPeople.Add( "Martschenko", new UDTPerson( "Bill", "Martschenko" ) );
29:              htPeople.Add( "Schumacher",  new UDTPerson( "Greg", "Schumacher" ) );
30:              htPeople.Add( "Pitzer", new UDTPerson( "Jay", "Pitzer" ) );
31:
32:         }
33:
34:         #region Component Designer generated code
35:         /// <summary>
36:         /// Required method for Designer support - do not modify
37:         /// the contents of this method with the code editor.
38:         /// </summary>
39:         private void InitializeComponent()
40:         {
41:         }
42:         #endregion
43:
44:         /// <summary>
45:         /// Clean up any resources being used.
46:         /// </summary>
47:         protected override void Dispose( bool disposing )
48:         {
49:         }
50:
51:         [WebMethod]
52:          public UDTPerson LocatePerson( string LastName ) {
53:
54:             try {
55:                 return (UDTPerson)htPeople[ LastName ];
56:             }  catch( Exception ) {
57:             }
58:             return null;
59:         }
60:     }
61: }

Rather than retrieving from a database, this example creates a hash table to hold a few different people for whom to search. The LocatePerson method on line 52 takes the LastName as a string parameter. It is important to notice that the method looks no different than the WebMethod found in the EchoService. Because the default serialization mechanism handles the common case, you do not need to provide custom serialization code for the UDTPerson class.

Generating a Client Binding

Again, the WSDL.exe tool can be used to create the necessary client proxy class for invoking the LocatePerson method. Along with the proxy class, WSDL.exe will generate a simple class that represents the UDTPerson return type. The reason for this is that most users of your WebService will not have access to the code behind the service. Instead, they will have to rely on the WSDL description of the site to create the necessary client code to invoke any given service. Listing 4.4.10 shows the generated code produced by the WSDL.exe tool for the UDTService.

Listing 4.4.10. UDTService Proxy Code
 1: //------------------------------------------------------------------------
 2: // <autogenerated>
 3: //     This code was generated by a tool.
 4: //     Runtime Version: 1.0.2914.11
 5: //
 6: //     Changes to this file may cause incorrect behavior and will be lost if
 7: //     the code is regenerated.
 8: // </autogenerated>
 9: //------------------------------------------------------------------------
10:
11: //
12: // This source code was auto-generated by wsdl, Version=1.0.2914.11.
13: //
14: using System.Diagnostics;
15: using System.Xml.Serialization;
16: using System;
17: using System.Web.Services.Protocols;
18: using System.Web.Services;
19:
20:
21: [System.Web.Services.WebServiceBindingAttribute(Name="UDTServiceSoap", Namespace="http
://tempuri.org/")]
22: public class UDTService : System.Web.Services.Protocols.SoapHttpClientProtocol {
23:
24:     [System.Diagnostics.DebuggerStepThroughAttribute()]
25:     public UDTService() {
26:         this.Url = "http://localhost/UDTWebService/UDTService.asmx";
27:     }
28:
29:     [System.Diagnostics.DebuggerStepThroughAttribute()]
30:     [System.Web.Services.Protocols.SoapDocumentMethodAttribute ("http://tempuri.org
/LocatePerson",  Use=System.Web.Services.Description.SoapBindingUse.Literal,
 ParameterStyle=System.Web.Services.Protocols. SoapParameterStyle.Wrapped)]
31:     public UDTPerson LocatePerson(string LastName) {
32:         object[] results = this.Invoke("LocatePerson", new object[] {
33:                     LastName} );
34:         return ((UDTPerson)(results[0]));
35:     }
36:
37:     [System.Diagnostics.DebuggerStepThroughAttribute()]
38:     public System.IAsyncResult BeginLocatePerson(string LastName, System.AsyncCallback
 callback, object asyncState) {
39:         return this.BeginInvoke("LocatePerson", new object[] {
40:                     LastName} , callback, asyncState);
41:     }
42:
43:     [System.Diagnostics.DebuggerStepThroughAttribute()]
44:     public UDTPerson EndLocatePerson(System.IAsyncResult asyncResult) {
45:         object[] results = this.EndInvoke(asyncResult);
46:         return ((UDTPerson)(results[0]));
47:     }
48: }
49:
50: public class UDTPerson {
51:
52:     public string FirstName;
53:
54:     public string LastName;
55: }

The WSDL.exe-generated code is basically the same as seen before; the new addition to notice is the UDTPerson class that was generated. Notice that the FirstName and LastName attributes are created as public fields rather than private fields. WSDL.exe has no way of knowing the actual implementation of UDTPerson as it exists on the server; instead, WSDL.exe must utilize the information found in the wsdl document to construct the proxy and referenced types.

Invoking UDTService.LocatePerson from Internet Explorer will produce an XML return and display it in the browser, as shown in Figure 4.4.8. This XML represents the return message from the WebService. Take a minute to study how the XML maps to the UDTPerson class created by the WSDL.exe tool.

Figure 4.4.8. The XML result from LocatePerson.


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.226.88.110