Skip to content
Petkir Blog
XLinkedinBluesky

The Christkind's - Enhancing Knowledge Access with Graph Connectors

Code, Copilot, M365, Xmas20248 min read

Story

After the productive meeting with Santa, the Christkind realized that addressing the challenges of sourcing detailed information for specialized parts required a more streamlined approach. The suggestions from Santa were spot on; the Christkind, too, struggled with finding precise data within the vast expanse of documents and notes accumulated over the years. The answer lay in integrating Microsoft Graph Connectors to connect external knowledge sources, particularly a wiki containing construction plans and descriptions.

The Christkind had always envisioned a system that could easily pull in critical information from various repositories, and this was the perfect opportunity to bring that vision to life. With the power of Microsoft Graph, it could connect to the wiki, enabling the elves to access the necessary construction plans and detailed descriptions of uncommon parts directly within their workflow.

Implementation Steps for the Graph Connector

Identify the External Data Source

  • The Christkind pinpointed the wiki as the primary data source, which housed valuable information on manufacturing processes and part specifications.

Configure the Graph Connector

  • With guidance from the elves, the Christkind set up the Graph Connector to establish a secure connection to the wiki. This involved defining the API endpoints and ensuring that the data structure matched the needs of the production team.

Index the Data

  • Once the connector was configured, the Christkind initiated a data indexing process to ensure that the relevant articles and documents from the wiki were searchable. This included construction plans and explanations for specialized parts.

Create a Search Experience

  • To make access easy for the elves, the Christkind collaborated with the IT team to develop a user-friendly interface within Microsoft Teams. This interface would allow the elves to query the wiki directly for information while working on their tasks.

Testing

  • The Christkind conducted testing sessions with the elves to gather feedback on the functionality of the Graph Connector. This was essential to ensure that the search results were relevant and the integration truly met their needs.

Excitement in the Workshop

As the integration came to life, the Christkind felt a renewed sense of excitement in the workshop. The elves no longer had to dig through stacks of paper or scroll endlessly through digital documents to find critical information. Instead, they could now simply type their queries and access the needed plans and specifications instantly.

With the knowledge of specialized parts at their fingertips, the elves felt empowered to enhance their production processes. They could now craft and order the right components efficiently, ensuring that no child’s wish would go unfulfilled.

The Christkind watched with pride as the workshop buzzed with activity, knowing that it had taken a significant step forward in creating a more connected and informed environment for everyone. The holiday season was shaping up to be the most efficient yet!

Implementation of the Graph Connector

Starting with a simple C# Console Application for the first try is enough to get things moving.

  • Create a new C# Console Application project in Visual Studio.
  • Add the necessary NuGet packages for Microsoft Graph and authentication.

The data source for this implementation consists of simple HTML files that contain the necessary information.

<html>
<head>
<title>Wiki Document1</title>
</head>
<body>
<h1>Wiki Document1</h1>
<p>Summary of the Document</p>
<h2>Material</h2>
<p>
...
</p>
<h2>Preperation</h2>
<p>
...
</p>
...
</body>
</html>

Configure Authentication

Go to the Entra Portal and register a new application. This involves setting up the necessary permissions and configuring either a certificate or a client secret for authentication. While using a certificate is generally more secure, a client secret can also be used for simplicity.

Here are the steps to register the application:

  • Navigate to the Entra Portal: Open the Entra Portal and go to the "App registrations" section.
  • Register a New Application: Click on "New registration" and fill in the required details.
  • Configure API Permissions (Application): After registering the application, go to the "API permissions" section and add the necessary Microsoft Graph permissions. Ensure you include permissions like ExternalConnection.ReadWrite.OwnedBy and ExternalItem.ReadWrite.OwnedBy. This is enough currently for this use case.
  • Set Up Authentication:
    • Certificate: If you choose to use a certificate, upload the certificate in the "Certificates & secrets" section.
    • Client Secret: If you prefer to use a client secret, generate a new client secret in the "Certificates & secrets" section and note it down as it will be used in your application.

Here is a screenshot showing the permissions configuration: Entra ID Registration

Connect to Microsoft Graph in C#

// Initialize the Graph client
var clientId = "YOUR_CLIENT_ID";
var tenantId = "YOUR_TENANT_ID";
var clientSecret = "YOUR_CLIENT_SECRET";
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithTenantId(tenantId)
.WithClientSecret(clientSecret)
.Build();
ClientCredentialProvider authProvider = new ClientCredentialProvider(confidentialClientApplication);
GraphServiceClient graphClient = new GraphServiceClient(authProvider);

Connect, and Define the Schema

Console.WriteLine("Check if External Connection exists");
if (await CheckConnection(connectionSettings))
{
Console.WriteLine("External Connection exists");
}
else
{
ExternalConnection connection = await CreateConnection(connectionSettings);
if (connection == null)
{
Console.WriteLine("External Connection not created");
return;
}
await RegisterSchemaAsync(connection);
Console.WriteLine("External Connection created and Schema created");
}
Console.WriteLine("Get HTML Files");

Register the External Connection in Graph

var newConnection = new ExternalConnection
{
Id = connectionSettings.Id,
Name = connectionSettings.Name,
Description = connectionSettings.Description,
};
return await graphClient.External.Connections.PostAsync(newConnection);

The Basic Structure of an External Item Schema for Graph

var schema = new Schema
{
BaseType = "microsoft.graph.externalItem",
Properties = new List<Property>
{
new Property { Name = "name", Type = PropertyType.String, IsQueryable = true, IsSearchable = true, IsRetrievable = true, IsRefinable = false, Labels = new List<Label?>() { Label.Title }},
new Property { Name = "description", Type = PropertyType.String, IsQueryable = false, IsSearchable = true, IsRetrievable = true, IsRefinable = false },
new Property { Name = "filename", Type = PropertyType.String, IsQueryable = false, IsSearchable = true, IsRetrievable = true, IsRefinable = false,Labels=new List<Label?>(){Label.FileName } },
new Property { Name = "fileExtension", Type = PropertyType.String, IsQueryable = false, IsSearchable = true, IsRetrievable = true, IsRefinable = false,Labels=new List<Label?>(){Label.FileExtension } },
new Property { Name = "url", Type = PropertyType.String, IsQueryable = false, IsSearchable = true, IsRetrievable = true, IsRefinable = false,Labels=new List<Label?>(){Label.Url } },
new Property { Name = "iconUrl", Type = PropertyType.String, IsQueryable = false, IsSearchable = true, IsRetrievable = true, IsRefinable = false,Labels=new List<Label?>(){Label.IconUrl } },
},
};
await GraphHelper.RegisterSchemaAsync(currentConnection.Id, schema);

Read HTML Files and Extract the Informations

here is the Code Block

List<ResponsePage> items = new List<ResponsePage>();
Directory.EnumerateFiles("../../../../../html", "1_*.html").OrderBy(f => f).ToList()
.ForEach((fileName) =>
{
Console.WriteLine($"Process {fileName}");
Console.WriteLine("Load HTML (Extract)");
var fileContent = File.ReadAllText(fileName);
Console.WriteLine("Load HTML (Transform)");
ResponsePage value = ExtractHTML.ExtractHTML(fileContent);
value.Key = ExtractHTML.GetHash(fileName);
var info=new FileInfo(fileName);
value.CreatedDateTime=info.CreationTimeUtc;
value.FileName=info.Name;
value.FileExtension=info.Extension;
value.Url = $"https://mysecureurl.cubido.at/{fileName}";
items.Add(value);
});

Create External Items and Upload it

This is the minimal Graph Item with an ACL that grants access to everyone. To modify the grant access take a look to the ACL section to a specific user or group.

var extItem = new ExternalItem
{
Id = item.Key,
Content = new ExternalItemContent
{
Type = ExternalItemContentType.Html,
Value = item.HTML
},
Acl = new List<Acl>
{
new Acl
{
AccessType = AccessType.Grant,
Type = AclType.Everyone,
Value = "everyone"//settings.TenantId,
/*
Type = AclType.User, Value = UserGuid
Type = AclType.Group, Value = GroupGuid
*/
}
},
Properties = new Properties
{
AdditionalData = new Dictionary<string, object>
{
{ "name", item.Title },
{ "description", item.Body } ,
{ "filename",item.FileName },
{ "fileExtension",item.FileExtension },
{ "url",item.Url },
{ "iconUrl",item.IconUrl }
}
},
};
await GraphHelper.AddOrUpdateItemAsync(connectionSettings.Id, extItem);

Show the Connector in the Portal

M365 Admin Portal Search and intelligence

Previously, the item limitation was quite restrictive, with only a few thousand items included and 500 items per E5 licensed user. Now, with the new update, your tenant supports up to 50 million items of index quota at no additional cost. This is a significant enhancement, especially for integrating Microsoft 365 experiences, including Copilot!

Great news 🎉 Your tenant now supports 50 million items of index quota to enhance Microsoft 365 experiences (including Copilot!) at no additional cost.

You can see your registration and connection name.

Customize the Result Type Layout

With a few clicks, you can change the layout of the search results. M365 Admin Portal Search and Intelligence

You can use the Search Layout Designer to make these changes.

M365 Search Layout Designer

Output of Microsoft Copilot

On the bottom left side, you can see the link to the external item. M365 Search Layout Designer

Remark

The Christkind marveled at how straightforward it was to integrate the items into M365 Search and Copilot. It wondered why this hadn't been done sooner.

Links

XMAS 2024 Overview