Geeks With Blogs
Molnar Tibor blog

I am involved, between others, in a PS 2003 -> PS 2007 migration project. We are close to the end, however, we had a request from the end users to have on the 'My tasks' page a web part having the folowing features:

  • displays in a grid for a selectable month and year all the tasks assigned to the current user were the user reported work effort
  • tasks are grouped by projects
  • for every task and every day of the selected month the reported work is displayed with different color depending on the status of the reported data: saved, submitted for approval, approved

The big challenge was the last requirement above, to find out the status of the task timephased data (data reorted per day); I will peresent to you the steps I took to solve that problem.

1. The programmability of PS 2007 goes through the PSI web services. The classes from the SDK should be touched only if you create Project Server extensions. The first step was to use the ReadResourceAssignments method of the Resource PSI web service to obtain the assignment for the current user.

2. Iterate though all the assignments and get the timephased data for every of them for each day of the current month using the ReadStatusTimephasedData method of the Statusing PSI web service, then feed a DataTable which will be the datasource of a Asp.Net data grid with the timpehased data. For every of the assignments call the ReadAssignmentHistory method of the Statusing PSI web service.

3. And here is the hard part: I tried to iterate through the transactions of the assignment history for the assignments obtained in teh iteration above and call the ReadTransactionDetails method of the Statusing PSI web service, in order to try find out the status of the timephased data for every day. The problem is that for the majority of the history entries (transactions), this web service method call fails with a general unhandled exception. I figured out, that for those transations represented by AssnHistoryDataSet.HistoryRow instances the TASK_CHANGE_DATA attributes is null. This might be or not the reason for the failure.

I started to crawl through the code of Project Server assemblies using reflection, and I figured out that an AssnHistoryDataSet.HistoryRow instance represents all the timephased data submitted using the Save button from the MyTasks page from the project web access and the ASSN_CHANGE_DATA attribute contains all the timephased changes which came with that save. The changes are in the form of binary serialisation of the Microsoft.Office.Project.SvrDataEdit.ChangeLog internal class which contains a list of the Microsoft.Office.Project.SvrDataEdit.Change internal class instances, which contains in the Value attribute a Microsoft.Office.Project.SvrDataEdit.PeriodData internal class instance which in turn has the Start, End and Value attributes. Additionally, the ASSN_TRANS_ACTION_ENUM of the history object means 'Submitted' if 0, 'Approved' if 1 and 'Rejected' if 2. If ASSN_TRANS_ACTION_ENUM is 0, then the ASSN_CHANGE_DATA contains all the unapproved submitted data on the date of creation of the history entry, in PeriodData instances. If 1, then contains all the approved data in the momentof creation of the history entry.

To make it more complicated, if a user saves multiple changes on My Tasks page using the Save button and then submits them for approval, all those changes are logged as Microsoft.Office.Project.SvrDataEdit.PeriodData instances for every changed day.

See below the code to deserialise the change log for a transaction and save it in a custom list containing custom HistoryEntry classes.

Object obj = fomBytesMethod.Invoke(null, new object[] { new ByteArray(byteData) });
int count = (int)changeLogType.InvokeMember("Count", BindingFlags.Default | BindingFlags.GetProperty, null, obj, null);
List<HistoryEntry> assignmentTimephasedData = new List<HistoryEntry>();


for (int idx = 0; idx < count; idx++)
{
  object change = changeLogType.InvokeMember("Item", BindingFlags.Default |   BindingFlags.GetProperty, null, obj, new object[] { idx });
  object changeValue = changeType.InvokeMember("Value", BindingFlags.Default | BindingFlags.GetProperty, null, change, null);
  DateTime startDate = (DateTime)periodDataType.InvokeMember("Start", BindingFlags.Default |   BindingFlags.GetProperty, null, changeValue, null);
  DateTime endDate = (DateTime)periodDataType.InvokeMember("End", BindingFlags.Default | BindingFlags.GetProperty, null, changeValue, null);
  double changeValueValue = (double)periodDataType.InvokeMember("Value", BindingFlags.Default |  BindingFlags.GetProperty, null, changeValue, null);


  HistoryEntry historyEntry = new HistoryEntry(startDate, endDate, changeValueValue);
  assignmentTimephasedData.Add(historyEntry);
}

In order to obtain the status of a reported timpehased data for an assignment (for example, I have 4 hours reported actual work for 8th of Feb for the 'Create Users Page' assignment) we have to iterate through all transactions (history) for that assignment, in chronological order, get the latest PeriodData data instance for that day, and depending on the ASSN_TRANS_ACTION_ENUM value we can say that we have an 'Approved' or 'Submitted' status. If there is no value for that day in the transaction history or the latest value obtained from the transaction history is different then the one obtained from the timephased data returned via the ReadStatusTimephasedData web method, then the status of the timephased data is 'Saved'. All the logic doing this kinda staff in the Project Server assemblies are obfuscated, it was challenging to sort all these things out. Hope this helps!

