Introduction to Calling Microsoft Graph from Polyglot Notebooks (.Net Interactive)

This post is a part of Festive Tech Calendar 2022 and a follow-up to Introduction to Calling Microsoft Graph from a C# .Net Core Application from 2018.

Microsoft Graph is the unified API for any developers working with data inside Microsoft 365, Azure Active Directory (Azure AD), Windows, and more.  In this post, we’ll cover how to call Microsoft Graph from Polyglot Notebooks (part of .Net Interactive). We’ll also introduce a preview of the Microsoft Graph extension for .Net Interactive.

Background

Do you ever want to test a few lines of code, but have to write dozens of lines of support code (i.e. “boilerplate” or “basic plumbing” code)?

Microsoft Graph has a number of offerings such as quick starts to let you pick a supported code language, download a sample application, and run the project within a few minutes, but this can still take 5-30 mins depending on your level of familiarity.

Separately, there is Microsoft Graph Explorer or the Microsoft Graph Postman collection to quickly execute a query against Microsoft Graph (seconds to minutes usually), but these only execute HTTP REST endpoints and not using SDKs (which I prefer).

I’ve used 3rd party tools such as LINQPad or websites like .Net Fiddle to quickly prototype and execute Microsoft Graph SDK code but these are often disconnected experiences from where I typically develop which is Visual Studio Code.

.Net Interactive and Polyglot Notebooks

