March 2 2023 - Extremely late after-the-fact update: I got a follow up question to this (posted as an answer, so it's going to be removed) as to whether or not this ever got resolved.
For posterity:
NO. It never got resolved. I had to resort to using the Project Server JSOM (PS.js) to do the deletions because I never got it working with REST.
Have fun figuring out how to load the dependencies for PS.js into an SPFx webpart. It's possible (I did it), but.... obtuse. Arcane. For cryin' out Pete's sake, Microsoft, just get your REST API working.
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:
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?