1

TL;DR - it appears to be impossible to delete tasks from Project Server using the REST API. Please, someone suggest something to me, because this is excruciatingly frustrating.


I'm trying to delete some tasks from Project Server using the REST API from an SPFx webpart using the SPFx HttpClient. Here are the steps I'm taking:

Get the project by sending GET to

https://server/site/_api/ProjectServer/Projects?$select=Name,Id,IsCheckedOut

Response is 200/OK. I happen to know there is only one project there, so I use the one at

response.json().then(responseJSON => responseJSON.value[0])

I store the ID to use later. If the project is not checked out, I proceed to check it out by sending POST to

https://server/site/_api/ProjectServer/Projects('projectId')/checkout

Response is 200/OK.

I then try to delete tasks, and I have tried BOTH

Sending DELETE to

https://server/site/_api/ProjectServer/Projects('projectId')/Draft/Tasks('taskId')

as described here, and also sending POST to

https://server/site/_api/ProjectServer/Projects('projectId')/Draft/Tasks('taskId')/deleteObject()

as described here. In BOTH cases I get back 200/OK, however for the DELETE request, if I do response.json() I get an "unexpected end of JSON content" error, and if I do response.text() I get just an empty string. If I do response.json() for the response of the POST request to the /deleteObject() endpoint, I get this:

console log of odata.null

In any case, the responses were 200/OK, so I then proceed to try to save the changes to the project by sending POST to

https://server/site/_api/ProjectServer/Projects('projectId')/Draft/update

Response is 200/OK. I then publish the project by sending POST to

https://server/site/_api/ProjectServer/Projects('projectId')/Draft/publish

Response is 200/OK. I then check in the project by sending POST to

https://server/site/_api/ProjectServer/Projects('projectId')/Draft/checkin

Response is 200/OK.

That seems like a reasonable course of action:

  • Check out the project
  • Make changes to the draft project (deletes)
  • Update the project
  • Publish the project
  • Check in the project

and for each of those steps the server is telling me it happened (200/OK).

But then if I open the project in MS Project client, or get

https://server/site/_api/ProjectServer/Projects('projectId')/Tasks

then the tasks I thought I deleted are still there!

What step am I missing to get my changes to stick?


OK, I tried to think of other approaches for how to get this done, and I realized I might be able to do it by operating on the draft task collection, instead of trying to do it at the task level.

I can add tasks to the project by doing this:

const uri = `https://server/site/_api/ProjectServer/Projects('${projectId}')/Draft/Tasks/Add`;
httpClient.post(uri, HttpClient.configurations.v1, {
    headers: {
        'accept': 'application/json',
        'content-type': 'application/json',
        'X-RequestDigest': this.requestDigest
    },
    body: JSON.stringify({
        parameters: {
            Name: 'My Shiny New Task'
        }
    })
});

and, if we look at the documentation for the add method of the DraftTaskCollection object, we can see that they specify the REST endpoint as being

http://<sitecollection>/<site>/_api/ProjectServer/Projects('projectid')/Draft/Tasks/add(parameters)

however clearly the parameters don't really go in parentheses as part of the URL, the parameters get sent in the body of the request.

So then if we go and look at the documentation of the remove method, it specifies that the REST endpoint is

http://<sitecollection>/<site>/_api/ProjectServer/Projects('projectid')/Draft/Tasks/remove(task)

however, again, we are most likely not sending the task parameter in parentheses as part of the URL, it should likely be sent in the body.

But when I try this:

const uri = `https://server/site/_api/ProjectServer/Projects('${projectId}')/Draft/Tasks/remove`;
httpClient.post(uri, HttpClient.configurations.v1, {
    headers: {
        'accept': 'application/json',
        'content-type': 'application/json',
        'X-RequestDigest': this.requestDigest
    },
    body: JSON.stringify({
        task: {
            Id: 'taskId'
        }
    })
});

I get back an error saying

The method Remove cannot be invoked as its parameter task is not supported.

Wait what???

The parameter that's specified in the documentation is "not supported"?

What the heck is going on here?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.