Posted on Thursday, February 7, 2008 5:11 AM SharePoint 2007 | Back to top


Comments on this post: Project Server 2007 assignment timephased data internals

# re: Project Server 2007 assignment timephased data internals
Requesting Gravatar...
Thank you! This is exactly what i am trying to achieve for our client!!

But in which assembly is the Microsoft.Office.Project.SvrDataEdit.ChangeLog class??? I had a look in the one that came with the SDK and it is not in there. Please help!! :(
Left by Bernado on Feb 11, 2008 6:19 PM

# re: Project Server 2007 assignment timephased data internals
Requesting Gravatar...
I think the code below will clarify:
- attributes declaration:
// PS 2007 deep dive reflection
private Type changeLogType;
private Type taskDataType;
private Type changeType;
private Type periodDataType;
private MethodInfo fomBytesMethod;
- code in constructor:

AssemblyName assemblyName = new AssemblyName("Microsoft.Office.Project.Server, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c");
Assembly assembly = Assembly.Load(assemblyName);
changeLogType = assembly.GetType("Microsoft.Office.Project.SvrDataEdit.ChangeLog");
changeType = assembly.GetType("Microsoft.Office.Project.SvrDataEdit.Change");
periodDataType = assembly.GetType("Microsoft.Office.Project.SvrDataEdit.PeriodData");
taskDataType = assembly.GetType("Microsoft.Office.Project.SvrDataEdit.TaskData");
assigmentUpdateTypes = new Dictionary<string, AssignmentUpdateType>();
fomBytesMethod = changeLogType.GetMethod("FromBytes");
Left by Tibi on Feb 11, 2008 9:21 PM

# re: Project Server 2007 assignment timephased data internals
Requesting Gravatar...
Got it! Thank you!

I'd like to add that the ByteArray class (the one you will need to call the FromBytes method) is in the Microsoft.Office.Project.Shared.dll file.

Cheers,
Bernado
Left by Bernado on Feb 14, 2008 12:04 PM

# re: Project Server 2007 assignment timephased data internals
Requesting Gravatar...
Guys, i'm sooooo much grateful for your posts. You made my current development much more easier... again, thx MUCH!!!

Dave
Left by Dave Kotyza on Aug 20, 2008 2:37 AM

# re: Project Server 2007 assignment timephased data internals
Requesting Gravatar...
Thanks!!!
Left by Pavel on Mar 17, 2009 12:52 AM

# re: Project Server 2007 assignment timephased data internals
Requesting Gravatar...
How can I obtain it?
Left by Igor on May 31, 2009 11:19 PM

# re: Project Server 2007 assignment timephased data internals
Requesting Gravatar...
Great stuff. Could you please share your webpart/control?
Left by Allen on Oct 13, 2009 1:14 AM

# re: Project Server 2007 assignment timephased data internals
Requesting Gravatar...
Hi Molnar,
Greate post.. i too had a similar requirement to display time phased data entered by resource in a custom web part where i am using Statusing web service's ReadStatusTimePhasedData method which i guess you are also working but i have noticed that for about 400-500 tasks if we make separate calls to this web methods then performance drops to a great unacceptable extent. It took almost 12 seconds to get those timephased data using this web method. Any idea ?
Left by Nikhil on Apr 20, 2010 11:56 PM

# re: Project Server 2007 assignment timephased data internals
Requesting Gravatar...
Would love to get the web part and code... some things we are doing here could use this as a start
Left by George Haney on Jul 08, 2010 2:34 PM

# re: Project Server 2007 assignment timephased data internals
Requesting Gravatar...
Can you post a complete code solution? I'm having trouble figuring out how to deserialize the transaction data.
Left by Greg on May 09, 2011 9:14 PM

# re: Project Server 2007 assignment timephased data internals
Requesting Gravatar...
Thank you so much!
We were seeking for this ability for a long long time...
Left by Izik on Feb 27, 2013 6:17 AM

# re: Project Server 2007 assignment timephased data internals
Requesting Gravatar...
This is really great information. I hope someone is still monitoring this because I am receiving a Stack overflow error when I make the call to the FromBytes method. I think it is due to format of my "bytedata". Is the bytedata the data from the ASSN_Change_Object?
Left by Sharon B on Apr 04, 2013 3:24 PM

# re: Project Server 2007 assignment timephased data internals
Requesting Gravatar...
Thanks for your great informations.. Can you please tell me how to interpret the submitted assignment effort for a week?
Left by karthick on Apr 29, 2013 5:11 AM

Your comment:
 (will show your gravatar)


Copyright © Molnar Tibor | Powered by: GeeksWithBlogs.net