ResourcePlan.ReadResourcePlan Method

Reads resource plan data for the specified project by using an optional filter or date range. Optionally, checks out the resource plan for modification.

Namespace:  [ResourcePlan Web service]
Service reference: http://ServerName:32843/[Project Service Application GUID]/PSI/ResourcePlan.svc
Web service reference: http://ServerName/ProjectServerName/_vti_bin/PSI/ResourcePlan.asmx?wsdl

Syntax

'Declaration
<SoapDocumentMethodAttribute("https://schemas.microsoft.com/office/project/server/webservices/ResourcePlan/ReadResourcePlan", RequestNamespace := "https://schemas.microsoft.com/office/project/server/webservices/ResourcePlan/",  _
    ResponseNamespace := "https://schemas.microsoft.com/office/project/server/webservices/ResourcePlan/",  _
    Use := SoapBindingUse.Literal, ParameterStyle := SoapParameterStyle.Wrapped)> _
Public Function ReadResourcePlan ( _
    filter As String, _
    projectUid As Guid, _
    startDate As DateTime, _
    endDate As DateTime, _
    timeScale As Short, _
    timephasedFTE As Boolean, _
    autoCheckOut As Boolean _
) As ResourcePlanDataSet
'Usage
Dim instance As ResourcePlan
Dim filter As String
Dim projectUid As Guid
Dim startDate As DateTime
Dim endDate As DateTime
Dim timeScale As Short
Dim timephasedFTE As Boolean
Dim autoCheckOut As Boolean
Dim returnValue As ResourcePlanDataSet

returnValue = instance.ReadResourcePlan(filter, _
    projectUid, startDate, endDate, timeScale, _
    timephasedFTE, autoCheckOut)
[SoapDocumentMethodAttribute("https://schemas.microsoft.com/office/project/server/webservices/ResourcePlan/ReadResourcePlan", RequestNamespace = "https://schemas.microsoft.com/office/project/server/webservices/ResourcePlan/", 
    ResponseNamespace = "https://schemas.microsoft.com/office/project/server/webservices/ResourcePlan/", 
    Use = SoapBindingUse.Literal, ParameterStyle = SoapParameterStyle.Wrapped)]
public ResourcePlanDataSet ReadResourcePlan(
    string filter,
    Guid projectUid,
    DateTime startDate,
    DateTime endDate,
    short timeScale,
    bool timephasedFTE,
    bool autoCheckOut
)

Parameters

  • filter
    Type: System.String
    Contains the XML filter to limit the data that is returned.
  • projectUid
    Type: System.Guid
    Contains the project GUID.
  • timephasedFTE
    Type: System.Boolean
    If true, converts the time values to a full-time equivalent resource.
  • autoCheckOut
    Type: System.Boolean
    If true, checks out the resource plan for editing.

Return Value

Type: [ResourcePlan Web service].ResourcePlanDataSet
The ResourcePlanDataSet.PlanResourcesDataTable includes the data that is specified by the filter or date parameters.

Remarks

The primary DataTable in a ResoucePlanDataSet is the PlanResourcesDataTable.

Note

The filter parameter works with the Criteria operators to filter rows only in the primary PlanResourcesDataTable. For example, you cannot use filter with the ReadResourcePlan method to filter rows in the PlanAssignmentCustomFieldsDataTable. If you try to filter rows in a secondary DataTable, the PSI returns a FilterInvalid exception.

However, you can use the Fields.Add method to filter columns in the primary CalendarsDataTable and in any secondary DataTable.

Examples

The example uses the SvcResourcePlan namespace in the ProjectServerServices.dll proxy assembly. The ConfigClientEndpoints method uses an app.config file to set the WCF binding, behavior, and endpoint for the resourcePlanClient object, the resourceClient object, and the projectClient object. For information about creating and using a PSI proxy assembly and an app.config file, see Prerequisites for WCF-Based Code Samples.

Note

The following example demonstrates the use of the ReadResourcePlan method; it is not a full solution.

For sample code about how to create a resource plan, see QueueCreateResourcePlan.To use the ReadResourcePlan sample, create a project, build the project team from the enterprise resources, and then create and publish a resource plan by using Project Web App.

After the resource plan is created and the project is published, compile and run the sample. For example, the following command reads the resource plan for a project named My Swell Project, and then writes the ResourcePlanDataSet contents to the C:\Project\Samples\Output\ReadResourcePlanDS.xml file.

ReadResourcePlan -project "My Swell Project"

The sample code is as follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.ServiceModel;
using System.Data;
using System.Xml;
using PSLibrary = Microsoft.Office.Project.Server.Library;