Enter .Net Interactive. .Net Interactive builds upon the Jupyter ecosystem (notebooks, kernels, server, etc.) to allow programming in a notebook fashion (executable code alongside text) but with support for multiple languages (C#, F#, JavaScript, PowerShell, SQL, and more). With this added support for multiple languages, the Visual Studio Code extension has been recently renamed to Polyglot Notebooks (previously called .Net Interactive Notebooks), but the base engine itself is still called .Net Interactive.

At a base level, Polyglot Notebooks allow you to write snippets of executable code in multiple languages alongside markdown text blocks. This is great for writing tutorials, sharing a sample of code with someone with explanation (beyond simple comments in the code), or designing a multi-step process of code blocks.

.Net Interactive is also extensible by allowing developers to create custom kernel extensions, magic commands, or script-based extensions.

Microsoft Graph extension for .Net Interactive

During a recent company hackathon event, myself, Jason Johnston, Jon Sequeira, and Diego Colombo built an initial prototype of a Microsoft Graph extension for .Net Interactive. The extension implements a magic command for #!microsoftgraph that can create and authenticate a GraphServiceClient and then binds it to a variable that can then be used in code blocks. The magic command accepts input parameters to control authentication flow, Azure AD application / tenant, Microsoft Graph API version, and more. The current repository includes support for C# (.Net) but we’re also exploring JavaScript and PowerShell in the future.

Prerequisites

There are a few prerequisites that you will need install

Getting started

After above requirements are met, you can get started by following the instructions in the GitHub repo README or the demo notebook.

Let’s take a look at a few samples.

Create a polyglot notebook

To create a new polyglot notebook, open the Command Palette(Ctrl+Shift+P) on Windows or (Cmd+Shift+P) on MacOS, and select Polyglot Notebook: Create new blank notebook. You can also create a new notebook with Ctrl+Shift+Alt+N key combination on Windows.

Build the NuGet package

After forking the repository, navigate to the source directory and run the following command (or execute in a PowerShell code block inside the notebook) to generate a NuGet package which we will then import in the next steps.

dotnet build ./src/Microsoft.DotNet.Interactive.MicrosoftGraph.csproj

Import the NuGet package

After the NuGet package has been built, run the following commands (be sure to replace <REPLACE_WITH_WORKING_DIRECTORY> with the actual directory location) in a C# script block in the notebook to import the NuGet package.

#i nuget:<REPLACE_WITH_WORKING_DIRECTORY>\src\bin\Debug\
#r "nuget:Microsoft.DotNet.Interactive.MicrosoftGraph,*-*"

Help example

Executing the #!microsoftgraph magic command with -h or –help will display the syntax and parameters available for input. Note that options are available with full name (two dashes “–“) or aliases (one dash “-“).

#!microsoftgraph -h

Create client

The following creates an instance of a GraphServiceClient with variable name “deviceCodeClient” using the device code authentication flow. Be sure to replace the input parameters for “YOUR_TENANT_ID” and “YOUR_CLIENT_ID”.

#!microsoftgraph -t "YOUR_TENANT_ID" -c "YOUR_CLIENT_ID" -a DeviceCode -n deviceCodeClient

Since we used -n to name the GraphServiceClient instance that is created, we can now use that variable going forward to make requests.

Make requests

Now you can execute Microsoft Graph .Net SDK code using the deviceCodeClient GraphServiceClient just created. We will be prompted to complete the device code authentication flow at this time. Follow the prompt and provide the device code provided.

var me = await deviceCodeClient.Me.GetAsync();
Console.WriteLine($"Me: {me.DisplayName}, {me.UserPrincipalName}");

Live demo

Recently Jason Johnston and I joined the M365 platform community call to give an overview and demo of the Microsoft Graph extension for .Net Interactive. If you want to skip to just the demo, jump to 8:28 timestamp in the video to see things in action.

Conclusion

As you can see, the Microsoft Graph extension for .Net Interactive offers a way to write code and text side by side. There are many scenarios that can benefit from this such as workshop tutorials, exploring the SDKs, prototyping solutions, and more. We welcome your input on feature requests, contributions, raising bugs, etc. Please submit issues or pull requests to the GitHub repository and we will review. Thanks and enjoy!

-Frog Out

Resources

Interactive C# with Polyglot Notebooks (good introduction to getting started with Polyglot Notebooks in .Net Interactive)
https://newdevsguide.com/2022/12/14/polyglot-notebooks-csharp/

What are you working on? (share early and often)

Hands working on clay project

I’ve always enjoyed “Show and Tell Fridays”, “Brown bag sessions” (i.e. bring your lunch and a presenter shares about a topic), and hackathons to see what cool things my peers are working on. Not only do I get to see / hear interesting projects and solutions they are building, it also sparks creativity in me to work on my own projects.

During our September 2022 company-wide hackathon I had the opportunity to collaborate with folks from multiple areas of Microsoft (Teams, Outlook, .Net Interactive, M365 Profile, and more) on interesting projects. What was really interesting to me is that 2 of these projects started via tweets on Twitter. A random message from myself was picked up by one engineering team for 1 project and a thread from a peer about “wouldn’t it be cool if…” started another project.

Ultimately, I highly recommend that you take the time to share early and share often your ideas, interests, side projects, and more. You never know how that may lead you and your peers to build the next innovative product / feature / etc.

For those interested, here is a link to one of the hackathon projects I worked on for a “Microsoft Graph extension for .Net Interactive”. For those unfamiliar, .Net Interactive Notebooks allow you to mix text (Markdown) and runnable code snippets (multiple languages supported) in a notebook style format. This custom extension allows authenticating to Microsoft Graph via 3 different authentication flows (possibly more to come) and run Microsoft Graph SDK queries easily.

I’ll be sharing more about this on my blog, M365 platform community call, and a few other places as it continues to develop. For now follow / star / fork / etc. the GitHub repo for more updates.

Microsoft Graph extension for .NET Interactive Notebooks
https://github.com/microsoftgraph/msgraph-dotnet-interactive-extension

-Frog Out

Windows Equivalent of Linux or Unix “Touch” Command

In Linux and Unix there is a “touch” command which will update the timestamp of a file without modifying the contents.  You can also create an empty file without having to open an application among other actions.  In Windows there isn’t a direct equivalent, but you can get close by using the “copy” command with a “+” at the end of the filename while specifying no destination file.  The + symbol points the copy operation back to the source file.  This will update the timestamp while not modifying the contents of the file.

Ex.

copy SampleFile.txt+

WindowsEquivTouch1

WindowsEquivTouch2

This process was helpful for my customer testing out automated CI/CD processes with Azure DevOps and Git.  Hopefully this will be useful to someone else.  Enjoy.

 

-Frog Out

Introduction to Calling Microsoft Graph from a C# .Net Core Application

This post is a part of The Second Annual C# Advent.

Microsoft Graph is the unified API for any developers working with data inside Office 365, Azure Active Directory (Azure AD), Windows 10, and more.  In this post we’ll cover a quick introduction and share resources from 30 Days of Microsoft Graph blog series to show how to authenticate and to make calls against Microsoft Graph with C# and .Net Core (v2.1 as of the time of writing.)  Each of the referenced articles aims to take 5-15 mins to get you up to speed as quickly as possible while also providing hands-on exercises.  If you’d like to skip the background reading and start from scratch building a .Net Core console application that calls Microsoft Graph read through the README for the base-console-app within dotnetcore-console-sample.

<Update 2019-10-07>Thanks to reader John Guilbert for pointing out that the sample code using MSAL .Net 2.x has deprecated certain APIs.  I’ve updated the sample code to reflect MSAL .Net 4.x.</Update>

Microsoft Graph overview

Microsoft Graph offers developers (and IT pros / admins) the ability to access data and insights in a number of services within Microsoft 365 services.  This includes:

  • Azure AD
  • Office 365 services
    • SharePoint
    • OneDrive
    • Outlook/Exchange
    • Microsoft Teams
    • OneNote
    • Planner
    • Excel
  • Enterprise Mobility and Security services
    • Identity Manager
    • Intune
    • Advanced Threat Analytics
    • Advanced Threat Protection
  • Windows 10 services
    • Activities
    • Devices
  • Education

By providing a unified endpoint for accessing all of these services Microsoft Graph removes a number of barriers including:

  • Discovering the service-specific endpoint URL
  • Authenticating to each endpoint separately
  • Managing different permission models
  • Working with incompatible data formats
  • …and more

All requests made to Microsoft Graph are sent as REST calls to https://graph.microsoft.com and leverage a common authentication model based on Azure AD and OAuth permissions along with a consent framework for users or admins.  The quickest way to see Microsoft Graph requests in action is to navigate to the Microsoft Graph explorer (https://aka.ms/ge, ge = Graph Explorer.)  For more information on using Graph Explorer please read Day 3 – Graph Explorer from the 30 Days of Microsoft Graph series.  Additionally you can make requests against Microsoft Graph using API development tools such as Postman.  Please read Day 13 – Postman to make Microsoft Graph requests for more information on using PostMan with Microsoft Graph.

 

Getting started sample

Seeing requests and their responses in a browser or tool is useful, but making requests in code or scripts is the more common scenario for usage.  In the examples below we will cover C# and .Net Core as .Net Core is available cross-platform, can be built in Visual Studio Code (also cross-platform), and offers many hosting options (console app, web app, serverless functions, and more.)

Authentication

All requests to Microsoft Graph require an authenticated context, either delegated or app-only.  Delegated is a union of the logged-in user’s context along with the application’s context.  App-only (as the name implies) is only the application’s context without any user involvement.  Please read Day 8 – Authentication roadmap and access tokens and Day 9 – Azure AD applications  on V2 endpoint for more information about creating an Azure AD application and getting an authenticated context.  On a similar note, you are highly encouraged to leverage Microsoft Authentication Library (MSAL) for creating your authentication context as this is the forward-focused version as opposed to the older Active Directory Authentication Library (ADAL).

Microsoft Graph SDK

While it is entirely possible to call the Microsoft Graph with an HttpClient (or similar) object, the Azure AD Identity and Microsoft Graph product groups recommend leveraging the Microsoft Graph SDK (Microsoft.Graph on Nuget.)  This SDK provides a number of benefits including:

  • Strongly typed entities and Microsoft Graph responses
  • Fluent API syntax
  • …and more

In future releases Microsoft Graph SDK will also provide abstractions for authentication prerequisites, automatic handling of retry logic or error handling, and more.

Sample solution

As mentioned at the beginning of this post if you’d like to build a working application from scratch (or clone the repo and configure the necessary settings) you can find the base-console-app within dotnetcore-console-sample.  Extracting the bare essential lines of code from this sample results in the following for authenticating to Microsoft Graph.

Note: If you do not see the below Gist please refer to code at this location: CS-Graph_Prepare_GraphServiceClient.cs

https://gist.github.com/BrianTJackett/3c629bca714325440cffce73e6b3bf56.js


var clientId = "<AzureADAppClientId>";
var clientSecret = "<AzureADAppClientSecret>";
var redirectUri = "<AzureADAppRedirectUri>";
var authority = "https://login.microsoftonline.com/<AzureADAppTenantId>/v2.0";
var cca = ConfidentialClientApplicationBuilder.Create(clientId)
.WithAuthority(authority)
.WithRedirectUri(redirectUri)
.WithClientSecret(clientSecret)
.Build();
// use the default permissions assigned from within the Azure AD app registration portal
List<string> scopes = new List<string>();
scopes.Add("https://graph.microsoft.com/.default");
var authenticationProvider = new MsalAuthenticationProvider(cca, scopes.ToArray());
GraphServiceClient graphClient = new GraphServiceClient(authenticationProvider);

The following class implements the IAuthenticationProvider interface used for retrieving and then adding an Azure AD access token to subsequent requests to Microsoft Graph.  An out of the box implementation of this class will be provided at a later date within the Graph SDK.

Note: If you do not see the below Gist please refer to code at this location: CS-Graph_Class_MsalAuthenticationProvider.cs


public class MsalAuthenticationProvider : IAuthenticationProvider
{
private IConfidentialClientApplication _clientApplication;
private string[] _scopes;
public MsalAuthenticationProvider(IConfidentialClientApplication clientApplication, string[] scopes) {
_clientApplication = clientApplication;
_scopes = scopes;
}
public async Task AuthenticateRequestAsync(HttpRequestMessage request)
{
var token = await GetTokenAsync();
request.Headers.Authorization = new AuthenticationHeaderValue("bearer", token);
}
public async Task<string> GetTokenAsync()
{
AuthenticationResult authResult = null;
authResult = await _clientApplication.AcquireTokenForClient(_scopes).ExecuteAsync();
return authResult.AccessToken;
}
}

https://gist.github.com/BrianTJackett/c69c1991eac2b3f5a76996d17223299a.js

Finally make a sample request to get a list of users within the Azure AD domain by calling Microsoft Graph.

Note: If you do not see the below Gist please refer to code at this location: CS-Graph_Request_Users_GraphServiceClient.cs


var graphResult = graphClient.Users.Request().GetAsync().Result;
Console.WriteLine(graphResult[0].DisplayName);

Conclusion

In this blog post we covered a quick introduction of Microsoft Graph and linked to additional resource within the 30 Days of Microsoft Graph blog series for additional background reading.  We also covered a barebones implementation of calling Microsoft Graph in a C# .Net Core console application.  Full instructions can be found on the base-console-app within dotnetcore-console-sample.  Thank you for reading along and please open an issue on GitHub repo if you run into any issues with the sample project.  Enjoy the rest of The Second Annual C# Advent.

 

-Frog Out

How To Edit Microsoft Documentation on GitHub

Recently I’ve been reading a lot of Microsoft official documentation, much of which has moved to hosting on GitHub.  If you didn’t know this move to GitHub also opens up the opportunity for anyone from the community to propose updates to the documentation through the GitHub pull request process.  This post will walk through the steps to make an edit of the documentation and submit a pull request.  Note this is not the only process to accomplish this but one that I’ve used with success recently.

Background

Additional resources for background on creating pull requests.

Creating a pull request
https://help.github.com/articles/creating-a-pull-request/

About pull requests
https://help.github.com/articles/about-pull-requests/

 

GitHub Pull Request Process

First ensure that you have a GitHub account (free or paid) that you can login to GItHub.com.

Signing up for a new GitHub account

https://help.github.com/articles/signing-up-for-a-new-github-account/

Next navigate to the documentation page you want to update (usually on the docs.microsoft.com domain).  Click the “Edit” button in upper right corner.

MSDocOnGitHub1

This will redirect you over to the underlying GitHub page where that file is sourced from.  Click the “pencil” icon to edit the file in question.

MSDocOnGitHub2

Make edits to the file as needed.

MSDocOnGitHub3

At the bottom of the page fill out a title and description for the file commit being proposed.  Click “Propose file change”.

MSDocOnGitHub4

You’ll see a summary of the commit being proposed with additions or deletions to the file at bottom.  Up top you can see which branch changes are coming from (yours) on the right and the branch to submit them to on the left (usually “master”).  Click “Create pull request” when ready.

MSDocOnGitHub5

You’ll be presented with a last page (not shown here) for the pull request prior to submitting.  Once submitted you should see the active pull request page with details about the checks being run and any comments from the approvers.  Here is an example of one that I submitted a few days ago.  Notice the “All check have passed” at bottom where a number of background checks run before the approvers even see the pull request.

MSDocOnGitHub6

 

Additional Resources

Microsoft Docs contributor guide overview
https://docs.microsoft.com/en-us/contribute

If you are editing a large number of files or want to work on them locally I would recommend installing the Docs Authoring Pack extension in Visual Studio Code.

Docs Authoring Pack for VS Code
https://docs.microsoft.com/en-us/contribute/how-to-write-docs-auth-pack

 

Conclusion

Hopefully after reading through this process you feel capable of making edits to official Microsoft documentation on GitHub and submitting pull requests.  Happy editing and share your knowledge with the world.

-Frog Out

Getting Started with ProcMon for Troubleshooting Long Running Processes

   In this post I will cover a few tips for getting started with using ProcMon (Process Monitor in the Sysinternals Suite) for troubleshooting long running processes.  Note that I am not an expert in ProcMon by a long shot, so this is more of a selfish post to remind myself of some key settings to be sure to configure.

   Side note.  You can run the Sysinternals tools from the web at Sysinternals Live without needing to download the tools to your local machine.  This is useful if your customer / organization doesn’t allow installing / running 3rd party tools or has concerns about running them directly on a machine.

 

Background

   Skip down to the Tips section if you don’t want to read the back story.

   At least once a month I have a customer scenario where two or more applications are not playing nice with each other.  A .Net website and anti-virus software, SharePoint and server backup software, etc.  Usually the problem involves one piece of software placing a write-lock or exclusive hold on a file / registry entry while the other software expects the same.  In such a scenario we need to monitor a file / registry entry from a fresh start (restart application pool, process, etc.) until the file / registry access error happens which could be hours or days.  Since we are monitoring for such a long time we want to make sure that ProcMon only captures the data that we need as well as be mindful of memory / disk space usage.

 

Tips

1) Start ProcMon with no tracing

   If you start up ProcMon by double clicking the executable ProcMon will start capturing data immediately.  Instead launch it from the command line with the /noconnect parameter.

c:sysinternals> procmon /noconnect

 

2) Specify a backing file

    By default ProcMon will store event data in virtual memory.  Since we could capturing hours or days worth of data it might be preferred to store that to a disk with lots of free space (multiple GBs or more depending on expected duration and number of events). 

   Navigate to File –> Backing Files… for these settings.

ProcMonTips1

 

   Change the radio button from “Use virtual memory” to “Use file named:” and then specify the filename you would like to use as a backing file.  .PML is the default extension used so I followed that convention.

ProcMonTips2

 

3) Apply filters

    By default all processes accessing any files and / or registry locations will be monitored.  Instead we want to filter events based on our criteria.  The most common scenarios that I run into (in order that I see them) are 1) filtering for location when we don’t know the process that is locking it or 2) filtering for a specific process when we know the process but not the location that is being locked.

   Click on the filter icon in the top menu or click Filter –> Filter… to access these settings.

ProcMonTips3

 

    In the example below we filter for any path that begins with “c:MyAppFolder”.  By doing this we include any subfolders of our application folder.

ProcMonTips4

 

4) Drop filtered events

   By default ProcMon will capture all events whether they are filtered or not.  To save on memory (or file space if you use a backing file) you can drop filtered events.  There is a chance that if you created your filter incorrectly you may miss the events needed for troubleshooting but by keeping your filter broad enough that shouldn’t be an issue.

   Click on Filter and select the Drop Filtered Events menu item.  If there is a check mark next to the menu item then you have correctly configured ProcMon to drop filtered events.

ProcMonTips5

 

Conclusion

   In this post I walked through a few quick tips for configuring ProcMon when you need to troubleshoot a long running process.  Hopefully these tips will help you avoid out of memory issues or having to parse through hundreds of thousands of events.

 

    Special thanks to my peer and teammate Ken Kilty for providing the research and background info for this blog post.

 

       -Frog Out