none
PSI Queue Create Project Error - CustomFieldRequiredValueNotProvided

    Question

  • I am using C# and PSI to create a Project Server file and to add tasks to the file. I am using the sample code from MSDN (http://msdn.microsoft.com/en-us/library/websvcproject.project.queueaddtoproject.aspx).

    When inserting a TaskRow on a ProjectDataSet, I get an exception when calling the QueueCreateProject. What am I missing?

    Line of Code Causing Exception: 

    projectSvc.QueueCreateProject(jobId, projectDs, false);

    Exception:

    System.Web.Services.Protocols.SoapException: ProjectServerError(s) LastError=CustomFieldRequiredValueNotProvided Instructions: Pass this into PSClientError constructor to access all error information
       at Microsoft.Office.Project.Server.WebService.Project.QueueCreateProject(Guid jobUid, ProjectDataSet dataset, Boolean validateOnly)

    • Moved by Alexander Burton [MVP]MVP, Moderator Friday, August 20, 2010 8:52 PM Programming Question - Moving to Programming forum (From:Project Server General Questions and Answers)
    Friday, August 20, 2010 6:08 PM

Answers

  • Here it is chocochip,

    I have built this around the SDK LoginDemo sample, and just added to the btnCreateProject_Click method.  The sample just creates a project - see http://msdn.microsoft.com/en-us/library/ms455600(office.12).aspx.  I have added a task, and both Project and Task level custom fields.  Across the project and task levels I have used each type of custom field to show which values need setting.  This is just to create a project - obviously adding or changing them later is very similar.  Sorry the formatting isn't better.

    For simplicity (and laziness) I have hard coded many of the GUIDs I am using.  For the Custom Fields I copied these from the URLs when in the edit screen for custom fields.  I got the lookup table value GUID in the 'View Source' page when editing the lookup table.  Obviously you could also get these from the database.  In a real situation you would use the Custom Field and Lookup Table web services.  Obviously your GUIDs will be different from mine.

    private void btnCreateProject_Click(object sender, EventArgs e)
        {
          string projectCreatedLabel = "Project created!";
          string wssUrl;
          string projectWorkspace = ResetWorkspaceUrl();
          bool created = false;
    
          // GUIDs for my CFs etc - in practice you would use the CF and LU PSI calls
          Guid projCostGuid = new Guid("e672bd64-c535-4486-bc64-8f4999547390");
          Guid projDateGuid = new Guid("3dafa5d4-9473-4781-9503-aafe207a71bb");
          Guid projTextGuid = new Guid("08758857-1a69-4efb-a657-27ed61d7d7c3");
          Guid taskTextGuid = new Guid("30665299-bc21-4c51-b954-220d407ba47e");
          Guid taskFlagGuid = new Guid("3658a81d-2e64-436f-afb9-970b778954b1");
          Guid taskNumberGuid = new Guid("d5c0318c-06cc-4d82-a891-7f3ea43503ab");
          Guid taskDurationGuid = new Guid("58519124-7e1d-44b8-b14c-7435408f02e7");
          Guid colourLUValueRed = new Guid("5b730bab-7212-4ffb-823d-60aef0df1fff");
    
          lblProjectCreated.Text = "";
          lblWorkspaceUrl.Text = projectWorkspace;
          this.Cursor = Cursors.WaitCursor;
    
          try
          {
            WebSvcProject.ProjectDataSet dsProject = 
              new WebSvcProject.ProjectDataSet();
            WebSvcProject.ProjectDataSet.ProjectRow projectRow = 
              dsProject.Project.NewProjectRow();
    
            Guid projectGuid = Guid.NewGuid();
            projectRow.PROJ_UID = projectGuid;
            projectRow.PROJ_NAME = this.txtProjectName.Text;
            projectRow.PROJ_TYPE = 
              Convert.ToInt32(PSLibrary.Project.ProjectType.Project);
    
            dsProject.Project.AddProjectRow(projectRow);
    
            //Adding a row for my first Project CF - ProjCost
    
            WebSvcProject.ProjectDataSet.ProjectCustomFieldsRow cfRowCost = 
              dsProject.ProjectCustomFields.NewProjectCustomFieldsRow();
    
            cfRowCost.PROJ_UID = projectGuid;
            // The Custom_Field_UID is the unique identifier for each custom field row
            cfRowCost.CUSTOM_FIELD_UID = Guid.NewGuid();
            // The MD_PROP_UID identifies the specific custom field
            cfRowCost.MD_PROP_UID = projCostGuid;
            // Cost custom fields have their value set in NUM_VALUE
            // The value entered is decimal and 100 times the actual cost - 5000 = $50 in my case
            cfRowCost.NUM_VALUE = 5000;
    
            //Adding a row for my second Project CF - ProjDate
    
            WebSvcProject.ProjectDataSet.ProjectCustomFieldsRow cfRowDate =
              dsProject.ProjectCustomFields.NewProjectCustomFieldsRow();
    
            cfRowDate.PROJ_UID = projectGuid;
            cfRowDate.CUSTOM_FIELD_UID = Guid.NewGuid();
            cfRowDate.MD_PROP_UID = projDateGuid;
            // Date custom fields have their values set in DATE_VALUE as a DateTime data type
            cfRowDate.DATE_VALUE = DateTime.Parse("Aug 25, 2010 10:45:00 PM");
    
            //Adding a row for my third Project CF - ProjText, which is based on a Lookup Table
    
            WebSvcProject.ProjectDataSet.ProjectCustomFieldsRow cfRowText =
              dsProject.ProjectCustomFields.NewProjectCustomFieldsRow();
    
            cfRowText.PROJ_UID = projectGuid;
            cfRowText.CUSTOM_FIELD_UID = Guid.NewGuid();
            cfRowText.MD_PROP_UID = projTextGuid;
            // Custom fields based on a lookup table have the GUID that identifies the row in
            // the lookup table entered against CODE_VALUE. See the LT_STRUCT_UID from the 
            // LookupTable web service
            cfRowText.CODE_VALUE = colourLUValueRed;
    
            //Adding my CFRows to the dataset
    
            dsProject.ProjectCustomFields.AddProjectCustomFieldsRow(cfRowCost);
            dsProject.ProjectCustomFields.AddProjectCustomFieldsRow(cfRowDate);
            dsProject.ProjectCustomFields.AddProjectCustomFieldsRow(cfRowText);
    
            //Now for the Task custom fields. First I will add a Task
    
            WebSvcProject.ProjectDataSet.TaskRow taskRow =
              dsProject.Task.NewTaskRow();
    
            Guid taskGuid = Guid.NewGuid();
    
            taskRow.PROJ_UID = projectGuid;
            taskRow.TASK_UID = taskGuid;
            taskRow.TASK_NAME = "My Task";
    
            dsProject.Task.AddTaskRow(taskRow);
    
            // And add some custom fields to my task
    
            // First a text field not based on a lookup table
            WebSvcProject.ProjectDataSet.TaskCustomFieldsRow cfRowTaskText =
              dsProject.TaskCustomFields.NewTaskCustomFieldsRow();
    
            cfRowTaskText.PROJ_UID = projectGuid;
            // For our Task CF rows we need the Task UID as well as the Project UID
            cfRowTaskText.TASK_UID = taskGuid;
            cfRowTaskText.CUSTOM_FIELD_UID = Guid.NewGuid();
            cfRowTaskText.MD_PROP_UID = taskTextGuid;
            // As we have no lookup table for this text field the value goes in TEXT_VALUE
            cfRowTaskText.TEXT_VALUE = "My Text Value";
    
            // Next a Flag field
            WebSvcProject.ProjectDataSet.TaskCustomFieldsRow cfRowTaskFlag =
              dsProject.TaskCustomFields.NewTaskCustomFieldsRow();
    
            cfRowTaskFlag.PROJ_UID = projectGuid;
            cfRowTaskFlag.TASK_UID = taskGuid;
            cfRowTaskFlag.CUSTOM_FIELD_UID = Guid.NewGuid();
            cfRowTaskFlag.MD_PROP_UID = taskFlagGuid;
            // Flags are a bool, so expect true or false - they default to false
            // Also Flags cannot be made required, as they will always have a value anyway
            // They are entered against FLAG_VALUE
            cfRowTaskFlag.FLAG_VALUE = true;
    
            // Next a Number field
            WebSvcProject.ProjectDataSet.TaskCustomFieldsRow cfRowTaskNumber =
              dsProject.TaskCustomFields.NewTaskCustomFieldsRow();
    
            cfRowTaskNumber.PROJ_UID = projectGuid;
            cfRowTaskNumber.TASK_UID = taskGuid;
            cfRowTaskNumber.CUSTOM_FIELD_UID = Guid.NewGuid();
            cfRowTaskNumber.MD_PROP_UID = taskNumberGuid;
            // Numbers are decimal - the M suffix is used as this value would normally default to double
            // They are entered against NUM_VALUE
            cfRowTaskNumber.NUM_VALUE = 25.6M;
    
            // Finally a duration field
            WebSvcProject.ProjectDataSet.TaskCustomFieldsRow cfRowTaskDuration =
              dsProject.TaskCustomFields.NewTaskCustomFieldsRow();
    
            cfRowTaskDuration.PROJ_UID = projectGuid;
            cfRowTaskDuration.TASK_UID = taskGuid;
            cfRowTaskDuration.CUSTOM_FIELD_UID = Guid.NewGuid();
            cfRowTaskDuration.MD_PROP_UID = taskDurationGuid;
            // Durations have a format for their display which is best enumerated as below
            // They are entered against NUM_VALUE
            cfRowTaskDuration.DUR_FMT = (int)PSLibrary.Task.DurationFormat.Day; 
            // Duration is indicated in tenths of minutes. A value of 100 indicates 10 minutes
            cfRowTaskDuration.DUR_VALUE = 24000;
    
            // Add my custom field rows to the dataset
    
            dsProject.TaskCustomFields.AddTaskCustomFieldsRow(cfRowTaskText);
            dsProject.TaskCustomFields.AddTaskCustomFieldsRow(cfRowTaskFlag);
            dsProject.TaskCustomFields.AddTaskCustomFieldsRow(cfRowTaskNumber);
            dsProject.TaskCustomFields.AddTaskCustomFieldsRow(cfRowTaskDuration);
    
            
    
            Guid jobGuid = Guid.NewGuid();
            bool validateOnly = false;
            // Create and save project to the Draft db
            project.QueueCreateProject(jobGuid, dsProject, validateOnly);
    
            // Wait 3 seconds (more or less) for Queue job to complete.
            // Or, add a routine that checks the QueueSystem for job completion.
            System.Threading.Thread.Sleep(3000);
    
            WebSvcProject.ProjectRelationsDataSet dsProjectRelations =
              new WebSvcProject.ProjectRelationsDataSet();
            jobGuid = Guid.NewGuid();
    
            // Set wssUrl = "" to have default WSS project workspace, or null to have no workspace.
            if (chkDefaultWorkspace.Checked)
              wssUrl = "";
            else if (projectWorkspace == "")
              wssUrl = null;
            else
              wssUrl = projectWorkspace;
    
            bool fullPublish = true;
            // Publishes project to the Published db
            dsProjectRelations = project.QueuePublish(jobGuid, projectGuid, fullPublish, wssUrl);
            created = true;
          }
          catch (SoapException ex)
          {
            string errMess = "";
            // Pass the exception to the PSClientError constructor to get 
            // all error information.
            PSLibrary.PSClientError error = new PSLibrary.PSClientError(ex);
            PSLibrary.PSErrorInfo[] errors = error.GetAllErrors();
    
            for (int j = 0; j < errors.Length; j++)
            {
              errMess += errors[j].ErrId.ToString() + "\n";
            }
            errMess += "\n" + ex.Message.ToString();
    
            MessageBox.Show(errMess, "Error", MessageBoxButtons.OK,
              MessageBoxIcon.Error);
          }
          catch (WebException ex)
          {
            string message = ex.Message.ToString() +
              "\n\nLog on, or check the Project Server Queuing Service";
            MessageBox.Show(message, "Project Creation Error", 
              MessageBoxButtons.OK, MessageBoxIcon.Error);
          }
          this.Cursor = Cursors.Default;
          
          if (created)
          {
            lblProjectCreated.ForeColor = Color.Green;
            lblWorkspaceUrl.Visible = true;
            lblWorkspaceLabel.Visible = true;
          }
          else
          {
            projectCreatedLabel = "Project not created";
            lblProjectCreated.ForeColor = Color.Red;
            lblWorkspaceUrl.Visible = false;
            lblWorkspaceLabel.Visible = true;
          }
          lblProjectCreated.Text = projectCreatedLabel;
          lblProjectCreated.Visible = true;
        }
    

    Hope this helps.  I will also do a blog posting for anyone else still waiting since my 2007 original post.  Sorry it took so long.

    Best regards,

    Brian.


    Blog | Facebook | Twitter | Posting is provided "AS IS" with no warranties, and confers no rights.
    Project Server TechCenter | Project Developer Center | Project Server Help | Project Product Page
    • Marked as answer by chocochip Friday, August 27, 2010 3:01 PM
    Wednesday, August 25, 2010 6:58 PM
    Owner

