Users with permissions can create Planner tasks with PowerShell and Microsoft Graph. In the past, users could update a Planner task description in text format (string). Since 2022, the Planner API plannerTaskDetails contains a Notes property for an HTML description.
- Property Description > only supports plain text.
- Property Notes > supports HTML format.
As Microsoft describes in the documentation, these two properties are linked and should not be updated together.
notes
Rich text description of the task. To be used by HTML-aware clients. For backwards compatibility, a plain-text version of the HTML description will be synced to the “description” field. If this field hasn’t previously been set but “description” has been, the existing description is synchronized to “notes” with minimal whitespace-preserving HTML markup. Setting both “description” and “notes” is an error and will result in an exception.
Two steps are required to update the description field of a Planner task with PowerShell.
- Creating a Planner task
- Updating the description of the task
Content
New Planner task with description in plain text
In the first example, I create the task with the Description property. The description of that task is in plain text.
Import-Module Microsoft.Graph.Authentication
Connect-MgGraph -Scopes Tasks.ReadWrite
# Prepare the body to create a new task
$Body = @"
{
"planId": "xWXTRNFiDEuKXzpfad8EV5gAEFfk",
"bucketId": "DvPqFQBk0E-xeopNovLVGpgAEiJv",
"title": "Task with plain description"
}
"@
# Create a new task
$Url = "https://graph.microsoft.com/v1.0/planner/tasks"
$NewPlannerTask = Invoke-MgGraphRequest -Method POST -Uri $Url -Body $Body -ContentType "application/json"
$NewPlannerTaskID = $NewPlannerTask.id
# Get the task details to get the latest etag value (required to update a Planner task)
$Url = "https://graph.microsoft.com/v1.0/planner/tasks/$NewPlannerTaskID/details"
$PlannerTaskDetails = Invoke-MgGraphRequest -Method GET -Uri $Url -ContentType "application/json"
# Prepare the body to update the task with a description
$MessageBody = @"
<p>This is a <strong>sample description</strong> with <em>HTML</em> content.</p>
<ul>
<li>First item</li>
<li>Second item</li>
<li>Third item</li>
</ul>
<p>For more information, visit <a href='https://blog-en.topedia.com/' Target='_blank'>Topedia Blog</a>.</p>
"@
# Update the task body with the description
$Body = @{
'previewType' = 'noPreview'
'description' = $MessageBody
}
# Update the task with the description (in plain text)
$Url = "https://graph.microsoft.com/v1.0/planner/tasks/$NewPlannerTaskID/details"
$Header = @{ "If-Match" = $PlannerTaskDetails.'@odata.etag' }
Invoke-MgGraphRequest -Method PATCH -Uri $Url -Body ($Body | ConvertTo-Json) -Headers $Header -ContentType "application/json"
The new task has been created. The description is an unformatted HTML format in plain text.
New Planner task with description in HTML format
The same process for creating a task with a description in HTML format.
Important: Use the beta endpoint for the Notes property; otherwise, it will continue to create the description in plain text. The v1 endpoint does not yet support a Notes property.
# Prepare the body to create a new task
$Body = @"
{
"planId": "xWXTRNFiDEuKXzpfad8EV5gAEFfk",
"bucketId": "DvPqFQBk0E-xeopNovLVGpgAEiJv",
"title": "Task with HTML description"
}
"@
# Create a new task
$Url = "https://graph.microsoft.com/beta/planner/tasks"
$NewPlannerTask = Invoke-MgGraphRequest -Method POST -Uri $Url -Body $Body -ContentType "application/json"
$NewPlannerTaskID = $NewPlannerTask.id
# Get the task details to get the latest etag value (required to update a Planner task)
$Url = "https://graph.microsoft.com/beta/planner/tasks/$NewPlannerTaskID/details"
$PlannerTaskDetails = Invoke-MgGraphRequest -Method GET -Uri $Url -ContentType "application/json"
# Prepare the body to update the task with a description
$MessageBody = @"
<p>This is a <strong>sample description</strong> with <em>HTML</em> content.</p>
<ul>
<li>First item</li>
<li>Second item</li>
<li>Third item</li>
</ul>
<p>For more information, visit <a href='https://blog-en.topedia.com/'>Topedia Blog</a>.</p>
"@
# Update the task body with the HTML description
$Body = @{
'previewType' = 'noPreview'
'notes' = @{
'contentType' = 'html'
'content' = $MessageBody
}
}
# Update the task with the description (in HTML format)
$Url = "https://graph.microsoft.com/beta/planner/tasks/$NewPlannerTaskID/details"
$Header = @{ "If-Match" = $PlannerTaskDetails.'@odata.etag' }
Invoke-MgGraphRequest -Method PATCH -Uri $Url -Body ($Body | ConvertTo-Json) -Headers $Header -ContentType "application/json"
Disconnect-MgGraph
The second task has been created. The description is a formatted HTML format.
Bonus: New Planner task from Microsoft 365 Message in HTML format
The Microsoft 365 Message Center messages include an HTML format in the body. The entire body (incl. screenshots) can be added to the Planner task.
Note that the Notes property does not support some HTML attributes. For Microsoft 365 Messages, for example, one of the attributes is the attribute target=”_blank”. The API will return an error in such cases.
The request contains invalid HTML for the Notes field. [Invalid or disallowed HTML attribute or attribute value [NotAllowedAttribute]]
In my example for MC949004, I remove the attribute (if present).
Connect-MgGraph -Scopes Tasks.ReadWrite, ServiceMessage.Read.All
# Get the service announcement message for MC949004
$Url = "https://graph.microsoft.com/beta/admin/serviceAnnouncement/messages/MC949004"
$MCResult = Invoke-MgGraphRequest -Method Get -Uri $Url
# Prepare the body to create a new task
$TaskTitle = $MCResult.title + " - " + $MCResult.id
$Body = @"
{
"planId": "xWXTRNFiDEuKXzpfad8EV5gAEFfk",
"bucketId": "DvPqFQBk0E-xeopNovLVGpgAEiJv",
"title": "$TaskTitle"
}
"@
# Create a new task
$Url = "https://graph.microsoft.com/beta/planner/tasks"
$NewPlannerTask = Invoke-MgGraphRequest -Method POST -Uri $Url -Body $Body -ContentType "application/json"
$NewPlannerTaskID = $NewPlannerTask.id
# Get the task details to get the latest etag value (required to update a Planner task)
$Url = "https://graph.microsoft.com/beta/planner/tasks/$NewPlannerTaskID/details"
$PlannerTaskDetails = Invoke-MgGraphRequest -Method GET -Uri $Url -ContentType "application/json"
# Remove an unsupported HTML attribute from the message body
$MessageBody = $MCResult.body.content
$MessageBody = $MessageBody -replace 'target="_blank"', ""
# Prepare the body to update the task with a description
$Body = @{
'previewType' = 'noPreview'
'notes' = @{
'contentType' = 'html'
'content' = $MessageBody
}
}
# Update the task with the description (in HTML format)
$Url = "https://graph.microsoft.com/beta/planner/tasks/$NewPlannerTaskID/details"
$Header = @{ "If-Match" = $PlannerTaskDetails.'@odata.etag' }
Invoke-MgGraphRequest -Method PATCH -Uri $Url -Body ($Body | ConvertTo-Json) -Headers $Header -ContentType "application/json"
Disconnect-MgGraph
The third task was created, and the description is in HTML format.