I'm trying to create a plan inside a group using the Microsoft Graph SDK, but the request fails.
I'm able to get a list of groups, and a list of plans within a group, but when I copy-paste the code from the documentation example, I receive an ODataError without any exception details or even a meaningful message.
This is the code I'm using:
private async Task<PlannerPlan?> CreatePlan(Guid id, string planName)
{
var requestBody = new PlannerPlan
{
Container = new PlannerPlanContainer
{
Url = $"https://graph.microsoft.com/beta/groups/{id}"
},
Title = planName
};
var graphClient = GetGraphClient();
try
{
return await graphClient.Planner.Plans.PostAsync(requestBody);
}
catch (Microsoft.Graph.Models.ODataErrors.ODataError oDataError)
{
var error = oDataError.Error;
throw;
}
}
The id
is taken directly from the group which was obtained by calling...
await graphClient.Groups.GetAsync();
I've also tried specifying the group ID (as ContainerId
) and the container type (Type = PlannerContainerType.Group
) in the PlannerPlan
object, but this makes no difference.
This is the response from the Graph API:
The authentication takes place through an Azure app registration, which has been granted the following permissions:
Can anyone tell me why I'm unable to create the plan?
I registered one Azure AD application and granted API permissions of Application type like this:
Initially, I too got same error when I ran your code with /beta
in container URL like this:
private async Task<PlannerPlan?> CreatePlan(Guid id, string planName)
{
var requestBody = new PlannerPlan
{
Container = new PlannerPlanContainer
{
Url = $"https://graph.microsoft.com/beta/groups/{id}"
},
Title = planName
};
var graphClient = GetGraphClient();
try
{
return await graphClient.Planner.Plans.PostAsync(requestBody);
}
catch (Microsoft.Graph.Models.ODataErrors.ODataError oDataError)
{
var error = oDataError.Error;
throw;
}
}
Response:
To resolve the error, make use of v1.0
endpoint by modifying your code that is the correct containerUrl to specify path to group like this:
using Azure.Identity;
using Microsoft.Graph;
using Microsoft.Graph.Models;
using System;
class Program
{
static async Task Main(string[] args)
{
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "tenantId";
var clientId = "appId";
var clientSecret = "secret";
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
};
var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret, options);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
try
{
var groupId = "groupId"; // Group ID where you want to create the plan
var createdPlan = await CreatePlan(new Guid(groupId), "Demo Plan1", graphClient);
Console.WriteLine($"Plan Title: {createdPlan.Title}");
Console.WriteLine($"Plan ID: {createdPlan.Id}");
}
catch (Microsoft.Graph.Models.ODataErrors.ODataError oDataError)
{
var error = oDataError.Error;
Console.WriteLine(error.Code);
Console.WriteLine(error);
}
}
private static async Task<PlannerPlan?> CreatePlan(Guid id, string planName, GraphServiceClient graphClient)
{
var requestBody = new PlannerPlan
{
Container = new PlannerPlanContainer
{
Url = $"https://graph.microsoft.com/v1.0/groups/{id}"
},
Title = planName
};
try
{
return await graphClient.Planner.Plans.PostAsync(requestBody);
}
catch (Microsoft.Graph.Models.ODataErrors.ODataError oDataError)
{
var error = oDataError.Error;
throw; // Rethrow the exception to propagate it
}
}
}
Response:
Reference: plannerPlanContainer resource type - Microsoft Graph v1.0