Returning Complex Data from a Web Service

Simple data can be returned by using the HTTP protocol. Complex data (instances of structures or classes) uses the SOAP protocol. It is worth knowing when various protocols come into play. SOAP used to mean Simple Object Access Protocol ; but now SOAP is just SOAP. However, the old expansion of the acronym describes nicely what SOAP does for us. SOAP makes it possible to transport an object across a network by using the self-describing nature of XML to include the description of the data along with the data.

Writing Web Services that return complex data types requires no special effort; however, you need to be aware of some additional things that happen with the related technologies. Thus I will show you a class and a Web Service that returns data representative of data that might be returned from a clearing corporation like the National Securities Clearing Corporation (if it were using Web Services) and the resulting impacts and opportunities for the Web Service consumers.

Implementing a Complex Type

Complex data in this context refers to structures or classes. You can define a class or structure and return it from a Web Service in much the same manner as you would return a class or structure from any DLL. The class I defined for this example (Listing 14.3) represents information that might be returned by a commissions clearing Web Service.

Listing 14.3 The CommissionsData Class
 Public Class CommissionsData   Private FSystemCode As String   Private FRecordType As String   Private FClearingSettlingFirmNumber As String   Private FFundProcessingDate As DateTime   Private FCommissionType As String   Private FDebitCreditIndicator As String   Private FDebitReasonCode As String   Private FSettlementIndicator As String   Private FRecordDate As DateTime   Public Property SystemCode() As String   Get     Return FSystemCode   End Get   Set(ByVal Value As String)     FSystemCode = Value   End Set   End Property   Public Property RecordType() As String   Get     Return FRecordType   End Get   Set(ByVal Value As String)     FRecordType = Value   End Set   End Property   Public Property ClearingSettlingFirmNumber() As String   Get     Return FClearingSettlingFirmNumber   End Get   Set(ByVal Value As String)     FClearingSettlingFirmNumber = Value   End Set   End Property   Public Property FundProcessingDate() As DateTime   Get     Return FFundProcessingDate   End Get   Set(ByVal Value As DateTime)     FFundProcessingDate = Value   End Set   End Property   Public Property CommissionType() As String   Get     Return FCommissionType   End Get   Set(ByVal Value As String)     FCommissionType = Value   End Set   End Property   Public Property DebitCreditIndicator() As String   Get     Return FDebitCreditIndicator   End Get   Set(ByVal Value As String)     FDebitCreditIndicator = Value   End Set   End Property   Public Property DebitReasonCode() As String   Get     Return FDebitReasonCode   End Get   Set(ByVal Value As String)     FDebitReasonCode = Value   End Set   End Property   Public Property SettlementIndicator() As String   Get     Return FSettlementIndicator   End Get   Set(ByVal Value As String)     FSettlementIndicator = Value   End Set   End Property   Public Property RecordDate() As DateTime   Get     Return FRecordDate   End Get   Set(ByVal Value As DateTime)     FRecordDate = Value   End Set   End Property End Class 

There isn't anything especially noteworthy about the CommissionsData class; it is comprised of fields and properties. I used the F prefix convention for fields and dropped the F prefix for properties. (Not even Microsoft is promoting the Hungarian notation anymore.)

Note that the class contains only fields and properties. We could implement methods and events for this class. However, there would be no impact on how we would implement the Web Service.

Implementing a Web Service

The CommissionsData class represents a complex type that we want to return from a Web Service. For our illustration it doesn't matter whether or not we have any data assigned to the members of CommissionsData . If we returned an instance of CommissionsData , that data would be returned along with the definition of the type when we invoked the Web method. Listing 14.4 demonstrates a simple Web method that returns a CommissionsData object.

Listing 14.4 A Web Method That Returns a CommissionsData Object
 Imports System.Web.Services <WebService(Namespace:="")> _ Public Class Service1   Inherits System.Web.Services.WebService   [ Web Services Designer generated code ]   <WebMethod()> _   Public Function GetData() As CommissionsData.CommissionsData     Return New CommissionsData.CommissionsData()   End Function End Class 

If you compare the Web Services in Listings 14.2 and 14.4, you will note that there are fundamentally no differences in the mechanics of implementing the Web Services. All the differences occur when the WSDL utility generates the proxy class and when we use the Web Service that returns a complex type.

Referencing a Web Service

When you add a Web reference to a project consuming a Web Service (see Chapter 13), WSDL generates several files. These files help bridge the gap between your Web Service and the client that consumes the Web Service. If you click on the namespace created by WSDL and then click the Show All Files toolbar button, the Reference.vb proxy file will be displayed in the Solution Explorer (Figure 14.2). You can also select the Reference.vb file from Windows Explorer by navigating to it and opening that file.

Figure 14.2. Click the Show All Files button to show the Reference.vb proxy file generated by the WSDL utility.


Exploring the Proxy Class

