Working with Data Contracts


When building the WCF services so far, the data contract that was defined depended upon simple types or primitive datatypes. In the case of the earlier WCF service, a .NET type of Integer was exposed, which in turn was mapped to an XSD type of int. You might not have seen the input and output types actually defined in the WSDL document that was provided via the WCF-generated one, but they are there. These types are actually exposed through an imported .xsd document (a dynamic document). This bit of the WSDL document is presented here:

  <wsdl:types>    <xsd:schema targetNamespace="http://tempuri.org/Imports">    <xsd:import schemaLocation="http://localhost:8000/docs?xsd=xsd0"     namespace="http://tempuri.org/" />    <xsd:import schemaLocation="http://localhost:8000/docs?xsd=xsd1"     namespace="http://schemas.microsoft.com/2003/10/Serialization/" />   </xsd:schema> </wsdl:types> 

Typing in the XSD location of http://localhost:8000/docs?xsd=xsd0 gives you the input and output parameters of the service. For instance, looking at the definition of the Add() method, you will see the following bit of code:

  <xs:element name="Add">    <xs:complexType>       <xs:sequence>          <xs:element minOccurs="0" name="a" type="xs:int" />          <xs:element minOccurs="0" name="b" type="xs:int" />       </xs:sequence>    </xs:complexType> </xs:element> <xs:element name="AddResponse">    <xs:complexType>       <xs:sequence>          <xs:element minOccurs="0" name="AddResult" type="xs:int" />       </xs:sequence>    </xs:complexType> </xs:element> 

This bit of XML code indicates that there are two required input parameters (a and b) that are of type int; in return, the consumer gets an element called <AddResult>, which contains a value of type int.

As a builder of this WCF service, you didn’t have to build the data contract, mainly because this service used simple types. When using complex types, you have to create a data contract in addition to your service contract.

Building a Service with a Data Contract

For an example of working with data contracts, create a new WCF service (again within a Console Application project) called WCF_WithDataContract. In this case, you still need an interface that defines your service contract, and then another class that implements that interface. In addition to these items, you also need another class that defines the data contract.

Like the service contract, which makes use of the <ServiceContract()> and the <OperationContract()> attributes, the data contract uses the <DataContract()> and <DataMember()> attributes. To gain access to these attributes, you have to make a reference to the System.Runtime.Serialization namespace in your project and import this namespace into the file.

The full WCF definition is presented here:

  Imports System Imports System.ServiceModel Imports System.Runtime.Serialization <DataContract()> _ Public Class Customer     <DataMember()> _     Public FirstName As String     <DataMember()> _     Public LastName As String End Class <ServiceContract()> _ Public Interface IHelloCustomer     <OperationContract()> _     Function HelloFirstName(ByVal cust As Customer) As String     <OperationContract()> _     Function HelloFullName(ByVal cust As Customer) As String End Interface Public Class HelloCustomer     Implements IHelloCustomer     Public Function HelloFirstName(ByVal cust As Customer) As String _       Implements IHelloCustomer.HelloFirstName         Return "Hello " & cust.FirstName     End Function     Public Function HelloFullName(ByVal cust As Customer) As String _       Implements IHelloCustomer.HelloFullName         Return "Hello " & cust.FirstName & " " & cust.LastName     End Function End Class 

Here, you can see that the System.Runtime.Serialization namespace is also imported, and the first class in the file is the data contract of the service. This class, the Customer class, has two members: FirstName and LastName. Both of these properties are of type String. You specify a class as a data contract through the use of the <DataContract()> attribute:

 <DataContract()> _ Public Class Customer    ' Code removed for clarity End Class

Now, any of the properties contained in the class are also part of the data contract through the use of the <DataMember()> attribute:

 <DataContract()> _ Public Class Customer     <DataMember()> _     Public FirstName As String     <DataMember()> _     Public LastName As String End Class

Finally, the Customer object is used in the interface as well as the class that implements the IHelloCustomer interface.

Building the Host

The next step is the same as before: Change the Module1.vb file so that it becomes the host of the WCF service you just built. This task is illustrated in the following example:

 Imports System Imports System.ServiceModel Imports System.ServiceModel.Description Module Module1     Sub Main()         Using serviceHost As ServiceHost = New ServiceHost(GetType(HelloCustomer))             Dim ntb As NetTcpBinding = New NetTcpBinding(SecurityMode.None)             serviceHost.AddServiceEndpoint(GetType(IHelloCustomer), ntb, _                New Uri("net.tcp://192.168.1.102:8080/HelloCustomer/"))             Dim smb As New ServiceMetadataBehavior()             smb.HttpGetEnabled = True             smb.HttpGetUrl = New Uri("http://localhost:8000/docs")             serviceHost.Description.Behaviors.Add(smb)             serviceHost.Open()             Console.WriteLine("Press the <ENTER> key to close the host.")             Console.ReadLine()         End Using     End Sub End Module

