Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Lesedauer 7 Min.

Dokumente und Collaboration mit Microsoft Graph

Eine .NET-App liest Dokumentbibliotheken aus OneDrive und SharePoint, überträgt Dateien und verfolgt Änderungen über Microsoft Graph.
© EMGenie

OneDrive und SharePoint bilden in vielen Unternehmen die gemeinsame Dokumentenbasis. Dieser Beitrag zeigt, wie Microsoft Graph Dateien, Ordner, Bibliotheken, Versionen und Freigaben für eigene .NET-Anwendungen zugänglich macht, und ergänzt damit den zugehörigen Leitartikel „Connected Apps mit .NET“ unter [1].

Dokumente liegen in Microsoft 365 nicht einfach nur als Dateien in einem Verzeichnis. In OneDrive und SharePoint sind sie Teil einer größeren Struktur aus Sites, Dokumentbibliotheken, Ordnern, Berechtigungen, Versionen und Freigaben. Microsoft Graph bildet diese Strukturen für die .NET-App ab. Das Modell besteht aus Site, Drive und DriveItem. Eine SharePoint-Site kann mehrere Dokumentbibliotheken besitzen, jede Bibliothek erscheint in Graph als Drive, und Dateien sowie Ordner werden als DriveItem angesprochen.

Damit eignet sich Microsoft Graph nicht nur für einen einfachen Datei-Download. Eine Anwendung kann beispielsweise Projektunterlagen aus einer SharePoint-Bibliothek anzeigen, neue Dokumente ablegen, Versionen auslesen oder Freigabelinks erzeugen. Der Benutzer bleibt dabei in der eigenen Anwendung, während Microsoft 365 die eigentliche Dokumentenablage übernimmt.

Entscheidend ist auch hier, den Zugriff aus Gründen der Datensicherheit und des Datenschutzes auf die tatsächlich benötigten Daten zu beschränken. Für einen lesenden Zugriff auf Dateien im Benutzerkontext genügt in vielen Szenarien Files.Read. Soll auf SharePoint-Sites zugegriffen werden, kommt die Berechtigung Sites.Read.All hinzu. Schreibende Funktionen benötigen entsprechend weitergehende Rechte, wie Files.ReadWrite oder Sites.ReadWrite.All.

Für Datei- und SharePoint-Zugriffe initialisiert wird der Graph-Client folgendermaßen:

 

private static readonly string[] Scopes =
[
    "Files.Read",
    "Sites.Read.All"
];
_pca = PublicClientApplicationBuilder.Create(clientId)
    .WithAuthority(AzureCloudInstance.AzurePublic, tenant)
    .WithRedirectUri("http://localhost")
    .Build();
var provider = new BaseBearerTokenAuthenticationProvider(
    new MsalAccessTokenProvider(this));
_graphClient = new GraphServiceClient(provider);

 

Die Anmeldung kann – wie in anderen Szenarien (siehe Teil 1 und Teil 2 dieser Serie zu Connected Apps mit .NET) – zunächst mit bereits vorhandenen Anmeldeinformationen versucht werden. Nur wenn kein gültiges Zugriffstoken verfügbar ist, wird der Benutzer interaktiv zur Anmeldung aufgefordert. Danach übernimmt der GraphServiceClient die Kommunikation mit Microsoft Graph. Die eigentliche Dokumentenlogik muss dadurch weder OAuth-Abläufe noch einzelne HTTP-Requests selbst verwalten.

Dokumentbibliotheken und Ordner gezielt lesen

Für den Zugriff auf SharePoint ist zunächst die Ziel-Site relevant. Eine Site kann über ihre ID angesprochen oder über Hostname und Pfad ermittelt werden. Die zugehörigen Dokumentbibliotheken lassen sich anschließend als Drives abrufen. Damit entsteht eine klare Hierarchie (vergleiche Bild 1):

Site → Drive → DriveItem

Ein persönliches OneDrive folgt demselben Grundmodell, beginnt aber direkt beim Drive des Benutzers.

Einheitlicher Dokumentzugriff über Microsoft Graph – OneDrive und SharePoint (Bild 1)

Einheitlicher Dokumentzugriff über Microsoft Graph – OneDrive und SharePoint (Bild 1)

© Autor

Innerhalb einer Dokumentbibliothek liefert die children-Beziehung die Elemente eines Ordners. Für eine Dateiansicht werden meist nur wenige Eigenschaften benötigt: ID, Name, Größe, Web-URL, Änderungszeitpunkt sowie die Information, ob es sich um eine Datei oder einen Ordner handelt. Mit $select lässt sich die Antwort entsprechend begrenzen. Ordner besitzen eine folder-Facette, Dateien eine file-Facette. Diese Unterscheidung genügt bereits für einen einfachen Dokumentenbrowser.

Geladen werden die Dateien und Ordner einer Dokumentbibliothek in folgender Weise:

 

public async Task<IReadOnlyList<DriveItem>> LoadFolderAsync(string driveId, string folderId,
        CancellationToken ct = default)
{
    var page = await _graphClient.Drives[driveId]
        .Items[folderId].Children.GetAsync(cfg =>
        {
            cfg.QueryParameters.Select =
            [
                "id", "name", "size", "webUrl",
                "lastModifiedDateTime", "folder", "file"
            ];
            cfg.QueryParameters.Orderby = ["name"];
            cfg.QueryParameters.Top = 100;
        }, ct);
    return page?.Value ?? [];
}

 

Die Methode arbeitet mit einer Drive-ID und einer Ordner-ID. Damit ist sie unabhängig davon, ob der Inhalt aus OneDrive oder aus einer SharePoint-Dokumentbibliothek stammt. Für die Anzeige können die komplexen DriveItem-Objekte anschließend in ein einfacheres und kompaktes eigenes Datenmodell überführt werden. Die Oberfläche benötigt häufig nur Name, Typ, Größe, Änderungsdatum und eine Aktion zum Öffnen oder Herunterladen:

 

public sealed record DocumentDisplayItem(
    string Id,
    string Name,
    bool IsFolder,
    long Size,
    DateTimeOffset? Modified,
    string WebUrl);
private static DocumentDisplayItem ToDisplayItem(DriveItem item) =>
    new(
        item.Id ?? "",
        item.Name ?? "",
        item.Folder is not null,
        item.Size ?? 0,
        item.LastModifiedDateTimez,
        item.WebUrl ?? "");

 

Die Trennung vereinfacht die Darstellung deutlich. Eine Desktop-, Mobile- oder Weboberfläche kann dieselbe Liste beispielsweise als Tabelle, Kacheln oder Baumansicht anzeigen, ohne die Graph-Typen zu kennen. Beim Öffnen eines Ordners wird dessen ID erneut an LoadFolderAsync übergeben; beim Öffnen einer Datei kann der Web-URL verwendet oder der Dateiinhalt direkt über Graph geladen werden.

Wie bei anderen Graph-Aufrufen muss auch hier Pagination berücksichtigt werden. Ein Top-Wert beschreibt nur die gewünschte Seitengröße. Liefert Graph weitere Ergebnisse, muss der nächste Link verarbeitet werden. Gerade in Dokumentbibliotheken mit vielen Dateien darf eine Anwendung nicht davon ausgehen, dass eine einzelne Antwort den gesamten Ordner enthält.

Dateien übertragen, Versionen und Freigaben nutzen

Für viele Anwendungen ist das Lesen nur der erste Schritt. Dokumente sollen aus der eigenen Anwendung heraus abgelegt oder aktualisiert werden. Bei kleineren Dateien kann der Inhalt in einem einzigen Request übertragen werden. Microsoft Graph unterstützt diesen direkten Upload derzeit für Dateien bis 250 MByte. Für größere Dateien empfiehlt sich eine Upload-Session, bei der die Datei in Blöcken übertragen wird und ein unterbrochener Upload fortgesetzt werden kann.

