WCF Tutorial
Wednesday, August 12, 2009 10:09The 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.