WCF Outlook Demo - in VB.NET
[Updated: I added the source as a post attachment (thanks, Robert, for the suggestion).]
I often hear a lament that there exists too few examples for .NET 3.0 technologies using VB.NET. Here is a cool sample that shows how you can separate the service, contracts, and hosting code. The sample calls into Outlook and creates a contact, and exposes the service using named pipes.
Contoso.Contracts
The Contoso.Contracts project contains the DataContract and ServiceContract decorated types.
References: System.ServiceModel.dll, System.Runtime.Serialization.dll
Contact.vb
Imports System.Runtime.Serialization
Namespace Contoso.Contracts
<DataContract()> _
Public Class Contact
Private _imAddress As String
<DataMember()> _
Public Property IMAddress() As String
Get
Return _imAddress
End Get
Set(ByVal value As String)
_imAddress = value
End Set
End Property
Private _companyName As String
<DataMember()> _
Public Property CompanyName() As String
Get
Return _companyName
End Get
Set(ByVal value As String)
_companyName = value
End Set
End Property
Private _fullName As String
<DataMember()> _
Public Property FullName() As String
Get
Return _fullName
End Get
Set(ByVal value As String)
_fullName = value
End Set
End Property
Private _businessPhone As String
<DataMember()> _
Public Property BusinessPhone() As String
Get
Return _businessPhone
End Get
Set(ByVal value As String)
_businessPhone = value
End Set
End Property
Private _mobilePhone As String
<DataMember()> _
Public Property MobilePhone() As String
Get
Return _mobilePhone
End Get
Set(ByVal value As String)
_mobilePhone = value
End Set
End Property
Private _homePhone As String
<DataMember()> _
Public Property HomePhone() As String
Get
Return _homePhone
End Get
Set(ByVal value As String)
_homePhone = value
End Set
End Property
End Class
End Namespace
IContactService.vb
Imports System
Imports System.ServiceModel
Namespace Contoso.Contracts
<ServiceContract()> _
Public Interface IContactService
<OperationContract()> _
Sub CreateContact(ByVal c As Contact)
End Interface
End Namespace
Contoso.Outlook
This library contains the actual implementation logic. Think of this assembly as "business logic", or the meat behind the service facade.
References: Office.dll, Microsoft.Office.Interop.Outlook.dll
Contact.vb
Namespace Contoso.Outlook
Public Class Contact
Private _imAddress As String
Public Property IMAddress() As String
Get
Return _imAddress
End Get
Set(ByVal value As String)
_imAddress = value
End Set
End Property
Private _companyName As String
Public Property CompanyName() As String
Get
Return _companyName
End Get
Set(ByVal value As String)
_companyName = value
End Set
End Property
Private _fullName As String
Public Property FullName() As String
Get
Return _fullName
End Get
Set(ByVal value As String)
_fullName = value
End Set
End Property
Private _businessPhone As String
Public Property BusinessPhone() As String
Get
Return _businessPhone
End Get
Set(ByVal value As String)
_businessPhone = value
End Set
End Property
Private _mobilePhone As String
Public Property MobilePhone() As String
Get
Return _mobilePhone
End Get
Set(ByVal value As String)
_mobilePhone = value
End Set
End Property
Private _homePhone As String
Public Property HomePhone() As String
Get
Return _homePhone
End Get
Set(ByVal value As String)
_homePhone = value
End Set
End Property
End Class
End Namespace
Contacts.vb
Imports Microsoft.Office.Interop.Outlook
Namespace Contoso.Outlook
Public Class Contacts
Public Sub StoreContact(ByVal c As Contact)
Dim outlookApp As Microsoft.Office.Interop.Outlook.Application = New Microsoft.Office.Interop.Outlook.Application()
Dim newContact As Microsoft.Office.Interop.Outlook.ContactItem = CType(outlookApp.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olContactItem), Microsoft.Office.Interop.Outlook.ContactItem)
With newContact
.FullName = c.FullName
.FileAs = c.FullName
.CompanyName = c.CompanyName
.BusinessTelephoneNumber = c.BusinessPhone
.HomeTelephoneNumber = c.HomePhone
.IMAddress = c.IMAddress
.MobileTelephoneNumber = c.MobilePhone
End With
newContact.Save()
End Sub
End Class
End Namespace
Contoso.Services
This assembly contains the implementation of the service contracts. This is separated from the contracts assembly because you could distribute the Contoso.Contracts assembly to consumers of your service and use the ChannelFactory.CreateChannel method instead of generating a service proxy. If the service logic were contained in that assembly, you would potentially expose sensitive code.
References: Contoso.Contracts.dll, Contoso.Outlook.dll, System.ServiceModel.dll, System.Runtime.Serialization.dll
ContactService.vb
Imports System
Imports System.ServiceModel
Imports Contoso.Contracts
Imports OutlookLib = Contoso.Outlook
Namespace Contoso.Services
Public Class ContactService
Implements IContactService
Public Sub CreateContact(ByVal c As Contact) Implements IContactService.CreateContact
Dim c2 As OutlookLib.Contact = New OutlookLib.Contact()
c2.BusinessPhone = c.BusinessPhone
c2.CompanyName = c.CompanyName
c2.FullName = c.FullName
c2.HomePhone = c.HomePhone
c2.IMAddress = c.IMAddress
c2.MobilePhone = c.MobilePhone
Dim contacts As OutlookLib.Contacts = New OutlookLib.Contacts()
contacts.StoreContact(c2)
End Sub
End Class
End Namespace
Contoso.Hosting
This assembly hosts the WCF service in a Console application.
References: Contoso.Contracts.dll, Contoso.Services.dll, System.ServiceModel.dll, System.Runtime.Serialization.dll
ServiceHost.vb
Imports System
Imports System.ServiceModel
Imports System.Configuration
Imports Contoso.Services
Public Class Host
Friend Shared myHost As ServiceHost = Nothing
Friend Shared Sub StartService()
Dim baseAddress As Uri = New Uri(ConfigurationManager.AppSettings("baseAddress"))
myHost = New ServiceHost(GetType(ContactService), baseAddress)
myHost.Open()
End Sub
Friend Shared Sub StopService()
If myHost.State <> CommunicationState.Closed Then
myHost.Close()
End If
End Sub
End Class
Program.vb
Namespace Contoso.Hosting
Module Program
Public Sub Main()
Console.WriteLine("starting the service...")
Host.StartService()
Console.WriteLine("service started. Press ENTER to continue.")
Console.ReadLine()
Host.StopService()
End Sub
End Module
End Namespace
app.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="baseAddress" value="net.pipe://localhost/Contoso"/>
</appSettings>
<system.serviceModel>
<services>
<service name="Contoso.Services.ContactService">
<endpoint address="Outlook" binding="netNamedPipeBinding" contract="Contoso.Contracts.IContactService" />
</service>
</services>
<behaviors>
<behavior name="returnFaults" returnUnknownExceptionsAsFaults="true" />
</behaviors>
</system.serviceModel>
</configuration>
client
This assembly is a simple client. Instead of using Add Service Reference in Visual Studio, we take advantage of the fact that the contracts were implemented in a DLL that we can share out to consumers. The client references the contracts and uses this to consume the service. Run the client, then check your Contacts in Outlook and see that you have a new contact.
References: Contoso.Contracts.dll, System.ServiceModel.dll, System.Runtime.Serialization.dll
Program.vb
Imports Contoso.Contracts
Imports System.ServiceModel
Module Program
Sub Main()
Dim c As Contact = New Contact()
c.BusinessPhone = "4045551212"
c.CompanyName = "Contoso"
c.FullName = "John Jacob Jingleheimerschmidt"
c.HomePhone = "4048675309"
c.IMAddress = "freeporn@hotmail.com"
c.MobilePhone = "7705551212"
Dim factory As ChannelFactory(Of IContactService) = New ChannelFactory(Of IContactService)("default")
Dim proxy As IContactService = factory.CreateChannel()
proxy.CreateContact(c)
End Sub
End Module
app.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<client>
<endpoint
address="net.pipe://localhost/Contoso/Outlook"
binding="netNamedPipeBinding"
contract="Contoso.Contracts.IContactService"
name="default"/>
</client>
</system.serviceModel>
</configuration>
Comments
- Anonymous
August 29, 2006
The comment has been removed - Anonymous
August 29, 2006
Kirk Allen Evans has a cool demo of how WCF abstracts away some of the service implementation details... - Anonymous
October 01, 2006
Kirk Allen Evans has a cool demo of how WCF abstracts away some of the service implementation details