Das Hochladen einer Datei in eine Dokumentbibliothek gestaltet sich folgendermaßen:

 

public async Task<DriveItem?> UploadFileAsync(
        string driveId,
        string parentId,
        string fileName,
        string localPath,
        CancellationToken ct = default)
{
    await using var stream = File.OpenRead(localPath);
    return await _graphClient.Drives[driveId]
        .Items[parentId]
        .ItemWithPath(fileName)
        .Content.PutAsync(stream, cancellationToken: ct);
}

 

Die Zielposition wird durch die Dokumentbibliothek, den übergeordneten Ordner und den Dateinamen bestimmt. Soll eine bereits vorhandene Datei ersetzt werden, kann sie auch über ihre DriveItem-ID adressiert werden. Der Download funktioniert über die content-Ressource eines DriveItem. Nur Elemente mit einer file-Facette besitzen einen herunterladbaren Dateiinhalt. Der Stream kann anschließend in einer lokalen Datei gespeichert, direkt weiterverarbeitet oder beispielsweise einer Dokumentvorschau zugeführt werden. Hier das Herunterladen einer Datei:

 

public async Task DownloadFileAsync(
        string driveId,
        string itemId,
        string targetPath,
        CancellationToken ct = default)
{
    await using var source = await _graphClient.Drives[driveId]
        .Items[itemId].Content.GetAsync(cancellationToken: ct);
    if (source is null)
        return;
    await using var target = File.Create(targetPath);
    await source.CopyToAsync(target, ct);
}

 

Ein Vorteil von SharePoint und OneDrive gegenüber einer einfachen Dateiablage ist die Versionierung. Microsoft Graph kann die vorhandenen Versionen eines DriveItem auslesen. Damit lässt sich beispielsweise anzeigen, wann ein Dokument geändert wurde oder welche ältere Version verfügbar ist. Abhängig von der Konfiguration der Bibliothek kann eine neue Version bei Änderungen, Speichervorgängen oder manuell entstehen. Abgerufen werden die Dokumentversionen so:

 

var versions = await _graphClient.Drives[driveId]
    .Items[itemId].Versions.GetAsync(cancellationToken: ct);
foreach (var version in versions?.Value ?? [])
{
    Console.WriteLine($"{version.Id}  {version.LastModifiedDateTime}");
}

 

Auch Freigaben lassen sich programmatisch erzeugen. Die createLink-Aktion liefert eine Permission mit einem Freigabelink zurück. Der Link kann beispielsweise für einen nur lesenden Zugriff oder für eine Bearbeitung der Dokumente genutzt werden.

Änderungen verfolgen statt Bibliotheken neu laden

Eine Dokumentenansicht beim Öffnen vollständig neu zu laden ist für wenige Dateien und Ordner ausreichend. Sobald eine Anwendung Inhalte lokal zwischenspeichert, synchronisiert oder automatisiert weiterverarbeitet, sollten möglichst nur die Änderungen seit dem letzten Abruf ermittelt werden. Microsoft Graph stellt dafür Delta Queries bereit.

Der erste Delta-Aufruf läuft über den aktuellen Drive und liefert die vorhandenen Elemente seitenweise. Während dieser Initialisierung folgt die Anwendung den nextLinks. Am Ende erhält sie einen deltaLink. Dieser Link wird gespeichert und beim nächsten Synchronisationslauf erneut aufgerufen. Die Antwort enthält dann nur noch die seit diesem Zustand erkannten Änderungen, einschließlich neuer, geänderter und gelöschter Elemente. Dadurch muss eine große Dokumentbibliothek nicht bei jedem Abruf vollständig neu eingelesen werden.

Die Änderungen einer Dokumentbibliothek mit Delta Query werden so verfolgt:

 

var page = await _graphClient.Drives[driveId]
    .Items["root"].Delta.GetAsDeltaGetResponseAsync(
        cancellationToken: ct);