When you have added a Web reference to the Commissions Web Service, a proxy class is added to your project. (You can open the proxy class for the Commissions Web Service and follow along as we explore.) Listing 13.3 in the previous chapter shows an entire proxy file, and of course you can create a Web Service, reference it, and examine that proxy file too. For now we are interested only in the treatment of our CommissionsData class by the WSDL utility. Listing 14.5 shows just the generated CommissionsData proxy file.

Listing 14.5 The CommissionsData Proxy File Generated by WSDL
 <System.Xml.Serialization.XmlTypeAttribute( _ [Namespace]:="")> _   Public Class CommissionsData     '<remarks/>     Public RecordDate As Date     '<remarks/>     Public SystemCode As String     '<remarks/>     Public SettlementIndicator As String     '<remarks/>     Public RecordType As String     '<remarks/>     Public ClearingSettlingFirmNumber As String     '<remarks/>     Public FundProcessingDate As Date     '<remarks/>     Public CommissionType As String     '<remarks/>     Public DebitCreditIndicator As String     '<remarks/>     Public DebitReasonCode As String   End Class End Namespace 

Note that the generated proxy class contains only fields ”no properties, methods, or events (or anything else, for that matter). I refer to this as flattening the complex type. All our properties become public fields in the proxy class. If you think about this for a minute, it makes sense.

If Web Services returned fat objects ” with methods, events, properties, and other code ”Web Services would have to return all the assemblies and related assemblies across the wire. This means that Web Services would have to download and install binary files. For complex Web Services you might be referring to half of the CLR. Clearly, sending the CLR across the Web for each Web method invocation would not be a good thing. Even worse is that you might be dragging third-party code onto your workstation or server. (You don't know where that code has been.) Instead Web Services return a sanitary proxy class capable of containing data. So, in a way we are back to data-only data types, but just for Web Services. (Later in this chapter I will show you how to return fat objects from Web Services.)

Implementing the Web Service Consumer

The mechanism behind the WSDL tool is (probably) the CodeDOM. The CodeDOM contains classes that can generate very complex code. Thus far we know that almost everything about returning complex types in a Web Service is no more challenging than returning a simple type. The big difference is that the Web Service has the real class and the consumer gets a fields-only replica.

Clearly, you will not be able to invoke operations on the proxy class returned by the Web Service, but you can use the data. Listing 14.6 demonstrates a simple use of the proxy CommissionsData class: I use the fields information to generate a simple user input form. (This is for fun as much as for the hope that you'll find it a useful application for Reflection.)

Listing 14.6 Using Reflection to Generate a Simple User Interface
 1:  Imports Service = CommissionsDataApp.localhost.Service1 2:  Imports System.Reflection 3: 4:  Public Class Form1 5:    Inherits System.Windows.Forms.Form 6: 7:  [ Windows Form Designer generated code ] 8: 9:    Private Sub Form1_Load(ByVal sender As System.Object, _ 10:     ByVal e As System.EventArgs) Handles MyBase.Load 11: 12:     Dim Service As Service = New Service() 13: 14:     GenerateForm(Service.GetData().GetType()) 15: 16:   End Sub 17: 18:   Private Sub GenerateForm(ByVal Type As Type) 19: 20:     Dim Info As FieldInfo 21:     Dim Y As Integer = 0 22:     Dim Label As Label 23:     Dim TextBox As TextBox 24: 25:     For Each Info In Type.GetFields() 26: 27:       Label = New Label() 28:       Label.Text = Info.Name 29:       Label.Location = New Point(10, Y) 30:       Label.AutoSize = True 31:       Controls.Add(Label) 32: 33:       TextBox = New TextBox() 34:       TextBox.Location = New Point(20 + Label.Width, Y) 35:       Controls.Add(TextBox) 36:       Y += 25 37: 38:     Next 39: 40:   End Sub 41: End Class 

The code in Listing 14.6 is direct. I used the aliasing trick to shorten the namespace reference in line 1. I imported the System.Reflection namespace, which contains the FieldInfo class used to reflect the CommissionsData proxy class in lines 20 and 25. When the form loads (lines 12 and 14), I create an instance of the service and a simple user interface (Figure 14.3).

Figure 14.3. A user interface dynamically generated by using Reflection.


A practical application might be a form generator. For a commercial application we might employ the CodeDOM and generate actual code, supporting programmer customization. More likely, though, you will be using the data returned by the Web Service.

Downloading binary assemblies with executable code would not be secure. However, what if you download code that you know is reliable? For example, Microsoft supports returning DataSet objects from a Web Service, and these include methods too. Because the DataSet class contains known code from Microsoft and it is assumed that you have the CLR on the machine using the DataSet Web Service, it seems reasonable to support fat DataSet objects from Web Services. Let's take a look at how that works.

Visual Basic. NET Power Coding
Visual Basic(R) .NET Power Coding
ISBN: 0672324075
EAN: 2147483647
Year: 2005
Pages: 215
Authors: Paul Kimmel © 2008-2017.
If you may any questions please contact us: