What is Microsoft Graph?
Microsoft Graph is the unified REST API for Microsoft 365. Think of it as a single gateway to access data across SharePoint, Teams, OneDrive, Outlook, Azure AD, and more - all through one consistent API.
Graph vs CSOM/PnP.Framework:
- Graph: Modern REST API, works across all Microsoft 365 services
- CSOM/PnP: SharePoint-specific, more SharePoint features available
When to Use Graph SDK vs PnP.Framework
✅ Use Graph SDK when:
- Building modern cloud applications
- Need access to Teams, OneDrive, Exchange, or Azure AD
- Want built-in retry logic, batching, and performance optimizations
- Building apps that integrate multiple Microsoft 365 services
✅ Use PnP.Framework when:
- Need advanced SharePoint features (site templates, provisioning, taxonomy)
- Working with SharePoint-specific APIs not yet in Graph
- Building SharePoint-focused solutions
- Need features like search refiners, managed metadata, or custom actions
❌ Graph SDK limitations:
- No support for SharePoint classic features (master pages, web parts)
- Limited search capabilities compared to SharePoint Search API
- Some advanced list/library features not available
- Can’t access SharePoint on-premises (SharePoint Server)
Quick Start
Building on the PnP.Framework authentication setup, let’s add Microsoft Graph SDK to access all Microsoft 365 services with the same certificate.
Add Graph Permissions
In your existing app registration, go to “API permissions” → “Add a permission” → “Microsoft Graph” → “Application permissions”:
- Sites.ReadWrite.All: SharePoint sites and lists access
Important: Click “Grant admin consent” after adding permissions!
Install and Code
Install the NuGet package:
Install-Package Microsoft.Graph
Here’s the same example from the PnP.Framework post, but using Graph SDK:
using Microsoft.Graph;
using Microsoft.Graph.Auth;
using System.Security.Cryptography.X509Certificates;
class Program
{
private static readonly string TenantId = "your-tenant-id";
private static readonly string ClientId = "your-client-id";
private static readonly string CertificatePath = @"C:\Temp\cert\pnpappcert.pfx";
private static readonly string CertificatePassword = "MySuperStrongPassword!";
static async Task Main(string[] args)
{
// Create Graph client (same certificate as PnP.Framework)
var certificate = new X509Certificate2(CertificatePath, CertificatePassword);
var options = new ClientCertificateCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
};
var clientCertCredential = new ClientCertificateCredential(
TenantId, ClientId, certificate, options);
var scopes = new[] { "https://graph.microsoft.com/.default" };
var graphClient = new GraphServiceClient(clientCertCredential, scopes);
// Test connection
var org = await graphClient.Organization.Request().GetAsync();
Console.WriteLine($"Connected to: {org.First().DisplayName}");
// Get all lists (like PnP.Framework example)
var site = await graphClient.Sites["root"].Request().GetAsync();
var lists = await graphClient.Sites[site.Id].Lists.Request().GetAsync();
Console.WriteLine("Lists in this site:");
foreach (var list in lists)
{
Console.WriteLine($"- {list.DisplayName}");
}
// Upload a document (like PnP.Framework example)
var docLib = lists.FirstOrDefault(l => l.DisplayName == "Documents");
if (docLib != null)
{
var content = System.Text.Encoding.UTF8.GetBytes("Hello from Graph SDK!");
var drive = await graphClient.Sites[site.Id].Lists[docLib.Id].Drive.Request().GetAsync();
var file = await graphClient.Drives[drive.Id].Root
.ItemWithPath("sample-document.txt")
.Content
.Request()
.PutAsync<DriveItem>(new MemoryStream(content));
Console.WriteLine($"Uploaded file: {file.Name}");
}
}
}
Key Differences from PnP.Framework
Same operations, different syntax:
| Operation | PnP.Framework | Graph SDK |
|---|---|---|
| Get Lists | context.Web.Lists |
graphClient.Sites[id].Lists |
| Upload File | docLib.RootFolder.Files.Add() |
drive.Root.ItemWithPath().Content.Put() |
| Authentication | AuthenticationManager |
ClientCertificateProvider |
Graph advantages: Access to Teams, OneDrive, Exchange data with same client
PnP advantages: More SharePoint-specific features like content types, site columns
Troubleshooting
- “Insufficient privileges”: Check permissions and admin consent
- “Certificate not found”: Verify certificate path and password
- “Unauthorized”: Ensure app has correct Graph permissions
Next Steps
You now have Graph SDK working with your existing app registration! With the basic setup, you can:
- Access SharePoint sites and lists
- Upload and manage files in document libraries
- Get organization information
To access more Microsoft 365 services, add the appropriate permissions:
- User.Read.All for user data
- Group.Read.All for Teams and groups
- Files.ReadWrite.All for broader file operations
- Mail.Read for Exchange data
Perfect foundation for building comprehensive Microsoft 365 integrations.