foreach (var item in page?.Value ?? [])
{
    // Lokalen Zustand aktualisieren.
}
var nextLink = page?.OdataNextLink;
var deltaLink = page?.OdataDeltaLink;

 

Für ereignisorientierte Szenarien kommen zusätzlich Change Notifications in Betracht. Eine Anwendung registriert dabei eine HTTPS-Adresse, an die Microsoft Graph Benachrichtigungen sendet, wenn sich ein überwachter Bereich ändert. Es ergibt sich ein Synchronisationsmuster (vergleiche Bild 2):

Notification empfangen → Verarbeitung entkoppeln → Delta Query ausführen → lokalen Zustand aktualisieren

Dokumentablauf in einer Graph-basierten Anwendung (Bild 2)

Dokumentablauf in einer Graph-basierten Anwendung (Bild 2)

© Autor

Bei SharePoint und OneDrive lohnt sich außerdem eine klare Entscheidung, welche Daten lokal überhaupt benötigt werden. Häufig genügt es, IDs und Metadaten zwischenzuspeichern und den eigentlichen Dateiinhalt erst bei Bedarf zu laden. Das reduziert Speicherbedarf und vermeidet unnötige Kopien vertraulicher Dokumente.

Fazit

Microsoft Graph stellt für OneDrive und SharePoint ein weitgehend einheitliches Dokumentenmodell bereit. Für eine .NET-Anwendung genügen ein authentifizierter GraphServiceClient, das Verständnis von Site, Drive und DriveItem sowie gezielte Abfragen für Ordner und Dateien. Darauf bauen Upload und Download, Versionierung, Freigaben und Synchronisation auf.

Delta Queries und Change Notifications ergänzen dieses Modell um effiziente Synchronisation und ereignisorientierte Verarbeitung.

[1] Veikko Krypczyk, Connected Apps mit .NET, dotnetpro 4/2026, Seite 36 ff.

Neueste Beiträge

Tests gezielt verteilen - Schnellere .NET-CI-Pipelines mit Test Sharding, Teil 1
Lange Testsuiten verzögern das Feedback im Pull Request. Meziantou.ShardedTest verteilt die Testfälle auf mehrere CI-Jobs und verspricht dadurch mehr Geschwindigkeit. Dieser Einstieg zeigt, wie die Aufteilung funktioniert und welche Voraussetzungen nötig sind.
6 Minuten
Outlook und Mailintegration mit Microsoft Graph - Connected Apps mit .NET, Teil 2
Eine .NET-App meldet Benutzer an, liest Outlook-Nachrichten aus dem Posteingang und bereitet E-Mails für Anzeige und weitere Verarbeitung auf.
8 Minuten
GitHub Actions umstellen - Schnellere .NET-CI-Pipelines mit Test Sharding, Teil 2
Eine Jobmatrix bringt die lokale Testaufteilung auf mehrere Runner. Damit daraus ein verlässlicher CI-Lauf entsteht, müssen Shard-Nummern, Fehlerstatus und Ergebnisdateien zusammenpassen. Der Workflow zeigt die nötigen Schritte.
6 Minuten

Das könnte Dich auch interessieren

Kalenderdaten mit Microsoft Graph - Connected Apps mit .NET, Teil 1
Eine .NET-App meldet Benutzer an, lädt eine Kalenderwoche und bereitet Outlook-Termine für die Anzeige auf.
6 Minuten
Outlook und Mailintegration mit Microsoft Graph - Connected Apps mit .NET, Teil 2
Eine .NET-App meldet Benutzer an, liest Outlook-Nachrichten aus dem Posteingang und bereitet E-Mails für Anzeige und weitere Verarbeitung auf.
8 Minuten
DB API Marketplace ersetzt das Open API Portal - Deutsche Bahn
Die Deutsche Bahn entwickelt sein DB Open Data Angebot weiter. Der erste Schritt ist die Umstellung des bisherigen Open API Portals auf den neuen DB API Marketplace.
2 Minuten
30. Mai 2022
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige