WCF Tutorial

Wednesday, August 12, 2009 10:09
Posted in category HowTo

The following is a relatively simple address lookup service that illustrates how to create a loosely coupled WCF service with commonly accepted best practices: SRP; Repository Pattern; Service Layers; and Dependency Injection.

The first step is to identify the data that will need to be exchanged by the service.  Often, it will be necessary / desired to utilize objects for this data exchange.  This is accomplished through the use of Data Contracts.  Here is a sample Data Contact that one might have for an address lookup service:

   1:  <DataContract()> _
   2:  Public Class Address
   3:   
   4:      Private _address As String
   5:      Private _city As String
   6:      Private _state As String
   7:      Private _zip As String
   8:   
   9:      <DataMember()> _
  10:      Public Property Address() As String
  11:          Get
  12:              Return _address
  13:          End Get
  14:          Set(ByVal varAddress As String)
  15:              _address = varAddress
  16:          End Set
  17:      End Property
  18:   
  19:      <DataMember()> _
  20:      Public Property City() As String
  21:          Get
  22:              Return _city
  23:          End Get
  24:          Set(ByVal varCity As String)
  25:              _city = varCity
  26:          End Set
  27:      End Property
  28:   
  29:      <DataMember()> _
  30:      Public Property State() As String
  31:          Get
  32:              Return _state
  33:          End Get
  34:          Set(ByVal varState As String)
  35:              _state = varState
  36:          End Set
  37:      End Property
  38:   
  39:      <DataMember()> _
  40:      Public Property Zip() As String
  41:          Get
  42:              Return _zip
  43:          End Get
  44:          Set(ByVal varZip As String)
  45:              _zip = varZip
  46:          End Set
  47:      End Property
  48:   
  49:  End Class

Now that our data contracts are defined we need to create our Repository interface:

   1:  Public Interface IAddressRepository
   2:      Function ListAddresses(ByVal varAddress As String) As List(Of Address)
   3:  End Interface

and our Repository concrete class:

   1:  Imports System.Data.SqlClient
   2:   
   3:  Public Class AddressRepository_DataServices
   4:      Implements IAddressRepository
   5:   
   6:      Public Function ListAddresses(ByVal varAddress As String) _
   7:                  As List(Of Address) _
   8:                  Implements IAddressRepository.ListAddresses
   9:          Dim _address As Address
  10:          Dim _addressList As List(Of Address) = New List(Of Address)
  11:          Dim _commandText As String
  12:          Dim _connectionString As String = "$SOME_CONNECTION_STRING$"
  13:          Dim _sqlCommand As SqlCommand
  14:          Dim _sqlDataReader As SqlDataReader
  15:   
  16:          Using _sqlConnection As New SqlConnection(_connectionString)
  17:              _sqlCommand = New SqlCommand()
  18:              _commandText = "USP_ADDRESS_SELECT"
  19:              With _sqlCommand
  20:                  .Connection = _sqlConnection
  21:                  .Parameters.AddWithValue("@ADDRESS", varAddress)
  22:                  .CommandText = _commandText
  23:                  .CommandType = CommandType.StoredProcedure
  24:              End With
  25:              _sqlConnection.Open()
  26:              _sqlDataReader = _sqlCommand.ExecuteReader()
  27:              If _sqlDataReader.HasRows Then
  28:                  Do While _sqlDataReader.Read()
  29:                      _address = New Address()
  30:                      With _address
  31:                          .Address = _sqlDataReader("ADDRESS").ToString()
  32:                          .City = _sqlDataReader("CITY").ToString()
  33:                          .State = _sqlDataReader("STATE").ToString()
  34:                          .Zip = _sqlDataReader("ZIP").ToString()
  35:                      End With
  36:                      _addressList.Add(_address)
  37:                  Loop
  38:              End If
  39:          End Using
  40:   
  41:          Return _addressList
  42:      End Function
  43:   
  44:  End Class

This example is relatively simple and as such only has one interface and corresponding concrete class.  Since the Repository is to handle any and all data requests, a typically Repository would have many more. However, as this Repository is complete, we can move on to creating our Service Layer; which will contain all of our business logic.  Again we create both an interface:

   1:  Public Interface IAddressServiceLibrary
   2:      Function Search(ByVal varAddress As String) As List(Of Address)
   3:  End Interface

and concrete class:

   1:  Public Class AddressServiceLibrary
   2:      Implements IAddressServiceLibrary
   3:   
   4:      Private _addressRepository As IAddressRepository = New AddressRepository_DataServices()
   5:   
   6:      Public Function Search(ByVal varAddress As String) As List(Of Address) Implements IAddressServiceLibrary.Search
   7:          Return _addressRepository.ListAddresses(varAddress)
   8:      End Function
   9:   
  10:  End Class

With the business logic taken care of it is time to create our WCF service, consisting of a Service Contract and one or more Operation Contracts.  Once again we create an interface:

   1:  <ServiceContract()> _
   2:  Public Interface IAddressLookupService
   3:      <OperationContract()> _
   4:      Function Search(ByVal varAddress As String) As List(Of Address)
   5:  End Interface

and a concrete class:

   1:  Public Class AddressLookupService
   2:      Implements IAddressLookupService
   3:   
   4:      Private _addressServiceLibrary As IAddressServiceLibrary = New AddressServiceLibrary()
   5:   
   6:      Public Function Search(ByVal varAddress As String) As List(Of Address) Implements IAddressLookupService.Search
   7:          Return _addressServiceLibrary.Search(varAddress)
   8:      End Function
   9:   
  10:  End Class

Our WCF service is now complete.  This sample could be extended to also utilize the Decorator Pattern; however, in the interest of brevity I have opted to not include in this posting.

You can skip to the end and leave a response. Pinging is currently not allowed.

Leave a Reply