namespace Microsoft.SDK.Project.Samples.ReadResourcePlan
{
    class ReadResourcePlan
    {

        private const string ENDPOINT_RESPLAN = "basicHttp_ResourcePlan";
        private const string ENDPOINT_R = "basicHttp_Resource";
        private const string ENDPOINT_P = "basicHttp_Project";
        private const string OUTPUT_FILES = @"C:\Project\Samples\Output\";
        private const string XML_FILE = "ReadResourcePlanDS.xml";

        private static SvcResourcePlan.ResourcePlanClient resourcePlanClient;
        private static SvcResource.ResourceClient resourceClient;
        private static SvcProject.ProjectClient projectClient;
        private static string outFile_ResourcePlanDS;

        static void Main(string[] args)
        {
            string projName = string.Empty;
            bool badNews = false;

            try
            {
                if (args.Length == 2)
                {
                    if (args[0].ToLower() == "-project")
                        projName = args[1];
                    else
                    {
                        Console.WriteLine("Incorrect argument: {0}", args[0]);
                        badNews = true;
                    }
                }
                else
                {
                    badNews = true;
                }

                if (badNews) throw new ApplicationException(
                    @"Usage: ReadResourcePlan -project ""Project Name""");

                // Configure the endpoints.
                bool configResult = false;
                configResult = ConfigClientEndpoints(ENDPOINT_RESPLAN);
                configResult = ConfigClientEndpoints(ENDPOINT_P);
                configResult = ConfigClientEndpoints(ENDPOINT_R);

                if (!configResult) throw new ApplicationException(
                    "Error(s) in WCF client configuration");

                // If output directory does not exist, create it.
                if (!Directory.Exists(OUTPUT_FILES))
                {
                    Directory.CreateDirectory(OUTPUT_FILES);
                }

                // Set the output file path.
                outFile_ResourcePlanDS = OUTPUT_FILES + XML_FILE;

                try
                {
                    GetResourcePlan(projName);
                }
                catch (FaultException fault)
                {
                    // Use the WCF FaultException, because the ASMX SoapException does not 
                    // exist in a WCF-based application.
                    WriteFaultOutput(fault);
                }
                catch (CommunicationException e)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine(
                        "\n***System.ServiceModel.CommunicationException\n{0}:", e.Message);
                    Console.ResetColor();
                }
            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("\n\n***Exception:\n{0}", ex.Message);
                Console.ResetColor();
            }
            Console.Write("\nPress any key to exit: ");
            Console.ReadKey(true);
        }

        // Extract a PSClientError object from the WCF FaultException object, and
        // then display the exception details and each error in the PSClientError stack.
        private static void WriteFaultOutput(FaultException fault)
        {
            string errAttributeName;
            string errAttribute;
            string errOut;
            string errMess = "".PadRight(30, '=') + "\r\n"
                + "Error details: " + "\r\n";

            PSLibrary.PSClientError error = Helpers.GetPSClientError(fault, out errOut);
            errMess += errOut;

            if (error != null)
            {
                PSLibrary.PSErrorInfo[] errors = error.GetAllErrors();
                PSLibrary.PSErrorInfo thisError;

                for (int i = 0; i < errors.Length; i++)
                {
                    thisError = errors[i];
                    errMess += "\r\n".PadRight(30, '=') + "\r\nPSClientError output:\r\n";
                    errMess += thisError.ErrId.ToString() + "\n";

                    for (int j = 0; j < thisError.ErrorAttributes.Length; j++)
                    {
                        errAttributeName = thisError.ErrorAttributeNames()[j];
                        errAttribute = thisError.ErrorAttributes[j];
                        errMess += "\r\n\t" + errAttributeName
                            + ": " + errAttribute;
                    }
                }
            }
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(errMess);
            Console.ResetColor();
        }

        // Get the resource plan for the specified project.
        public static void GetResourcePlan(string projName)
        {
            Guid projUid = GetProjectUid(projName);

            // Get project start date and end date.
            List<DateTime> startFinishDates = GetStartFinishDates(projUid);
            if (startFinishDates.Count != 2) 
                throw new ApplicationException("Invalid project start and finish dates.");

            DateTime startDate = startFinishDates[0];
            DateTime endDate = startFinishDates[1];

            // Read the resource plan.
            Console.WriteLine("Reading the resource plan of the project: \n\t{0}\n\t{1}",
                projName, projUid.ToString());

            string resPlanFilter = string.Empty;
            bool fteTime = false;
            bool autoCheckOut = false;

            SvcResourcePlan.ResourcePlanDataSet resPlanDs = resourcePlanClient.ReadResourcePlan(
                resPlanFilter, projUid, startDate, endDate,
                (short)PSLibrary.ResourcePlan.TimeScale.Days, fteTime, autoCheckOut);

            // Write the ResourcePlan DataSet to an XML file.
            resPlanDs.WriteXml(outFile_ResourcePlanDS);
            Console.WriteLine("\nSee XML output of resource plan DataSet at {0}",
                outFile_ResourcePlanDS);
        }
   
