PS2007 Project Details (JavaScript)

Post three and now things are getting a little more interesting. We leave the blanket of .Net and head out into the cold harsh reality of HTML, XML, and JavaScript. I want to do the same thing I did in the previous examples... get the list of projects on the Project Server, then display the details of each one on demand. First thing I need to do is figure out how to call a web service from JavaScript. First thought is SOAP toolkit, I used to use that back in the day. But it has been deprecated due to .Net, that's a no starter. How about XMLHTTP? It comes with XML so it should be installed on many user machines already, I think this is the way to go. After some research I find a good structure for using XMLHHTP is

    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");

    xmlhttp.open("POST", sSoapPostURL, false);

    xmlhttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");

    xmlhttp.setRequestHeader("SOAPAction", sSoapAction);

    xmlhttp.send(sRequest);

We’ve go three parameters to deal with: sSoapPostURL, sSoapAction, sRequest

sSoapPostURL is pretty straight forward, it’s the URL for the web service. I’ve done this from .Net, it should look something like:

sSoapPostURL = myserver + '/_vti_bin/psi/project.asmx';

sSoapAction starts me scratching my head. It hasn’t been that long since I’ve written to a web service without .Net… has it? Yeah it has, been then I remember the WSDL (Web Service Description Language). Every web service needs one of these and that is where I get the information from. I start hunting through the Project Server directories, and don’t find a WSDL file in sight. What I do find is a bunch of aspx files named like projectwsdl.aspx and projectdisco.aspx. I open them up and surprise, just what I’m looking for. I have the signature of the service and can go dancing in the 70s after (ok bad joke). But….aaaackkk what a mess to navigate. Just when I’m about to dig in I remember adding web services to .Net… and a cool dialog box that has everything I’m looking for. I go to the “Add Web Reference” dialog, and reference project.asmx. I get a list of methods, click on ProjectList and sweet nectar I see the following:

POST /SharedServices1/PSI/project.asmx HTTP/1.1

Host: lduffps2007

Content-Type: text/xml; charset=utf-8

Content-Length: length

SOAPAction: "https://schemas.microsoft.com/office/project/server/webservices/Project/ReadProjectList"

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

  <soap:Body>

    <ReadProjectList xmlns="https://schemas.microsoft.com/office/project/server/webservices/Project/" />

  </soap:Body>

</soap:Envelope>

Not only have I found my SoapAction, but exactly what I need for the Request too. It even told me I’d get back a dataset, which I kind-of already figured since everything is a dataset in the PSI.

HTTP/1.1 200 OK

Content-Type: text/xml; charset=utf-8

Content-Length: length

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

  <soap:Body>

    <ReadProjectListResponse xmlns="https://schemas.microsoft.com/office/project/server/webservices/Project/">

      <ReadProjectListResult>dataset</ReadProjectListResult>

    </ReadProjectListResponse>

  </soap:Body>

</soap:Envelope>

OK we have a way to call the Project web service, using XMLHTTP. We have the parameters to pass in courtesy of .Net Add Web Reference dialog. I pull it together, make a call to get my list of projects and realize… what do I do with a dataset when I’m not in .Net? In my previous example I made EXTENSIVE use of binding datasets to UI elements, that’s not going to fly here. Wait, the serialized version of a dataset is just XML. I’m already hammering XML via XMLHTTP, how about a little DOM action? Off we go to load the DOM with the dataset that got returned. I start “spelunking” the DOM in search of my data, where the &^($^! is my data. I finally push the XML out to a file, then reload it in a DOM in .Net. Then I debug the DOM and find the data six levels deep, WOW! So to get the project list I end up with the following:

 projects = xmlObj.childNodes(0).childNodes(0).childNodes(0).childNodes(1).childNodes(0).childNodes;

Once I find that it’s a matter of jamming this into some UI elements. Then I want to display the details of the project, so I retrace my steps for ReadProject. Once you get though the questions of how to talk to the web service and how to consume the data coming back it’s pretty straight forward.

A big word of WARNING!!! I did this sample on beta 2… it crashed and burned on beta 2 technical refresh. It took me a couple weeks off and on to figure out the problem… the namespaces had been completely changed. Even though the calls hadn’t really changed, the namespace change crashed the sample around my ears. And we all know how fun it is to debug JavaScript (alert(sRequest); … ) ALL the information in the SOAP headers is very important, not just the signature of the method call.

Attached is the complete sample for your enjoyment. Don’t forget to change yourserver/pwa to reflect your instance.

 

ProjectDetailsHTML.zip