Parsing the XML Request
When a client application sends an XML request to the Project Data Service (PDS) in Microsoft® Office Project Server 2003, if the PDS doesn't recognize the request, it looks for a registered PDS extender that implements the requested method. If the PDS finds an extender with the requested method, it then checks whether the extender implements a public method named XMLRequestEx or XMLRequest. If the public method is XMLRequestEx, the PDS calls the extender with the new syntax for Project Server 2003; otherwise, the PDS uses the legacy style syntax for Project Server 2002.
The Microsoft Visual Basic® 6.0 project in the Project 2003: Project Renamer PDS Extender (pj11pdsxRenamer.exe) download is ProjectRenamer.vbp; it contains only one class, CMain (CMain.cls), which implements the public functions XMLRequestEx and RenameProject and the private helper functions.
The Public XMLRequestEx Function
Following is the XMLRequestEx signature.
Public Function XMLRequestEx( _
ByVal sXML As String, _
ByVal sPDSInfoEx As String, _
ByRef nHandled As Integer) _
As String
XMLRequestEx parses the sPDSInfoEx parameter into member variables for the user logon, path, and database information. The sPDSInfoEx parameter contains an XML string with the following information; the SOAPRequestCookie and HTTPRequestCreate elements are optional, depending on whether the request arrived by SOAP or HTTP POST.
<PDSExtensionXML>
<UserName></UserName>
<UserGUID></UserGUID>
<UserID></UserID>
<PDSConnect></PDSConnect>
<BasePath></BasePath>
<DBType></DBType>
<SOAPRequestCookie></SOAPRequestCookie>
<HTTPRequestCreate></HTTPRequestCreate>
</PDSExtensionXML>
For more information on the XMLRequestEx function and parameters, see Writing a PDS Extender.
XMLRequestEx loads and then calls the private XMLRequest function, as follows:
XMLRequestEx = XMLRequest(sXML, m_sUserName, m_sPDSConnect, m_eDatabaseType, nHandled)
The Private XMLRequest Function
XMLRequest validates and parses the ProjectRename method request, and also calls InitPjSvrSecurity to initialize the Project Server Security object (m_oPjSvrSecurity) with the BasePath value.
Following is the XMLRequest signature.
Private Function XMLRequest( _
ByVal sXML As String, _
ByVal sUser As String, _
ByVal sConnect As String, _
ByVal lDBType As Long, _
ByRef nHandled As Integer) _
As String
The primary parameter is sXML, which contains the XML request string. For the RenameProject method, this request takes the following form; there can be one or more Project elements:
<Request>
<ProjectRename>
<Project>
<ProjectID></ProjectID>
<NewName></NewName>
</Project>
<Project>
<ProjectID></ProjectID>
<NewName></NewName>
</Project>
. . .
</ProjectRename>
</Request>
XMLRequest uses the Microsoft XML Parser (MSXML) to check if the XML request is valid:
Dim lStatus As Long
Dim sXMLReply As String
Dim oXMLDocument As MSXML2.DOMDocument
Dim oXMLRoot As MSXML2.IXMLDOMElement
lStatus = STATUS_OK
If Len(sXML) = 0 Then
sXMLReply = "<Error>Request string is empty</Error>"
lStatus = STATUS_INVALID_REQUEST
GoTo PrepareReply
End If
Set oXMLDocument = New MSXML2.DOMDocument
oXMLDocument.loadXML sXML
If oXMLDocument.parseError.errorCode <> 0 Then
sXMLReply = "<Error>XML Parse error</Error>"
lStatus = STATUS_INVALID_REQUEST
GoTo PrepareReply
End If
Set oXMLRoot = oXMLDocument.firstChild
If oXMLRoot Is Nothing Then
sXMLReply = "<Error>Root node not found</Error>"
lStatus = STATUS_INVALID_REQUEST
GoTo PrepareReply
End If
If the XML request is valid, XMLRequest looks for the <Request> node and for the <ProjectRename> child node. If the <ProjectRename> node is present, XMLRequest uses the Project Server Security object (m_oPjSvrSecurity) to check the permissions before renaming any projects.
Dim sNodeName As String
sNodeName = oXMLRoot.nodeName
Select Case sNodeName
Case "Request"
Dim oNode As MSXML2.IXMLDOMNode
Dim oChildNode As MSXML2.IXMLDOMNode
For Each oNode In oXMLRoot.childNodes
sNodeName = oNode.nodeName
Select Case sNodeName
Case "ProjectRename"
'Check appropriate global user permissions for this call (if necessary)
If m_oPjSvrSecurity.CheckSPGlobalPermission(m_sUserGUID, _
PERMISSION_ADMIN_ENTERPRISE) <> 0 _
And m_oPjSvrSecurity.CheckSPGlobalPermission(m_sUserGUID, _
PERMISSION_ENT_NEW_PROJECT) <> 0 Then
lStatus = RenameProject(oNode)
nHandled = 1
Else
'Return Access Denied if the security check fails
lStatus = STATUS_ACCESS_DENIED
GoTo PrepareReply
End If
Case Else
lStatus = STATUS_UNKNOWN_REQUEST
GoTo PrepareReply
End Select
Next oNode
Case Else
lStatus = STATUS_UNKNOWN_REQUEST
GoTo PrepareReply
End Select
PrepareReply:
If lStatus = STATUS_UNKNOWN_REQUEST Then
nHandled = 0
Else
nHandled = 1
End If
XMLRequest = "<Reply><HRESULT>0</HRESULT><STATUS>" _
& Format$(lStatus, "0") & "</STATUS>" & sXMLReply & "</Reply>"
If XMLRequest does not recognize the request, it returns a status code that indicates the error. XMLRequest also sets the nHandled parameter to 0 if it cannot handle the request, or to 1 if it does handle the request. If nHandled is 0, that notifies the PDS to look for another extender that might be able to handle the request.
When the permission checks pass, XMLRequest sends the <ProjectRename> node to the RenameProject function. For more information, see Parsing the ProjectRename Method.