Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ServiceCollectionExtensions, Sample Application, Documentation, Service convenience work #4

Merged
merged 4 commits into from
May 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -396,3 +396,4 @@ FodyWeavers.xsd

# JetBrains Rider
*.sln.iml
sample/Atc.Microsoft.Graph.Client.Sample/appsettings.Development.json
7 changes: 7 additions & 0 deletions Atc.Microsoft.Graph.Client.sln
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{67FE0C
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Atc.Microsoft.Graph.Client", "src\Atc.Microsoft.Graph.Client\Atc.Microsoft.Graph.Client.csproj", "{E0C8319E-49CC-4A55-B356-986320EBF055}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Atc.Microsoft.Graph.Client.Sample", "sample\Atc.Microsoft.Graph.Client.Sample\Atc.Microsoft.Graph.Client.Sample.csproj", "{C742D749-CA38-4D8B-9FDB-5F3A35214D78}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -26,12 +28,17 @@ Global
{E0C8319E-49CC-4A55-B356-986320EBF055}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E0C8319E-49CC-4A55-B356-986320EBF055}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E0C8319E-49CC-4A55-B356-986320EBF055}.Release|Any CPU.Build.0 = Release|Any CPU
{C742D749-CA38-4D8B-9FDB-5F3A35214D78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C742D749-CA38-4D8B-9FDB-5F3A35214D78}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C742D749-CA38-4D8B-9FDB-5F3A35214D78}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C742D749-CA38-4D8B-9FDB-5F3A35214D78}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{E0C8319E-49CC-4A55-B356-986320EBF055} = {69C84246-AA75-43E8-94B2-66FD555B18B0}
{C742D749-CA38-4D8B-9FDB-5F3A35214D78} = {67FE0C20-D944-47C5-A64E-AC05F7438940}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {04120463-05C5-417B-8D7A-2D7D35B71A07}
Expand Down
85 changes: 82 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,91 @@

The library provides a convenient abstraction layer over the Microsoft Graph SDK, simplifying interactions with Microsoft Graph APIs. By wrapping the Microsoft Graph SDK, the library offers a consistent and simplified interface, handling complexities like paging and error handling for you.

# Table of Content
# Table of Contents

- [Introduction](#introduction)
- [Table of Content](#table-of-content)
- [Table of Contents](#table-of-contents)
- [Atc.Microsoft.Graph.Client](#atcmicrosoftgraphclient)
- [Services](#services)
- [OneDriveGraphService](#onedrivegraphservice)
- [OutlookGraphService](#outlookgraphservice)
- [SharepointGraphService](#sharepointgraphservice)
- [TeamsGraphService](#teamsgraphservice)
- [UsersGraphService](#usersgraphservice)
- [Wire-Up Using ServiceCollection Extensions](#wire-up-using-servicecollection-extensions)
- [Options Available in the Extensions Class](#options-available-in-the-extensions-class)
- [Setup with ServiceCollection](#setup-with-servicecollection)
- [Sample Project](#sample-project)
- [Requirements](#requirements)
- [How to contribute](#how-to-contribute)
- [How to Contribute](#how-to-contribute)

# Atc.Microsoft.Graph.Client

[![NuGet Version](https://img.shields.io/nuget/v/atc.microsoft.graph.client.svg?logo=nuget&style=for-the-badge)](https://www.nuget.org/packages/atc.microsoft.graph.client)

## Services

The services provided in the `Atc.Microsoft.Graph.Client` package are designed to facilitate seamless interaction with various Microsoft services through the Graph API. These services are essential for applications that need to manage and retrieve data efficiently from OneDrive, Outlook, SharePoint, Teams, User Management etc. By leveraging these services, applications can ensure robust and secure handling of data, integrating comprehensive functionalities directly into the application's workflow. Each service supports efficient querying of data, supporting expand, filter, and select query parameters to tailor the data retrieval process.

### OneDriveGraphService

The `IOneDriveGraphService` is essential for applications that require efficient management of OneDrive resources, including retrieving and managing drives and drive items, tracking changes with delta tokens, and downloading files. This service ensures robust and secure handling of OneDrive data, integrating OneDrive capabilities directly into the application's workflow.

### OutlookGraphService

The `IOutlookGraphService` is essential for applications that need to manage and retrieve Outlook mail data, such as mail folders, messages, and file attachments. It enables efficient querying of mail folders and messages, supports the use of delta tokens for tracking changes, and ensures secure handling of email data, enhancing email management within the application's ecosystem.

### SharepointGraphService

The `ISharepointGraphService` is essential for applications that need to manage SharePoint sites and subscriptions effectively. It provides capabilities for retrieving site information, setting up and managing subscriptions, and handling subscription renewals and deletions, ensuring robust and efficient integration of SharePoint functionalities within the application's environment.

### `TeamsGraphService`

The ITeamsGraphService is essential for applications that need to retrieve and manage information about Teams. It allows for efficient querying of Teams data, enhancing collaboration and communication capabilities within the application's ecosystem.

### UsersGraphService

The `IUsersGraphService` is essential for applications that need to retrieve and manage information about users. It allows for efficient querying of user data, ensuring robust and efficient integration of user management functionalities within the application's environment.

## Wire-Up Using ServiceCollection Extensions

To seamlessly integrate the Graph services into your application, you can utilize the provided [`ServiceCollection`](src/Atc.Microsoft.Graph.Client/Extensions/ServiceCollectionExtensions.cs) extension methods. These methods simplify the setup process and ensure that the Graph services are correctly configured and ready to use within your application's service architecture.

The methods ensure that the Graph services are added to the application's service collection and configured according to the specified parameters, making them available throughout your application via dependency injection.

The configuration example below utilize the application's settings (typically defined in appsettings.json) to configure the Graph Services by calling the overload that accepts `GraphServiceOptions` and implicitly configures the GraphServiceClient utilizing a ClientSecretCredential.

### Options Available in the Extensions Class
The `ServiceCollectionExtensions` class provides several methods to add and configure the Graph services in your application:

- AddMicrosoftGraphServices(GraphServiceClient? graphServiceClient = null)
> Adds the GraphServiceClient to the service collection, optionally using a provided GraphServiceClient instance. If no instance is provided, one must be available in the service provider when this service is resolved.

- AddMicrosoftGraphServices(TokenCredential tokenCredential, string[]? scopes = null)
> Adds the GraphServiceClient to the service collection using the provided TokenCredential for authentication. Optional scopes can also be specified.

- AddMicrosoftGraphServices(GraphServiceOptions graphServiceOptions, string[]? scopes = null)
> Adds the GraphServiceClient to the service collection using the provided GraphServiceOptions. This method ensures the GraphServiceClient is configured with a ClientSecretCredential based on the specified options.

### Setup with ServiceCollection

```csharp
public void ConfigureServices(IServiceCollection services)
{
var graphServiceOptions = new GraphServiceOptions
{
TenantId = "your_tenant_id",
ClientId = "your_client_id",
ClientSecret = "your_client_secret",
};

services.AddMicrosoftGraphServices(graphServiceOptions);
}
```

# Sample Project

A [sample](sample/Atc.Microsoft.Graph.Client.Sample/Program.cs) is included, demonstrating how to configure and use the Microsoft Graph services.

# Requirements

Expand Down
4 changes: 3 additions & 1 deletion sample/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,6 @@ dotnet_diagnostic.S1075.severity = none # Refactor your code not to

##########################################
# Custom - Code Analyzers Rules
##########################################
##########################################

dotnet_diagnostic.CA1303.severity = none #
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Atc.Microsoft.Graph.Client\Atc.Microsoft.Graph.Client.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="appsettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
7 changes: 7 additions & 0 deletions sample/Atc.Microsoft.Graph.Client.Sample/GlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
global using System.Net;
global using Atc.Microsoft.Graph.Client.Extensions;
global using Atc.Microsoft.Graph.Client.Options;
global using Atc.Microsoft.Graph.Client.Services.Sharepoint;
global using Microsoft.Extensions.Configuration;
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.Logging;
39 changes: 39 additions & 0 deletions sample/Atc.Microsoft.Graph.Client.Sample/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// ReSharper disable StringLiteralTypo
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile("appsettings.Development.json", optional: false, reloadOnChange: true)
.Build();

var services = new ServiceCollection();

services.AddLogging(configure => configure.AddConsole());

var graphServiceOptions = new GraphServiceOptions();
configuration.GetRequiredSection("GraphServiceOptions").Bind(graphServiceOptions);

services.AddMicrosoftGraphServices(graphServiceOptions);

var serviceProvider = services.BuildServiceProvider();

var sharepointService = serviceProvider.GetRequiredService<ISharepointGraphService>();

using var cts = new CancellationTokenSource();

var (statusCode, sites) = await sharepointService.GetSites(
selectQueryParameters: ["id", "webUrl", "isPersonalSite"],
cancellationToken: cts.Token);

if (statusCode != HttpStatusCode.OK)
{
Console.WriteLine("Failed to retrieve sites.");
return;
}

foreach (var site in sites)
{
Console.WriteLine($"SiteId: {site.Id}");
Console.WriteLine($"WebUrl: {site.WebUrl}");
Console.WriteLine($"IsPersonalSite: {site.IsPersonalSite}");
Console.WriteLine("--------------------------------------");
}
7 changes: 7 additions & 0 deletions sample/Atc.Microsoft.Graph.Client.Sample/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"GraphServiceOptions": {
"TenantId": "<fill_out>",
"ClientId": "<fill_out>",
"ClientSecret": "<fill_out>"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,15 @@ private static void AddGraphService<TService, TImplementation>(
where TService : class
where TImplementation : GraphServiceClientWrapper, TService
{
services.AddSingleton<TService, TImplementation>(s => (TImplementation)Activator.CreateInstance(
typeof(TImplementation),
s.GetRequiredService<ILoggerFactory>(),
s.GetRequiredService<GraphServiceClient>())!);
services.AddSingleton<TService, TImplementation>(s =>
{
var loggerFactory = s.GetService<ILoggerFactory>() ?? new NullLoggerFactory();
var graphServiceClient = s.GetRequiredService<GraphServiceClient>();

return (TImplementation)Activator.CreateInstance(
typeof(TImplementation),
loggerFactory,
graphServiceClient)!;
});
}
}
1 change: 1 addition & 0 deletions src/Atc.Microsoft.Graph.Client/GlobalUsings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
global using Azure.Identity;
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.Logging;
global using Microsoft.Extensions.Logging.Abstractions;
global using Microsoft.Graph;
global using Microsoft.Graph.Drives.Item.List.Items;
global using Microsoft.Graph.Models;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ public interface IOneDriveGraphService
{
Task<(HttpStatusCode StatusCode, IList<Drive> Data)> GetDrivesBySiteId(
Guid siteId,
List<string>? expandQueryParameters,
string? filterQueryParameter,
List<string>? selectQueryParameters,
List<string>? expandQueryParameters = null,
string? filterQueryParameter = null,
List<string>? selectQueryParameters = null,
CancellationToken cancellationToken = default);

Task<Drive?> GetDriveByTeamId(
Expand All @@ -19,16 +19,16 @@ public interface IOneDriveGraphService

Task<(HttpStatusCode StatusCode, IList<DriveItem> Data)> GetDriveItemsByDriveId(
string driveId,
List<string>? expandQueryParameters,
string? filterQueryParameter,
List<string>? selectQueryParameters,
List<string>? expandQueryParameters = null,
string? filterQueryParameter = null,
List<string>? selectQueryParameters = null,
CancellationToken cancellationToken = default);

Task<(HttpStatusCode StatusCode, IList<DriveItem> Data)> GetDriveItemsByDriveIdAndDeltaToken(
string driveId,
string deltaToken,
string? filterQueryParameter,
List<string>? selectQueryParameters,
string? filterQueryParameter = null,
List<string>? selectQueryParameters = null,
CancellationToken cancellationToken = default);

Task<Stream?> DownloadFile(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ public OneDriveGraphService(

public async Task<(HttpStatusCode StatusCode, IList<Drive> Data)> GetDrivesBySiteId(
Guid siteId,
List<string>? expandQueryParameters,
string? filterQueryParameter,
List<string>? selectQueryParameters,
List<string>? expandQueryParameters = null,
string? filterQueryParameter = null,
List<string>? selectQueryParameters = null,
CancellationToken cancellationToken = default)
{
List<Drive> pagedItems = [];
Expand Down Expand Up @@ -159,9 +159,9 @@ public OneDriveGraphService(

public async Task<(HttpStatusCode StatusCode, IList<DriveItem> Data)> GetDriveItemsByDriveId(
string driveId,
List<string>? expandQueryParameters,
string? filterQueryParameter,
List<string>? selectQueryParameters,
List<string>? expandQueryParameters = null,
string? filterQueryParameter = null,
List<string>? selectQueryParameters = null,
CancellationToken cancellationToken = default)
{
var requestInformation = Client
Expand All @@ -187,8 +187,8 @@ public OneDriveGraphService(
public async Task<(HttpStatusCode StatusCode, IList<DriveItem> Data)> GetDriveItemsByDriveIdAndDeltaToken(
string driveId,
string deltaToken,
string? filterQueryParameter,
List<string>? selectQueryParameters,
string? filterQueryParameter = null,
List<string>? selectQueryParameters = null,
CancellationToken cancellationToken = default)
{
List<DriveItem> pagedItems = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,40 @@ public interface IOutlookGraphService
{
Task<(HttpStatusCode StatusCode, IList<MailFolder> Data)> GetRootMailFoldersByUserId(
string userId,
List<string>? expandQueryParameters,
string? filterQueryParameter,
List<string>? selectQueryParameters,
List<string>? expandQueryParameters = null,
string? filterQueryParameter = null,
List<string>? selectQueryParameters = null,
CancellationToken cancellationToken = default);

Task<(HttpStatusCode StatusCode, IList<MailFolder> Data)> GetMailFoldersByUserIdAndFolderId(
string userId,
string folderId,
List<string>? expandQueryParameters,
string? filterQueryParameter,
List<string>? selectQueryParameters,
List<string>? expandQueryParameters = null,
string? filterQueryParameter = null,
List<string>? selectQueryParameters = null,
CancellationToken cancellationToken = default);

Task<(HttpStatusCode StatusCode, IList<Message> Data)> GetMessagesByUserId(
string userId,
List<string>? expandQueryParameters,
string? filterQueryParameter,
List<string>? selectQueryParameters,
List<string>? expandQueryParameters = null,
string? filterQueryParameter = null,
List<string>? selectQueryParameters = null,
CancellationToken cancellationToken = default);

Task<(HttpStatusCode StatusCode, IList<Message> Data, string? DeltaToken)> GetMessagesByUserIdAndFolderId(
string userId,
string folderId,
List<string>? expandQueryParameters,
string? filterQueryParameter,
List<string>? selectQueryParameters,
List<string>? expandQueryParameters = null,
string? filterQueryParameter = null,
List<string>? selectQueryParameters = null,
string? deltaToken = null,
CancellationToken cancellationToken = default);

Task<(HttpStatusCode StatusCode, IList<FileAttachment> Data)> GetFileAttachmentsByUserIdAndMessageId(
string userId,
string messageId,
List<string>? expandQueryParameters,
string? filterQueryParameter,
List<string>? selectQueryParameters,
List<string>? expandQueryParameters = null,
string? filterQueryParameter = null,
List<string>? selectQueryParameters = null,
CancellationToken cancellationToken = default);
}
Loading