none
Project Server 2013. Unable to update Project Owner programmatically using CSOM RRS feed

  • Question

  • I'm unable to update the Project Owner using the CSOM.

    Below is the code I'm using.

    I can see it being added as a SharePoint user when I debug the code. draftProject.Owner = e.User;

    But after the update and a publish, nothing changes.

    public static void assignToTeam(ProjectContext projContext, DraftProject draftProject, Guid projectGuid, EnterpriseResource e)
            {
                projContext.Load(draftProject.ProjectResources);
                projContext.Load(e);
                projContext.Load(e.User);
                projContext.Load(draftProject);
                projContext.ExecuteQuery();

                draftProject.ProjectResources.AddEnterpriseResource(e);
                var updateResoColl = draftProject.Update();
                projContext.WaitForQueue(updateResoColl, Constants.timeoutSeconds);

                DraftProjectResourceCollection newResoColl = draftProject.ProjectResources;

                projContext.Load(e.User);
                projContext.ExecuteQuery();
                draftProject.Owner = e.User;
                draftProject.Update();
            }


    Brandon James SharePoint Developer/Administrator

    Thursday, September 25, 2014 2:51 PM

All replies

  • Hi James,

    Have you read this similar post? This might help you.

    http://social.msdn.microsoft.com/Forums/en-US/8b0e08b5-cd90-4fb1-b413-7a3e5a07e643/setting-the-project-owner-when-initially-creating-a-project-with-csom?forum=project2010custprog


    Hope this helps,


    Guillaume Rouyre, MBA, MCP, MCTS |


    Thursday, September 25, 2014 3:28 PM
    Moderator
  • Hi Brandon,

    It looks like you are doing everything right in that code, but in my experience I had a similar issue when trying set the owner using the EnterpriseResource.User property.

    In the end in my solution I added some code to get the SPSiteUsers.User object that matches my EnterpriseResource.User object, then I set the Owner to be that object and it works everytime.

    Regards,


    Martin Laukkanen
    Nearbaseline blog - nearbaseline.com/blog
    Bulk Edit and other Apps - nearbaseline.com/apps

    Monday, September 29, 2014 10:04 AM
  • This console app is working for me:

    using Microsoft.ProjectServer.Client;
    using Microsoft.SharePoint.Client;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace QueueUpdateProjectOwner
    {
        class Program
        {
            private static string pwaPath = "http://pServer.dev.local/pwa/"; // Change the path to your Project Web App instance.
            private static string projName = "hi";
            private static string strProjectGuid = "b61434b7-2885-4d39-81dc-2ed4950e8210";
            private static string Username = "i:0#.w|dev\\ghangas";
            private static int timeoutSeconds = 20;  // The maximum wait time for a queue job, in seconds.
    
            private static ProjectContext projContext;
    
            static void Main(string[] args)
            {
                if (!ParseCommandLine(args))
                {
                    Usage();
                    ExitApp();
                }
    
                projContext = new ProjectContext(pwaPath);
    
                UpdateProjectOwner();
                ExitApp();
            }
    
            // Create a project.
            private static bool UpdateProjectOwner()
            {
                bool projUpdated = false;
    
                try
                {
                    User newOwner = projContext.Web.SiteUsers.GetByLoginName(Username);
                    Guid ProjectGuid = Guid.Parse(strProjectGuid);
                    Console.Write("\nUpdating owner to {1} on project: {0} ...", ProjectGuid, Username);
    
                    DraftProject draftProjectToUpdate = projContext.Projects.GetByGuid(ProjectGuid).CheckOut();
                    draftProjectToUpdate.Owner = newOwner;
                    
                    QueueJob qJob = draftProjectToUpdate.Update();
                    projContext.Load(qJob);
                    projContext.ExecuteQuery();
                    JobState jobState = projContext.WaitForQueue(qJob, timeoutSeconds);
    
                    QueueJob qJob2 = draftProjectToUpdate.CheckIn(false);
                    projContext.Load(qJob2);
                    projContext.ExecuteQuery();
                    JobState jobState2 = projContext.WaitForQueue(qJob2, timeoutSeconds);
                }
                catch (Exception ex)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("\nError: {0}", ex.Message);
                    Console.ResetColor();
                }
                return projUpdated;
            }
    
            // Parse the command line. Return true if there are no errors.
            private static bool ParseCommandLine(string[] args)
            {
                bool error = false;
                int argsLen = args.Length;
    
                try
                {
                    for (int i = 0; i < argsLen; i++)
                    {
                        if (error) break;
                        if (args[i].StartsWith("-") || args[i].StartsWith("/"))
                            args[i] = "*" + args[i].Substring(1).ToLower();
    
                        switch (args[i])
                        {
                            case "*projguid":
                            case "*g":
                                if (++i >= argsLen) return false;
                                strProjectGuid = args[i];
                                break;
                            case "*username":
                            case "*u":
                                if (++i >= argsLen) return false;
                                Username = args[i];
                                break;
                            case "*pwaPath":
                            case "*p":
                                if (++i >= argsLen) return false;
                                pwaPath = args[i];
                                break;
                        }
                    }
                }
                catch (FormatException)
                {
                    error = true;
                }
    
                if (string.IsNullOrEmpty(projName)) error = true;
                return !error;
            }
    
            private static void Usage()
            {
                string example = "Usage: QueueCreateProject [-g \"Project guid\"] [-u username] [-p \"http://servername/pwa/\"]";
                example += "\nExample: QueueCreateProject -g \"b61434b7-2885-4d39-81dc-2ed4950e8210\" -u \"i:0#.w|dev\\ghangas\" -p \"http://Server.dev.local/pwa/\"";
                example += "\nDefault timeout seconds = " + timeoutSeconds.ToString();
                Console.WriteLine(example);
            }
    
            private static void ExitApp()
            {
                Console.Write("\nPress any key to exit... ");
                Console.ReadKey(true);
                Environment.Exit(0);
            }
        }
    }

    I ran into the following gotcha:

    in this section:

    		QueueJob qJob = draftProjectToUpdate.Update();
                    projContext.Load(qJob);
                    projContext.ExecuteQuery();
                    JobState jobState = projContext.WaitForQueue(qJob, timeoutSeconds);
    
                    QueueJob qJob2 = draftProjectToUpdate.CheckIn(false);
                    projContext.Load(qJob2);
                    projContext.ExecuteQuery();
                    JobState jobState2 = projContext.WaitForQueue(qJob2, timeoutSeconds);

    if you replace the qJob wait with a sleep timer it throws an exception. I did not dig into why sleeping did not work to allow the queue job to complete, but it didn't work for me. I suspect sleeping should work if you can handle the returns so they don't trip the catch

    For implementation I suggest turning this into a web service and running it on the pwa server to make it available to a workflow. 


    • Edited by ghangas Wednesday, October 15, 2014 7:18 PM punctuationating
    • Proposed as answer by Bhism Narayan Thursday, August 27, 2015 4:53 AM
    Wednesday, October 15, 2014 7:17 PM
  • this works for me:

    string Username = "i:0#.f|membership|user_email_here";
                         Microsoft.SharePoint.Client.User newOwner = projContext.Web.SiteUsers.GetByLoginName(Username);

                         projCheckedOut.Owner = newOwner;

                         projCheckedOut.Update();
                         projContext.ExecuteQuery();
                         projContext.Projects.Update();
                         projCheckedOut.Publish(true);


    tatiana

    Friday, April 13, 2018 4:49 PM
  • Hi, 

    How did you do this? Is this possible through Rest API? 

    Monday, August 10, 2020 6:37 AM