This host uses the IHelloCustomer interface and builds an endpoint at net.tcp://192.168.1.102:8080/HelloCustomer. Next, let’s look at consuming this service from another console application.

Building the Consumer

Now that the service is running and in place, the next step is to build the consumer. To begin, build a new console application from Visual Studio 2005 and call the project HelloWorldConsumer. Again, right-click on the solution and select Add Service Reference from the options provided in the menu.

From the Add Service Reference dialog, add http://localhost:8000/docs as the service URI and HelloCustomerService as the service reference name, as shown in Figure 30-11.

image from book
Figure 30-11

This will add the changes to the references and the app.config file just as before, enabling you to consume the service. The following code shows what is required:

  Module Module1     Sub Main()         Dim svc As New HelloCustomerService.HelloCustomerClient()         Dim cust As New HelloCustomerService.Customer()         Dim result As String         svc.Open()         Console.WriteLine("What is your first name?")         cust.FirstName = Console.ReadLine()           Console.WriteLine("What is your last name?")         cust.LastName = Console.ReadLine()         result = svc.HelloFullName(cust)         svc.Close()         Console.WriteLine(result)         Console.ReadLine()     End Sub End Module 

As a consumer, once you make the reference, you will notice that the service reference doesn’t just provide a HelloCustomerClient object; you will also find the Customer object that was defined through the service’s data contract.

Therefore, the preceding code block just instantiates both of these objects and builds the Customer object before it is passed into the HelloFullName() method provided by the service. Running this bit of code will return the results shown in Figure 30-12.

image from book
Figure 30-12

Looking at WSDL and the Schema for HelloCustomerService

When you make a reference to the HelloCustomer service, looking at the WSDL you will find the following XSD imports:

  <wsdl:types>    <xsd:schema targetNamespace="http://tempuri.org/Imports">       <xsd:import schemaLocation="http://localhost:8000/docs?xsd=xsd0"        namespace="http://tempuri.org/" />       <xsd:import schemaLocation="http://localhost:8000/docs?xsd=xsd1"        namespace="http://schemas.microsoft.com/2003/10/Serialization/" />       <xsd:import schemaLocation="http://localhost:8000/docs?xsd=xsd2"        namespace="http://schemas.datacontract.org/2004/07/WCF_WithDataContract" />    </xsd:schema> </wsdl:types> 

http://localhost:8000/docs?xsd=xsd2 provides the details on your Customer object. The code from this file is shown here:

  <?xml version="1.0" encoding="utf-8" ?> <xs:schema elementFormDefault="qualified"  targetNamespace="http://schemas.datacontract.org/2004/07/WCF_WithDataContract"  xmlns:xs="http://www.w3.org/2001/XMLSchema"  xmlns:tns="http://schemas.datacontract.org/2004/07/WCF_WithDataContract">    <xs:complexType name="Customer">       <xs:sequence>          <xs:element minOccurs="0" name="FirstName"           nillable="true" type="xs:string" />          <xs:element minOccurs="0" name="LastName"           nillable="true" type="xs:string" />       </xs:sequence>    </xs:complexType>    <xs:element name="Customer" nillable="true" type="tns:Customer" /> </xs:schema> 

This is an XSD description of the Customer object. Making a reference to the WSDL that includes the XSD description of the Customer object causes the auto-generated proxy class to create the following class as part of the proxy:

  <System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", _    "3.0.0.0"),  _    System.Runtime.Serialization.DataContractAttribute( _   [Namespace]:="http://schemas.datacontract.org/2004/07/WCF_WithDataContract"),  _      System.SerializableAttribute()>  _     Partial Public Class Customer         Inherits Object         Implements System.Runtime.Serialization.IExtensibleDataObject         <System.NonSerializedAttribute()>  _         Private extensionDataField As _            System.Runtime.Serialization.ExtensionDataObject         <System.Runtime.Serialization.OptionalFieldAttribute()>  _         Private FirstNameField As String         <System.Runtime.Serialization.OptionalFieldAttribute()>  _         Private LastNameField As String         Public Property ExtensionData() As _            System.Runtime.Serialization.ExtensionDataObject Implements _              System.Runtime.Serialization.IExtensibleDataObject.ExtensionData             Get                 Return Me.extensionDataField             End Get             Set                 Me.extensionDataField = value             End Set         End Property         <System.Runtime.Serialization.DataMemberAttribute()>  _         Public Property FirstName() As String             Get                 Return Me.FirstNameField             End Get             Set                 Me.FirstNameField = value             End Set         End Property         <System.Runtime.Serialization.DataMemberAttribute()>  _         Public Property LastName() As String             Get                Return Me.LastNameField            End Get            Set                Me.LastNameField = value            End Set        End Property    End Class 

Using this model, you can easily build your services with your own defined types.




Professional VB 2005 with. NET 3. 0
Professional VB 2005 with .NET 3.0 (Programmer to Programmer)
ISBN: 0470124709
EAN: 2147483647
Year: 2004
Pages: 267

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net