Übung: Importieren externer Inhalte
In dieser Übung erweitern Sie den benutzerdefinierten Microsoft Graph-Connector um den Code, um lokale Markdowndateien in Microsoft 365 zu importieren.
Vorbereitende Schritte
Bevor Sie mit dieser Übung beginnen, sollten Sie die erste Übung in diesem Modul bereits abgeschlossen haben.
Kopieren Sie für diese Übung die in dieser Übung verwendeten Beispielinhaltsdateien aus GitHub , und speichern Sie sie in Ihrem Projekt in einem Ordner namens content.
Damit der Code ordnungsgemäß funktioniert, müssen der Inhaltsordner und seine Inhalte in den Buildausgabeordner kopiert werden.
Innerhalb des Code-Editors:
Öffnen Sie die CSPROJ-Datei , und fügen Sie vor dem
</Project>
Tag den folgenden Code hinzu:<ItemGroup> <ContentFiles Include="content\**" CopyToOutputDirectory="PreserveNewest" /> </ItemGroup> <Target Name="CopyContentFolder" AfterTargets="Build"> <Copy SourceFiles="@(ContentFiles)" DestinationFiles="@(ContentFiles->'$(OutputPath)\content\%(RecursiveDir)%(Filename)%(Extension)')" /> </Target>
Speichern Sie Ihre Änderungen.
Hinzufügen von Bibliotheken zum Analysieren von Markdown und YAML
Der Microsoft Graph-Connector, den Sie erstellen, importiert lokale Markdowndateien in Microsoft 365. Jede dieser Dateien enthält einen Header mit Metadaten im YAML-Format, auch als Frontmatter bezeichnet. Darüber hinaus werden die Inhalte jeder Datei in Markdown geschrieben. Um Metadaten zu extrahieren und den Text in HTML zu konvertieren, verwenden Sie benutzerdefinierte Bibliotheken:
- Öffnen Sie ein Terminal, und ändern Sie das Arbeitsverzeichnis in Ihr Projekt.
- Führen Sie den folgenden Befehl aus, um die Markdownverarbeitungsbibliothek hinzuzufügen:
dotnet add package Markdig
. - Führen Sie den folgenden Befehl aus, um die YAML-Verarbeitungsbibliothek hinzuzufügen:
dotnet add package YamlDotNet
.
Definieren einer Klasse zur Darstellung der importierten Datei
Um die Arbeit mit importierten Markdowndateien und deren Inhalten zu vereinfachen, definieren wir eine Klasse mit den erforderlichen Eigenschaften.
Innerhalb des Code-Editors:
Öffnen Sie die datei ContentService.cs .
Fügen Sie die
using
-Anweisung hinzu, und aktualisieren Sie dieDocument
-Klasse wie folgt:using YamlDotNet.Serialization; public interface IMarkdown { string? Markdown { get; set; } } class Document : IMarkdown { [YamlMember(Alias = "title")] public string? Title { get; set; } [YamlMember(Alias = "description")] public string? Description { get; set; } public string? Markdown { get; set; } public string? Content { get; set; } public string? RelativePath { get; set; } public string? IconUrl { get; set; } public string? Url { get; set; } }
Die
IMarkdown
-Schnittstelle stellt den Inhalt der lokalen Markdowndatei dar. Sie muss separat definiert werden, um die Deserialisierung von Dateiinhalten zu unterstützen. DieDocument
-Klasse stellt das endgültige Dokument mit analysierten YAML-Eigenschaften und HTML-Inhalten dar.YamlMember
Attribute ordnen Eigenschaften metadaten in der Kopfzeile jedes Dokuments zu.Speichern Sie Ihre Änderungen.
Implementieren des Ladens von Markdowndateien
Der nächste Schritt besteht darin, die Logik zu implementieren, die die lokalen Markdowndateien lädt, Metadaten extrahiert und den Inhalt in HTML konvertiert.
Fügen Sie zunächst Hilfsmethoden hinzu, um die Markdig
Bibliotheken und YamlDotNet
einfach zu verwenden.
Innerhalb des Code-Editors:
Erstellen Sie eine neue Datei mit dem Namen MarkdownExtensions.cs.
Fügen Sie in der Datei den folgenden Code hinzu:
// from: https://khalidabuhakmeh.com/parse-markdown-front-matter-with-csharp using Markdig; using Markdig.Extensions.Yaml; using Markdig.Syntax; using YamlDotNet.Serialization; public static class MarkdownExtensions { private static readonly IDeserializer YamlDeserializer = new DeserializerBuilder() .IgnoreUnmatchedProperties() .Build(); private static readonly MarkdownPipeline Pipeline = new MarkdownPipelineBuilder() .UseYamlFrontMatter() .Build(); }
Die
YamlDeserializer
-Eigenschaft definiert einen neuen Deserialisierer für den YAML-Block in jeder der Markdowndateien, die Sie extrahieren. Sie konfigurieren den Deserialisierer so, dass alle Eigenschaften ignoriert werden, die nicht Teil der Klasse sind, in die die Datei deserialisiert wird.Die
Pipeline
-Eigenschaft definiert eine Verarbeitungspipeline für den Markdownparser. Sie konfigurieren ihn so, dass der YAML-Header analysiert wird. Ohne diese Konfiguration würden die Informationen aus dem Header verworfen.Erweitern Sie als Nächstes die
MarkdownExtensions
-Klasse mit dem folgenden Code:public static T GetContents<T>(this string markdown) where T : IMarkdown, new() { var document = Markdown.Parse(markdown, Pipeline); var block = document .Descendants<YamlFrontMatterBlock>() .FirstOrDefault(); if (block == null) return new T { Markdown = markdown }; var yaml = block // this is not a mistake // we have to call .Lines 2x .Lines // StringLineGroup[] .Lines // StringLine[] .OrderByDescending(x => x.Line) .Select(x => $"{x}\n") .ToList() .Select(x => x.Replace("---", string.Empty)) .Where(x => !string.IsNullOrWhiteSpace(x)) .Aggregate((s, agg) => agg + s); var t = YamlDeserializer.Deserialize<T>(yaml); t.Markdown = markdown.Substring(block.Span.End + 1); return t; }
Die
GetContents
-Methode konvertiert eine Markdownzeichenfolge mit YAML-Metadaten im Header in den angegebenen Typ, der dieIMarkdown
-Schnittstelle implementiert. Aus der Markdownzeichenfolge wird der YAML-Header extrahiert und in den angegebenen Typ deserialisiert. Anschließend wird der Text des Artikels extrahiert und zur weiteren Verarbeitung auf dieMarkdown
-Eigenschaft festgelegt.Speichern Sie Ihre Änderungen.
Extrahieren von Markdown- und YAML-Inhalten
Implementieren Sie mit den Hilfsmethoden die -Methode, um die Extract
lokalen Markdowndateien zu laden und Informationen daraus zu extrahieren.
Innerhalb des Code-Editors:
Öffnen Sie die datei ContentService.cs .
Fügen Sie oben in der Datei die folgende using-Anweisung hinzu:
using Markdig;
Implementieren Sie als Nächstes in der
ContentService
-Klasse dieExtract
-Methode mit dem folgenden Code:static IEnumerable<Document> Extract() { var docs = new List<Document>(); var contentFolder = "content"; var baseUrl = new Uri("https://learn.microsoft.com/graph/"); var contentFolderPath = Path.Combine(Directory.GetCurrentDirectory(), contentFolder); var files = Directory.GetFiles(contentFolder, "*.md", SearchOption.AllDirectories); foreach (var file in files) { try { var contents = File.ReadAllText(file); var doc = contents.GetContents<Document>(); doc.Content = Markdown.ToHtml(doc.Markdown ?? ""); doc.RelativePath = Path.GetRelativePath(contentFolderPath, file); doc.Url = new Uri(baseUrl, doc.RelativePath!.Replace(".md", "")).ToString(); doc.IconUrl = "https://raw.githubusercontent.com/waldekmastykarz/img/main/microsoft-graph.png"; docs.Add(doc); } catch (Exception ex) { Console.WriteLine(ex.Message); } } return docs; }
Die -Methode beginnt mit dem Laden von Markdowndateien aus dem Inhaltsordner . Für jede Datei wird der Inhalt als Zeichenfolge geladen. Die Zeichenfolge wird mithilfe der zuvor in der -Klasse definierten Erweiterungsmethode in ein Objekt mit den Metadaten und inhalten konvertiert, die
GetContents
MarkdownExtensions
in separaten Eigenschaften gespeichert sind. Als Nächstes wird die Markdownzeichenfolge in HTML konvertiert. Die URL wird im Internet mithilfe des relativen Pfads der Datei erstellt. Schließlich wird der relative Pfad zur Datei gespeichert und das Objekt zur weiteren Verarbeitung einer Auflistung hinzugefügt.Speichern Sie Ihre Änderungen.
Transformieren von Inhalten in externe Elemente
Nachdem Sie den externen Inhalt gelesen haben, besteht der nächste Schritt darin, ihn in externe Elemente zu transformieren, die in Microsoft 365 geladen werden.
Beginnen Sie mit der Implementierung der GetDocId
-Methode, die eine eindeutige ID für jedes externe Element basierend auf seinem relativen Dateipfad generiert.
Innerhalb des Code-Editors:
Vergewissern Sie sich, dass Sie die ContentService.cs Datei bearbeiten.
Fügen Sie in der
ContentService
-Klasse die folgende Methode hinzu:static string GetDocId(Document doc) { var id = doc.RelativePath! .Replace(Path.DirectorySeparatorChar.ToString(), "__") .Replace(".md", ""); return id; }
Die
GetDocId
-Methode verwendet den relativen Dateipfad des Dokuments und ersetzt alle Verzeichnistrennzeichen durch einen doppelten Unterstrich. Dies ist erforderlich, da Pfadtrennzeichen in einer externen Element-ID nicht verwendet werden können.Speichern Sie Ihre Änderungen.
Implementieren Sie nun die Transform
-Methode, die Objekte, die lokale Markdowndateien darstellen, in externe Elemente von Microsoft Graph konvertiert.
Innerhalb des Code-Editors:
Vergewissern Sie sich, dass Sie sich in der ContentService.cs-Datei befinden.
Implementieren Sie die
Transform
-Methode mithilfe des folgenden Codes:static IEnumerable<ExternalItem> Transform(IEnumerable<Document> documents) { return documents.Select(doc => { var docId = GetDocId(doc); return new ExternalItem { Id = docId, Properties = new() { AdditionalData = new Dictionary<string, object> { { "title", a.Title ?? "" }, { "description", a.Description ?? "" }, { "url", new Uri(baseUrl, a.RelativePath!.Replace(".md", "")).ToString() } } }, Content = new() { Value = a.Content ?? "", Type = ExternalItemContentType.Html }, Acl = new() { new() { Type = AclType.Everyone, Value = "everyone", AccessType = AccessType.Grant } } }; }); }
Zunächst definieren Sie eine Basis-URL. Sie verwenden diese URL, um eine vollständige URL für jedes Element zu erstellen, sodass benutzer beim Anzeigen des Elements zum ursprünglichen Element navigieren können. Als Nächstes transformieren Sie jedes Element von einem
DocsArticle
in einExternalItem
. Zunächst erhalten Sie eine eindeutige ID für jedes Element basierend auf seinem relativen Dateipfad. Anschließend erstellen Sie eine neue Instanz vonExternalItem
und füllen deren Eigenschaften mit Informationen aus .DocsArticle
Anschließend legen Sie den Inhalt des Elements auf den html-Inhalt fest, der aus der lokalen Datei extrahiert wurde, und legen den Elementinhaltstyp auf HTML fest. Schließlich konfigurieren Sie die Berechtigung des Elements so, dass es für alle personen in der Organisation sichtbar ist.Speichern Sie Ihre Änderungen.
Laden externer Elemente in Microsoft 365
Der letzte Schritt der Verarbeitung des Inhalts ist das Laden der transformierten externen Elemente in Microsoft 365.
Innerhalb des Code-Editors:
Überprüfen Sie, ob Sie die ContentService.cs-Datei bearbeiten.
Implementieren Sie in der
ContentService
-Klasse dieLoad
-Methode mithilfe des folgenden Codes:static async Task Load(IEnumerable<ExternalItem> items) { foreach (var item in items) { Console.Write(string.Format("Loading item {0}...", item.Id)); try { await GraphService.Client.External .Connections[Uri.EscapeDataString(ConnectionConfiguration. ExternalConnection.Id!)] .Items[item.Id] .PutAsync(item); Console.WriteLine("DONE"); } catch (Exception ex) { Console.WriteLine("ERROR"); Console.WriteLine(ex.Message); } } }
Für jedes externe Element verwenden Sie das Microsoft Graph .NET SDK, um die Microsoft Graph-API aufzurufen und das Element hochzuladen. In der Anforderung geben Sie die ID der zuvor erstellten externen Verbindung, die ID des hochzuladenden Elements und den vollständigen Inhalt des Elements an.
Speichern Sie Ihre Änderungen.
Hinzufügen des Inhaltsladebefehls
Bevor Sie den Code testen können, müssen Sie die Konsolenanwendung mit einem Befehl erweitern, der die Logik zum Laden von Inhalten aufruft.
Innerhalb des Code-Editors:
Öffnen Sie die datei Program.cs .
Fügen Sie einen neuen Befehl hinzu, um Inhalte mithilfe des folgenden Codes zu laden:
var loadContentCommand = new Command("load-content", "Loads content into the external connection"); loadContentCommand.SetHandler(ContentService.LoadContent);
Registrieren Sie den neu definierten Befehl mit dem Stammbefehl, damit er mit dem folgenden Code aufgerufen werden kann:
rootCommand.AddCommand(loadContentCommand);
Speichern Sie Ihre Änderungen.
Testen des Codes
Als Letztes müssen Sie testen, dass der Microsoft Graph-Connector externe Inhalte ordnungsgemäß importiert.
- Öffnen Sie ein Terminal.
- Ändern Sie das Arbeitsverzeichnis in Ihr Projekt.
- Erstellen Sie das Projekt, indem Sie den
dotnet build
Befehl ausführen. - Beginnen Sie mit dem Laden des Inhalts, indem Sie den
dotnet run -- load-content
Befehl ausführen. - Warten Sie, bis der Befehl abgeschlossen ist, und laden Sie den Inhalt.