        // Get the project GUID.
        public static Guid GetProjectUid(string projName)
        {
            Guid projUid = Guid.Empty;

            SvcProject.ProjectDataSet projectDs = projectClient.ReadProjectStatus(
                Guid.Empty, SvcProject.DataStoreEnum.PublishedStore, 
                projName, (int)PSLibrary.Project.ProjectType.Project);

            foreach (SvcProject.ProjectDataSet.ProjectRow project in projectDs.Project)
            {
                if (project.PROJ_NAME == projName)
                {
                    projUid = project.PROJ_UID;
                    break;
                }
            }
            if (projUid == Guid.Empty)
                throw new ApplicationException(string.Format("No project name: {0}", projName));

            return projUid;
        }

        // Get the project start date and finish date.
        public static List<DateTime> GetStartFinishDates(Guid projUid)
        {
            List<DateTime> dates = new List<DateTime>();

            SvcProject.ProjectDataSet projectDs = projectClient.ReadProject(
                projUid, SvcProject.DataStoreEnum.PublishedStore);

            dates.Add(projectDs.Project.Rows[0].Field<DateTime>("PROJ_INFO_START_DATE"));
            dates.Add(projectDs.Project.Rows[0].Field<DateTime>("PROJ_INFO_FINISH_DATE"));
            return dates;
        }

        // Configure the PSI client endpoints.
        public static bool ConfigClientEndpoints(string endpt)
        {
            bool result = true;

            switch (endpt)
            {
                case ENDPOINT_RESPLAN:
                    resourcePlanClient = new SvcResourcePlan.ResourcePlanClient(endpt);
                    break;
                case ENDPOINT_P:
                    projectClient = new SvcProject.ProjectClient(endpt);
                    break;
                case ENDPOINT_R:
                    resourceClient = new SvcResource.ResourceClient(endpt);
                    break;
                default:
                    result = false;
                    Console.WriteLine("Invalid endpoint: {0}", endpt);
                    break;
            }
            return result;
        }        
    }
    class Helpers
    {
        /// <summary>
        /// Extract a PSClientError object from the ServiceModel.FaultException,
        /// for use in output of the GetPSClientError stack of errors.
        /// </summary>
        /// <param name="e"></param>
        /// <param name="errOut">Shows that FaultException has more information 
        /// about the errors than PSClientError has. FaultException can also contain 
        /// other types of errors, such as failure to connect to the server.</param>
        /// <returns>PSClientError object, for enumerating errors.</returns>
        public static PSLibrary.PSClientError GetPSClientError(FaultException e,
                                                               out string errOut)
        {
            const string PREFIX = "GetPSClientError() returns null: ";
            errOut = string.Empty;
            PSLibrary.PSClientError psClientError = null;

            if (e == null)
            {
                errOut = PREFIX + "Null parameter (FaultException e) passed in.";
                psClientError = null;
            }
            else
            {
                // Get a ServiceModel.MessageFault object.
                var messageFault = e.CreateMessageFault();

                if (messageFault.HasDetail)
                {
                    using (var xmlReader = messageFault.GetReaderAtDetailContents())
                    {
                        var xml = new XmlDocument();
                        xml.Load(xmlReader);

                        var serverExecutionFault = xml["ServerExecutionFault"];
                        if (serverExecutionFault != null)
                        {
                            var exceptionDetails = serverExecutionFault["ExceptionDetails"];
                            if (exceptionDetails != null)
                            {
                                try
                                {
                                    errOut = exceptionDetails.InnerXml + "\r\n";
                                    psClientError =
                                        new PSLibrary.PSClientError(exceptionDetails.InnerXml);
                                }
                                catch (InvalidOperationException ex)
                                {
                                    errOut = PREFIX + "Unable to convert fault exception info ";
                                    errOut += "a valid Project Server error message. Message: \n\t";
                                    errOut += ex.Message;
                                    psClientError = null;
                                }
                            }
                            else
                            {
                                errOut = PREFIX + "The FaultException e is a ServerExecutionFault, "
                                    + "but does not have ExceptionDetails.";
                            }
                        }
                        else
                        {
                            errOut = PREFIX + "The FaultException e is not a ServerExecutionFault.";
                        }
                    }
                }
                else // No detail in the MessageFault.
                {
                    errOut = PREFIX + "The FaultException e does not have any detail.";
                }
            }
            errOut += "\r\n" + e.ToString() + "\r\n";
            return psClientError;
        }
    }
}

For a project that extends over two weeks, using the ReadResourcePlan method with the timescale in weeks shows two intervals named Interval0 and Interval1 in the resource plan. In this example, the resource plan intervals contain 0 hours of time. Following is an example of output in the ReadResourcePlanDS.xml file.

<?xml version="1.0" standalone="yes"?>
<ResourcePlanDataSet xmlns="https://schemas.microsoft.com/office/project/server/webservices/ResourcePlanDataSet/">
  <Utilization>
    <PROJ_UID>4f4b5ffb-e143-4c84-9cf4-299d316c7d8e</PROJ_UID>
    <RESPLAN_UTILIZATION_TYPE>0</RESPLAN_UTILIZATION_TYPE>
  </Utilization>
  <PlanResources>
    <RES_UID>0285a4e6-53f8-459a-945a-62f7ca465400</RES_UID>
    <PROJ_UID>4f4b5ffb-e143-4c84-9cf4-299d316c7d8e</PROJ_UID>
    <ASSN_UID>cc3f29ec-d033-473e-a6c4-5604c2e84601</ASSN_UID>
    <RES_NAME>Resource Name1</RES_NAME>
    <RES_TYPE>2</RES_TYPE>
    <RES_CAN_LEVEL>true</RES_CAN_LEVEL>
    <RES_TIMESHEET_MGR_UID>0285a4e6-53f8-459a-945a-62f7ca465400</RES_TIMESHEET_MGR_UID>
    <RES_DEF_ASSN_OWNER>0285a4e6-53f8-459a-945a-62f7ca465400</RES_DEF_ASSN_OWNER>
    <RES_INITIALS>R1</RES_INITIALS>
    <RES_ID>71</RES_ID>
    <ASSN_BOOKING_TYPE>0</ASSN_BOOKING_TYPE>
    <RES_IS_TEAM>false</RES_IS_TEAM>
    <RES_CHECKOUTDATE>2010-10-06T16:08:23.17-07:00</RES_CHECKOUTDATE>
    <Interval0>0</Interval0>
    <Interval1>0</Interval1>
  </PlanResources>
  <PlanResources>
    <RES_UID>009380d1-29ad-40df-9511-f82adb874834</RES_UID>
    <PROJ_UID>4f4b5ffb-e143-4c84-9cf4-299d316c7d8e</PROJ_UID>
    <ASSN_UID>ad15c911-ac55-4463-9d1c-cf29d9b6938a</ASSN_UID>
    <RES_NAME>Resource Name2</RES_NAME>
    <RES_TYPE>2</RES_TYPE>
    <RES_CAN_LEVEL>true</RES_CAN_LEVEL>
    <RES_TIMESHEET_MGR_UID>009380d1-29ad-40df-9511-f82adb874834</RES_TIMESHEET_MGR_UID>
    <RES_DEF_ASSN_OWNER>009380d1-29ad-40df-9511-f82adb874834</RES_DEF_ASSN_OWNER>
    <RES_INITIALS>R2</RES_INITIALS>
    <RES_ID>24</RES_ID>
    <ASSN_BOOKING_TYPE>0</ASSN_BOOKING_TYPE>
    <RES_HIRE_DATE>2010-09-21T00:00:00-07:00</RES_HIRE_DATE>
    <RES_TERMINATION_DATE>2011-09-25T00:00:00-07:00</RES_TERMINATION_DATE>
    <RES_IS_TEAM>false</RES_IS_TEAM>
    <RES_CHECKOUTDATE>2010-10-06T15:43:12.73-07:00</RES_CHECKOUTDATE>
    <Interval0>0</Interval0>
    <Interval1>0</Interval1>
  </PlanResources>
  <Dates>
    <StartDate>2010-10-27T00:00:00-07:00</StartDate>
    <EndDate>2010-11-01T00:00:00-07:00</EndDate>
    <IntervalName>Interval0</IntervalName>
  </Dates>
  <Dates>
    <StartDate>2010-11-01T00:00:00-07:00</StartDate>
    <EndDate>2010-11-05T00:00:00-07:00</EndDate>
    <IntervalName>Interval1</IntervalName>
  </Dates>
</ResourcePlanDataSet>

See Also

Reference

ResourcePlan Class

ResourcePlan Members

ResourcePlan Web Service

Other Resources

How to: Use a Filter Parameter with PSI Methods