3

Objective

Connect to Project Server 2013 in order to update an existing assignment of a resource to a task or create a new assignment for the resource in case it (the resource) is not assigned to the particular task.


Context info

The tasks are identified by project and by a custom field called EnterpriseAbs (more tasks can have the same value). The assignments are identified by task and resourceId. The update operation is meant only for the update of the assignment units.

Assignments can be created/updated for normal projects and also for master projects. That excludes the use of CSOM being that master projects cannot be read/updated. The idea was to use the OData Endpoint in order to do the operations. Considering the situation I added a service reference to the endpoint. It's all nice and good with querying the data using the context, but as soon as I want to make some changes I can't because:

  • I can't find a way to check out the project,
  • It throws an SPException with the message

"The security validation for this page is invalid and might be corrupted. Please use your web browser's Back button to try your operation again."

as soon as I try to save the changes.

The method that does the operation is the following:

private IHttpActionResult UpsertViaOData(Guid projectId, 
                                         string abs, 
                                         AssignmentInformation assignment, 
                                         ProjectODataContainer.ReportingData container, 
                                         ProjectContext context)
{
    var tasks = container.Tasks.Where(t => t.ProjectId == projectId
                                        && t.EnterpriseABS == abs)
                               .ToList();
    if (tasks.Count == 0)
    {
        return Ok();
    }
    var project = container.Projects.Where(p => p.ProjectId == projectId)
                                    .ToList()
                                    .FirstOrDefault();
    if (project == default(ProjectODataContainer.Project))
    {
        return NotFound();
    }
    var resourceId = assignment.Resource.Id;
    var assignments = container.Assignments.Where(a => a.ProjectId == projectId
                                                    && a.ResourceId == resourceId)
                                           .ToDictionary(a => a.TaskId, a => a);
    foreach (var task in tasks)
    {
        ProjectODataContainer.Assignment taskAssignment;
        if (assignments.TryGetValue(task.TaskId, out taskAssignment))
        {
            // assignment already exists
            if (taskAssignment.AssignmentPeakUnits != assignment.Units)
            {
                taskAssignment.AssignmentPeakUnits = assignment.Units;
                container.UpdateObject(taskAssignment);
            }
        }
        else
        {
            // assignment does not exist
            taskAssignment = new ProjectODataContainer.Assignment
            {
                TaskId = task.TaskId,
                AssignmentId = Guid.NewGuid(),
                ProjectId = projectId,
                AssignmentPeakUnits = assignment.Units
            };
            container.AddToAssignments(taskAssignment);
        }
    }

    // This is the instruction that throws the aforementioned Exception
    container.SaveChanges(System.Data.Services.Client.SaveChangesOptions.PatchOnUpdate);

    return Ok();
}

with ProjectODataContainer.ReportingData being the context and AssignmentInformation being defined as follows:

public class AssignmentInformation
{
    public Guid Id { get; set; }
    public ResourceInformation Resource { get; set; }
    public Guid TaskId { get; set; }
    public decimal? Units { get; set; }

    public AssignmentInformation() { }
}

Seems like it is an authorization problem, but the credentials with which the context runs have the right privileges (the same credentials used with CSOM do the job, but - as I wrote before - CSOM cannot be used with master projects).

Anybody has an idea how to solve this?

1 Answer 1

0

"The security validation for this page is invalid and might be corrupted. Please use your web browser's Back button to try your operation again."

That is a formdigest issue. You need to add a "X-RequestDigest" header.

https://docs.microsoft.com/en-us/sharepoint/dev/sp-add-ins/complete-basic-operations-using-sharepoint-rest-endpoints#writing-data-by-using-the-rest-interface

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.