All replies

  • Hi chocochip,

    this error is because when you create/save a project, you must fill every custom field that have "Required" flag. So, check in you enterprise what Custom fields (for task or project) that are flagged with "Required".

    You must fill this custom field before create project.

    I hope this help you.

    Best Regards,

    Paolo O.

    Saturday, August 21, 2010 2:05 PM
  • Thanks Paolo. You are right. We have 2 required fields for tasks. How do I populate these 2 fields with values in C#?

    Here's the code I'm using:

    static private Guid CreateSampleProject(ProjectWebSvc.Project projectSvc, QueueSystemWebSvc.QueueSystem q)
        {
          ProjectWebSvc.ProjectDataSet projectDs = new ProjectWebSvc.ProjectDataSet();
          Guid jobId;
          // Create the project
          ProjectWebSvc.ProjectDataSet.ProjectRow projectRow = projectDs.Project.NewProjectRow();
          projectRow.PROJ_UID = Guid.NewGuid();
          projectRow.PROJ_NAME = "Chocochip Test " +
            DateTime.Now.ToShortDateString().Replace("/", "") + " " +
            DateTime.Now.ToShortTimeString().Replace(":", "");
          projectRow.PROJ_TYPE = (int)PSLibrary.Project.ProjectType.Project;
          projectDs.Project.AddProjectRow(projectRow);
    
          // Add some tasks
          ProjectWebSvc.ProjectDataSet.TaskRow taskOne = projectDs.Task.NewTaskRow();
          taskOne.PROJ_UID = projectRow.PROJ_UID;
          taskOne.TASK_UID = Guid.NewGuid();
          //Task Duration format must be specified
          taskOne.TASK_DUR_FMT = (int)PSLibrary.Task.DurationFormat.Day;
          taskOne.TASK_DUR = 4800; // 8 hours in duration units (minute/10)
          taskOne.TASK_NAME = "Task One";
          taskOne.TASK_START_DATE = System.DateTime.Now.AddDays(1);
          taskOne.AddPosition = (int) PSLibrary.Task.AddPositionType.First;      
          projectDs.Task.AddTaskRow(taskOne);
    
          ProjectWebSvc.ProjectDataSet.TaskRow taskTwo = projectDs.Task.NewTaskRow();
          taskTwo.PROJ_UID = projectRow.PROJ_UID;
          taskTwo.TASK_UID = Guid.NewGuid();
          //Task Duration format must be specified
          taskTwo.TASK_DUR_FMT = (int)PSLibrary.Task.DurationFormat.Day;
          taskTwo.TASK_DUR = 4800; // 8 hours in duration units (minute/10)
          taskTwo.TASK_NAME = "Task Two";
          taskTwo.TASK_START_DATE = System.DateTime.Now.AddDays(1);
          taskTwo.AddPosition = (int)PSLibrary.Task.AddPositionType.Middle;
          taskTwo.AddAfterTaskUID = taskOne.TASK_UID;
          taskTwo.TASK_PARENT_UID = taskOne.TASK_UID;
          projectDs.Task.AddTaskRow(taskTwo);
    
          // Save the project to the database
          jobId = Guid.NewGuid();
          projectSvc.QueueCreateProject(jobId, projectDs, false);
          WaitForQueue(q, jobId);
          return projectRow.PROJ_UID;
        }
    

     

    Monday, August 23, 2010 3:07 PM
  • Hi chocochip,

    You need to add a TaskCustomFieldsRow to the dataset and set the values.  The MSDN reference for the row is at http://msdn.microsoft.com/en-us/library/websvcproject.projectdataset.taskcustomfieldsrow.aspx and you might find the general blog entry about custom fields at http://blogs.msdn.com/b/brismith/archive/2007/12/06/setting-custom-field-values-using-the-psi.aspx useful.

    Best regards,

    Brian


    Blog | Facebook | Twitter | Posting is provided "AS IS" with no warranties, and confers no rights.
    Project Server TechCenter | Project Developer Center | Project Server Help | Project Product Page
    Monday, August 23, 2010 8:09 PM
    Owner
  • Do you have a C# code example where:

    1. A new project is created

    2. New tasks are added

    3. The required custom fields are populated

    I can't seem to find an example of the whole implementation. I'm looking at this post: http://www.eggheadcafe.com/software/aspnet/34929441/cant-add-a-taskcustomfield--gives-me-itasktable-already-contains-this-task.aspx

    But I don't see where the QueueCreateProject is created. Thanks.

    Monday, August 23, 2010 9:02 PM
  • I don't - but I will see if I can put one together.  I think I promised one in my 2007 blog posting, so a little overdue.  Watch this space.  You might also be able to unravel the required code from ProjTool - the SDK sample, but I'll see if I can get something together in the next couple of days.

    Best regards,

    Brian.


    Blog | Facebook | Twitter | Posting is provided "AS IS" with no warranties, and confers no rights.
    Project Server TechCenter | Project Developer Center | Project Server Help | Project Product Page
    Monday, August 23, 2010 10:26 PM
    Owner
  • Thanks Brian. I look forward to seeing your sample code.
    Tuesday, August 24, 2010 7:23 PM
  • Here it is chocochip,

    I have built this around the SDK LoginDemo sample, and just added to the btnCreateProject_Click method.  The sample just creates a project - see http://msdn.microsoft.com/en-us/library/ms455600(office.12).aspx.  I have added a task, and both Project and Task level custom fields.  Across the project and task levels I have used each type of custom field to show which values need setting.  This is just to create a project - obviously adding or changing them later is very similar.  Sorry the formatting isn't better.

    For simplicity (and laziness) I have hard coded many of the GUIDs I am using.  For the Custom Fields I copied these from the URLs when in the edit screen for custom fields.  I got the lookup table value GUID in the 'View Source' page when editing the lookup table.  Obviously you could also get these from the database.  In a real situation you would use the Custom Field and Lookup Table web services.  Obviously your GUIDs will be different from mine.

    private void btnCreateProject_Click(object sender, EventArgs e)
        {
          string projectCreatedLabel = "Project created!";
          string wssUrl;
          string projectWorkspace = ResetWorkspaceUrl();
          bool created = false;
    
          // GUIDs for my CFs etc - in practice you would use the CF and LU PSI calls
          Guid projCostGuid = new Guid("e672bd64-c535-4486-bc64-8f4999547390");
          Guid projDateGuid = new Guid("3dafa5d4-9473-4781-9503-aafe207a71bb");
          Guid projTextGuid = new Guid("08758857-1a69-4efb-a657-27ed61d7d7c3");
          Guid taskTextGuid = new Guid("30665299-bc21-4c51-b954-220d407ba47e");
          Guid taskFlagGuid = new Guid("3658a81d-2e64-436f-afb9-970b778954b1");
          Guid taskNumberGuid = new Guid("d5c0318c-06cc-4d82-a891-7f3ea43503ab");
          Guid taskDurationGuid = new Guid("58519124-7e1d-44b8-b14c-7435408f02e7");
          Guid colourLUValueRed = new Guid("5b730bab-7212-4ffb-823d-60aef0df1fff");
    
          lblProjectCreated.Text = "";
          lblWorkspaceUrl.Text = projectWorkspace;
          this.Cursor = Cursors.WaitCursor;
    
          try
          {
            WebSvcProject.ProjectDataSet dsProject = 
              new WebSvcProject.ProjectDataSet();
            WebSvcProject.ProjectDataSet.ProjectRow projectRow = 
              dsProject.Project.NewProjectRow();
    
            Guid projectGuid = Guid.NewGuid();
            projectRow.PROJ_UID = projectGuid;
            projectRow.PROJ_NAME = this.txtProjectName.Text;
            projectRow.PROJ_TYPE = 
              Convert.ToInt32(PSLibrary.Project.ProjectType.Project);
    
            dsProject.Project.AddProjectRow(projectRow);
    
            //Adding a row for my first Project CF - ProjCost
    
            WebSvcProject.ProjectDataSet.ProjectCustomFieldsRow cfRowCost = 
              dsProject.ProjectCustomFields.NewProjectCustomFieldsRow();
    
            cfRowCost.PROJ_UID = projectGuid;
            // The Custom_Field_UID is the unique identifier for each custom field row
            cfRowCost.CUSTOM_FIELD_UID = Guid.NewGuid();
            // The MD_PROP_UID identifies the specific custom field
            cfRowCost.MD_PROP_UID = projCostGuid;
            // Cost custom fields have their value set in NUM_VALUE
            // The value entered is decimal and 100 times the actual cost - 5000 = $50 in my case
            cfRowCost.NUM_VALUE = 5000;
    
            //Adding a row for my second Project CF - ProjDate
    
            WebSvcProject.ProjectDataSet.ProjectCustomFieldsRow cfRowDate =
              dsProject.ProjectCustomFields.NewProjectCustomFieldsRow();
    
            cfRowDate.PROJ_UID = projectGuid;
            cfRowDate.CUSTOM_FIELD_UID = Guid.NewGuid();
            cfRowDate.MD_PROP_UID = projDateGuid;
            // Date custom fields have their values set in DATE_VALUE as a DateTime data type
            cfRowDate.DATE_VALUE = DateTime.Parse("Aug 25, 2010 10:45:00 PM");
    
            //Adding a row for my third Project CF - ProjText, which is based on a Lookup Table
    
            WebSvcProject.ProjectDataSet.ProjectCustomFieldsRow cfRowText =
              dsProject.ProjectCustomFields.NewProjectCustomFieldsRow();
    
            cfRowText.PROJ_UID = projectGuid;
            cfRowText.CUSTOM_FIELD_UID = Guid.NewGuid();
            cfRowText.MD_PROP_UID = projTextGuid;
            // Custom fields based on a lookup table have the GUID that identifies the row in
            // the lookup table entered against CODE_VALUE. See the LT_STRUCT_UID from the 
            // LookupTable web service
            cfRowText.CODE_VALUE = colourLUValueRed;
    
            //Adding my CFRows to the dataset
    
            dsProject.ProjectCustomFields.AddProjectCustomFieldsRow(cfRowCost);
            dsProject.ProjectCustomFields.AddProjectCustomFieldsRow(cfRowDate);
            dsProject.ProjectCustomFields.AddProjectCustomFieldsRow(cfRowText);
    
            //Now for the Task custom fields. First I will add a Task
    
            WebSvcProject.ProjectDataSet.TaskRow taskRow =
              dsProject.Task.NewTaskRow();
    
            Guid taskGuid = Guid.NewGuid();
    
            taskRow.PROJ_UID = projectGuid;
            taskRow.TASK_UID = taskGuid;
            taskRow.TASK_NAME = "My Task";
    
            dsProject.Task.AddTaskRow(taskRow);
    
            // And add some custom fields to my task
    
            // First a text field not based on a lookup table
            WebSvcProject.ProjectDataSet.TaskCustomFieldsRow cfRowTaskText =
              dsProject.TaskCustomFields.NewTaskCustomFieldsRow();
    
            cfRowTaskText.PROJ_UID = projectGuid;
            // For our Task CF rows we need the Task UID as well as the Project UID
            cfRowTaskText.TASK_UID = taskGuid;
            cfRowTaskText.CUSTOM_FIELD_UID = Guid.NewGuid();
            cfRowTaskText.MD_PROP_UID = taskTextGuid;
            // As we have no lookup table for this text field the value goes in TEXT_VALUE
            cfRowTaskText.TEXT_VALUE = "My Text Value";
    
            // Next a Flag field
            WebSvcProject.ProjectDataSet.TaskCustomFieldsRow cfRowTaskFlag =
              dsProject.TaskCustomFields.NewTaskCustomFieldsRow();
    
            cfRowTaskFlag.PROJ_UID = projectGuid;
            cfRowTaskFlag.TASK_UID = taskGuid;
            cfRowTaskFlag.CUSTOM_FIELD_UID = Guid.NewGuid();
            cfRowTaskFlag.MD_PROP_UID = taskFlagGuid;
            // Flags are a bool, so expect true or false - they default to false
            // Also Flags cannot be made required, as they will always have a value anyway
            // They are entered against FLAG_VALUE
            cfRowTaskFlag.FLAG_VALUE = true;
    
            // Next a Number field
            WebSvcProject.ProjectDataSet.TaskCustomFieldsRow cfRowTaskNumber =
              dsProject.TaskCustomFields.NewTaskCustomFieldsRow();
    
            cfRowTaskNumber.PROJ_UID = projectGuid;
            cfRowTaskNumber.TASK_UID = taskGuid;
            cfRowTaskNumber.CUSTOM_FIELD_UID = Guid.NewGuid();
            cfRowTaskNumber.MD_PROP_UID = taskNumberGuid;
            // Numbers are decimal - the M suffix is used as this value would normally default to double
            // They are entered against NUM_VALUE
            cfRowTaskNumber.NUM_VALUE = 25.6M;
    
            // Finally a duration field
            WebSvcProject.ProjectDataSet.TaskCustomFieldsRow cfRowTaskDuration =
              dsProject.TaskCustomFields.NewTaskCustomFieldsRow();
    
            cfRowTaskDuration.PROJ_UID = projectGuid;
            cfRowTaskDuration.TASK_UID = taskGuid;
            cfRowTaskDuration.CUSTOM_FIELD_UID = Guid.NewGuid();
            cfRowTaskDuration.MD_PROP_UID = taskDurationGuid;
            // Durations have a format for their display which is best enumerated as below
            // They are entered against NUM_VALUE
            cfRowTaskDuration.DUR_FMT = (int)PSLibrary.Task.DurationFormat.Day; 
            // Duration is indicated in tenths of minutes. A value of 100 indicates 10 minutes
            cfRowTaskDuration.DUR_VALUE = 24000;
    
            // Add my custom field rows to the dataset
    
            dsProject.TaskCustomFields.AddTaskCustomFieldsRow(cfRowTaskText);
            dsProject.TaskCustomFields.AddTaskCustomFieldsRow(cfRowTaskFlag);
            dsProject.TaskCustomFields.AddTaskCustomFieldsRow(cfRowTaskNumber);
            dsProject.TaskCustomFields.AddTaskCustomFieldsRow(cfRowTaskDuration);
    
            
    
            Guid jobGuid = Guid.NewGuid();
            bool validateOnly = false;
            // Create and save project to the Draft db
            project.QueueCreateProject(jobGuid, dsProject, validateOnly);
    
            // Wait 3 seconds (more or less) for Queue job to complete.
            // Or, add a routine that checks the QueueSystem for job completion.
            System.Threading.Thread.Sleep(3000);
    
            WebSvcProject.ProjectRelationsDataSet dsProjectRelations =
              new WebSvcProject.ProjectRelationsDataSet();
            jobGuid = Guid.NewGuid();
    
            // Set wssUrl = "" to have default WSS project workspace, or null to have no workspace.
            if (chkDefaultWorkspace.Checked)
              wssUrl = "";
            else if (projectWorkspace == "")
              wssUrl = null;
            else
              wssUrl = projectWorkspace;
    
            bool fullPublish = true;
            // Publishes project to the Published db
            dsProjectRelations = project.QueuePublish(jobGuid, projectGuid, fullPublish, wssUrl);
            created = true;
          }
          catch (SoapException ex)
          {
            string errMess = "";
            // Pass the exception to the PSClientError constructor to get 
            // all error information.
            PSLibrary.PSClientError error = new PSLibrary.PSClientError(ex);
            PSLibrary.PSErrorInfo[] errors = error.GetAllErrors();
    
            for (int j = 0; j < errors.Length; j++)
            {
              errMess += errors[j].ErrId.ToString() + "\n";
            }
            errMess += "\n" + ex.Message.ToString();
    
            MessageBox.Show(errMess, "Error", MessageBoxButtons.OK,
              MessageBoxIcon.Error);
          }
          catch (WebException ex)
          {
            string message = ex.Message.ToString() +
              "\n\nLog on, or check the Project Server Queuing Service";
            MessageBox.Show(message, "Project Creation Error", 
              MessageBoxButtons.OK, MessageBoxIcon.Error);
          }
          this.Cursor = Cursors.Default;
          
          if (created)
          {
            lblProjectCreated.ForeColor = Color.Green;
            lblWorkspaceUrl.Visible = true;
            lblWorkspaceLabel.Visible = true;
          }
          else
          {
            projectCreatedLabel = "Project not created";
            lblProjectCreated.ForeColor = Color.Red;
            lblWorkspaceUrl.Visible = false;
            lblWorkspaceLabel.Visible = true;
          }
          lblProjectCreated.Text = projectCreatedLabel;
          lblProjectCreated.Visible = true;
        }
    

    Hope this helps.  I will also do a blog posting for anyone else still waiting since my 2007 original post.  Sorry it took so long.

    Best regards,

    Brian.


    Blog | Facebook | Twitter | Posting is provided "AS IS" with no warranties, and confers no rights.
    Project Server TechCenter | Project Developer Center | Project Server Help | Project Product Page
    • Marked as answer by chocochip Friday, August 27, 2010 3:01 PM
    Wednesday, August 25, 2010 6:58 PM
    Owner
  • Thanks for the code Brian! I really appreciate it.
    Friday, August 27, 2010 3:02 PM