<span>Chapter 14: </span> Web Services and Exchange - Programming Microsoft Outlook and Microsoft Exchange 2003, Third Edition [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Programming Microsoft Outlook and Microsoft Exchange 2003, Third Edition [Electronic resources] - نسخه متنی

Thomas Rizzo

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
توضیحات
افزودن یادداشت جدید











Chapter 14: Web Services and Exchange

XML Web services allow you to expose programmable services to other applications or programmers. You can build XML Web services in two ways. The first way is by using Microsoft Visual Studio 6.0 and the SOAP Toolkit. The second way is to use Visual Studio .NET, which has built-in support for building and consuming Web services. This section will look at both techniques—you can decide which way is best for your needs.


Building a Web Service Using Visual Studio 6.0 and the SOAP Toolkit


To build a Web service using Visual Studio 6.0 and the SOAP Toolkit, you must first download and install the SOAP Toolkit from [ http://msdn.microsoft.com/soap ]. Using the toolkit, building a Web service is easy—you simply create the DLL that will implement your functionality. The Toolkit takes your DLL and creates a Web Services Definition Language (WSDL) file that contains the description of the methods, their parameters, and their return values for the DLL that implements your Web service. For our example, we will implement a free/busy lookup Web service. The following code for our free/busy lookup DLL was written using Visual Basic. Notice that the DLL exposes a public function as the main entry point that other applications can call:

Public Function GetFreeBusy(strDirURL As String, _
strUserNames As String, _
strStartDate As String, _
strEndDate As String, _
strInterval As String) As String
On Error Resume Next
'This function looks up free/busy information for users.
'User names must be email addresses separated by commas.
'The return value is a string of freebusy values for
'the users, separated by commas.
'Make sure a directory URL was passed
If strDirURL = " Then
GetFreeBusy = "You must pass a directory URL " & _
"in the format LDAP://directory"
Exit Function
End If
If Not (IsDate(strStartDate)) Then
'Not a date
GetFreeBusy = "Start Date is not a valid date!"
Exit Function
End If
If Not (IsDate(strEndDate)) Then
'Not a date
GetFreeBusy = "End Date is not a valid date!"
Exit Function
End If
If Not (IsNumeric(strInterval)) Then
GetFreeBusy = "You must enter a number for the interval."
Exit Function
ElseIf CInt(strInterval) <= 0 Then
GetFreeBusy = "You must enter a positive number for the interval."
Exit Function
End If
'Make sure that user names were passed
arrUserNames = Split(strUserNames, ",")
If UBound(arrUserNames) < 0 Then
'No usernames passed. Error and exit.
GetFreeBusy = "There were no user names passed."
Exit Function
End If
'Start building the string array for the free/busy info
strFreeBusy = "
For x = LBound(arrUserNames) To UBound(arrUserNames)
If strFreeBusy = " Then
strFreeBusy = strFreeBusy & PrivGetFreeBusy(arrUserNames(x), _
strDirURL, strStartDate, strEndDate, strInterval)
Else
strFreeBusy = strFreeBusy & "," & _
PrivGetFreeBusy(arrUserNames(x), strDirURL, _
strStartDate, strEndDate, strInterval)
End If
Next
GetFreeBusy = strFreeBusy
End Function
Private Function PrivGetFreeBusy(strUserName as String, _
strDirURL as String, _
strStartDate as String, _
strEndDate as String, _
strInterval as String) As String
On Error Resume Next
Dim oAddressee As CDO.Addressee
Set oAddressee = CreateObject("CDO.Addressee")
oAddressee.EmailAddress = strUserName
bFound = oAddressee.CheckName(strDirURL)
If bFound = False Then
PrivGetFreeBusy = "Could not resolve username: " & strUserName
Exit Function
End If
'Get the freebusy information
PrivGetFreeBusy = oAddressee.GetFreeBusy(strStartDate, strEndDate, _
strInterval)
Set oAddressee = Nothing
End Function

Next you generate a Web Service Description Language (WSDL) file and a Web Services Meta Language (WSML) file for your DLL. The WSDL file is an XML file that is a contract between the client and the server. It describes the format that the client should send to the server to call the Web service. The WSDL file for the free/busy Web service is shown here:

<?xml version='1.0' encoding='UTF-8' ?>
<!-- Generated 12/10/01 by Microsoft SOAP Toolkit WSDL File Generator,
Version 1.02.813.0 -->
<definitions name ='VS6FB' targetNamespace = 'http://tempuri.org/wsdl/'
xmlns:wsdlns='http://tempuri.org/wsdl/'
xmlns:typens='http://tempuri.org/type'
xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'
xmlns:stk='http://schemas.microsoft.com/soap-toolkit/wsdl-extension'
xmlns='http://schemas.xmlsoap.org/wsdl/'>
<types>
<schema targetNamespace='http://tempuri.org/type'
xmlns='http://www.w3.org/2001/XMLSchema'
xmlns:SOAP-ENC='http://schemas.xmlsoap.org/soap/encoding/'
xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/'
elementFormDefault='qualified'>
</schema>
</types>
<message name='FreeBusy.GetFreeBusy'>
<part name='strDirURL' type='xsd:string'/>
<part name='strUserNames' type='xsd:string'/>
<part name='strStartDate' type='xsd:string'/>
<part name='strEndDate' type='xsd:string'/>
<part name='strInterval' type='xsd:string'/>
</message>
<message name='FreeBusy.GetFreeBusyResponse'>
<part name='Result' type='xsd:string'/>
<part name='strDirURL' type='xsd:string'/>
<part name='strUserNames' type='xsd:string'/>
<part name='strStartDate' type='xsd:string'/>
<part name='strEndDate' type='xsd:string'/>
<part name='strInterval' type='xsd:string'/>
</message>
<portType name='FreeBusySoapPort'>
<operation name='GetFreeBusy' parameterOrder=
'strDirURL strUserNames strStartDate strEndDate strInterval'>
<input message='wsdlns:FreeBusy.GetFreeBusy' />
<output message='wsdlns:FreeBusy.GetFreeBusyResponse' />
</operation>
</portType>
<binding name='FreeBusySoapBinding' type='wsdlns:FreeBusySoapPort' >
<stk:binding preferredEncoding='UTF-8'/>
<soap:binding style='rpc'
transport='http://schemas.xmlsoap.org/soap/http' />
<operation name='GetFreeBusy' >
<soap:operation
soapAction='http://tempuri.org/action/FreeBusy.GetFreeBusy' />
<input>
<soap:body use='encoded'
namespace='http://tempuri.org/message/'
encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' />
</input>
<output>
<soap:body use='encoded'
namespace='http://tempuri.org/message/'
encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' />
</output>
</operation>
</binding>
<service name='VS6FB' >
<port name='FreeBusySoapPort' binding='wsdlns:FreeBusySoapBinding' >
<soap:address location='http://thomriznt52/vs6fb/VS6FB.WSDL' />
</port>
</service>
</definitions>

SOAP also requires a server-based WSML file, which provides the information that maps the operations of the service (as described in the WSDL file) to specific methods of the COM object. The WSML file determines which COM object and method should be used to service any requests. The WSML file for the sample is shown here:

<?xml version='1.0' encoding='UTF-8' ?>
<!-- Generated 12/10/01 by Microsoft SOAP Toolkit WSDL File Generator,
Version 1.02.813.0 -->
<servicemapping name='VS6FB'>
<service name='VS6FB'>
<using PROGID='ExchWS.FreeBusy' cachable='0' ID='FreeBusyObject' />
<port name='FreeBusySoapPort'>
<operation name='GetFreeBusy'>
<execute uses='FreeBusyObject' method='GetFreeBusy'
dispID='1610809344'>
<parameter callIndex='1' name='strDirURL'
elementName='strDirURL' />
<parameter callIndex='2' name='strUserNames'
elementName='strUserNames' />
<parameter callIndex='3' name='strStartDate'
elementName='strStartDate' />
<parameter callIndex='4' name='strEndDate'
elementName='strEndDate' />
<parameter callIndex='5' name='strInterval'
elementName='strInterval' />
<parameter callIndex='-1' name='retval'
elementName='Result' />
</execute>
</operation>
</port>
</service>
</servicemapping>

You might wonder how to go about generating these files. Well, you could attempt to generate the files by hand, but a much simpler and less error-prone approach is to use the WSDL generator tool from the SOAP Toolkit (shown in Figure 14-1).


Figure 14-1: The WSDL generator tool from the SOAP Toolkit

This tool outputs the files you need to create and call your Web service. The only other thing you need to do is test the service. The sample includes a consumer of the Web service. It is just a simple Visual Basic application that allows you to specify users, dates, the directory server, and the free/busy interval to use. The sample is shown in Figure 14-2.


Figure 14-2: The free/busy Web service consumer application

The consumer application uses the Microsoft SOAP Type Library and its SOAPClient object to talk to the Web service. The SOAPClient object makes it easy to connect to and call methods on a Web service. As you can see in the following code from the consumer application, the SOAPClient object has an MSSOAPINIT method that takes a WSDL file and a WSML file as arguments. If the method can successfully open these files from the Web service, the SOAPClient object will be initialized and can be used against the Web service. The SOAPClient object can then call Web service methods directly, and you can retrieve any failures or errors through the SOAPClient object as well.

Option Explicit
Private mSoapClient As SoapClient
Dim strServerResponse As String
Private Sub cmdConnect_Click()
On Error GoTo ErrorHandler
'See if there are any users
Dim NewSoapClient As New SoapClient
Dim WSDL As String
Dim WSML As String
If frmConnect.Connect(Me, WSDL, WSML) Then
Me.MousePointer = vbHourglass
NewSoapClient.mssoapinit WSDL, , , WSML
Set mSoapClient = NewSoapClient
cmdRefresh.Enabled = True
Me.MousePointer = vbNormal
End If
Exit Sub
ErrorHandler:
Me.MousePointer = vbDefault
If NewSoapClient.faultstring <> " Then
MsgBox "Connect failed. " & NewSoapClient.faultstring, _
vbExclamation
Else
MsgBox "Connect failed. " & Err.Description, vbExclamation
End If
Err.Clear
End Sub
Private Sub cmdRefresh_Click()
On Error GoTo ErrorHandler
listResponse.Clear
'Make sure the end date is not before the start date
If DateDiff("d", monthStart.Value, monthEnd.Value) < 0 Then
MsgBox "The end date must be after the start date!", _
vbOKOnly + vbExclamation
Exit Sub
End If
'Make sure interval is a #
If Not (IsNumeric(txtInterval.Text)) Then
MsgBox "You must enter a number for the interval.", _
vbOKOnly + vbExclamation
Exit Sub
ElseIf CInt(txtInterval.Text) < 0 Then
MsgBox "You must enter a number greater than zero.", _
vbOKOnly + vbExclamation
Exit Sub
End If
'Make sure there is a directory server
If txtDirServer.Text = " Then
MsgBox "You must enter a directory server!", _
vbOKOnly + vbExclamation
Exit Sub
End If
Me.MousePointer = vbHourglass
Dim strStartDate as String
Dim strEndDate as String
Dim strSMTPAddresses as String
'Figure out start and end date
strStartDate = monthStart.Value & " 12:00 AM"
strEndDate = monthEnd.Value & " 11:59 PM"
'Get the SMTP Addresses
If listUsers.ListCount > 0 Then
'Scroll through each user and separate with commas
Dim i
For i = 0 To listUsers.ListCount - 1
If i = 0 Then
strSMTPAddresses = listUsers.List(i)
Else
strSMTPAddresses = strSMTPAddresses & ", " & _
listUsers.List(i)
End If
Next
Else
MsgBox "You must enter users in order to query the server!", _
vbOKOnly + vbExclamation
Me.MousePointer = vbNormal
Exit Sub
End If
'Get the Response
strServerResponse = mSoapClient.GetFreeBusy(txtDirServer.Text, _
strSMTPAddresses, strStartDate, strEndDate, _
txtInterval.Text)
'Loop through the response and add it to the listbox
Dim arrResponse
arrResponse = Split(strServerResponse, ",")
For i = LBound(arrResponse) To UBound(arrResponse)
listResponse.AddItem arrResponse(i)
Next
Me.MousePointer = vbDefault
Exit Sub
ErrorHandler:
Me.MousePointer = vbDefault
If mSoapClient.faultstring <> " Then
MsgBox "Could not refresh application. " & _
mSoapClient.faultstring, vbExclamation
Else
MsgBox "Could not refresh application. " & Err.Description
End If
Err.Clear
End Sub

/ 227