如何在 Microsoft Graph 中使用 DI
How to use DI with Microsoft Graph
我有一个 .net web api 核心项目,我将调用 microsoft graph
所以我创建了一个配置class:
public class GraphConfiguration
{
public static void Configure(IServiceCollection services, IConfiguration configuration)
{
//Look at appsettings.Development.json | https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.1
var graphConfig = new AppSettingsSection();
configuration.GetSection("AzureAD").Bind(graphConfig);
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(graphConfig.ClientId)
.WithTenantId(graphConfig.TenantId)
.WithClientSecret(graphConfig.ClientSecret)
.Build();
ClientCredentialProvider authenticationProvider = new ClientCredentialProvider(confidentialClientApplication);
GraphServiceClient graphServiceClient = new GraphServiceClient(authenticationProvider);
}
}
在我的控制器中我有这个:
public class UserController : ControllerBase
{
private TelemetryClient telemetry;
private readonly ICosmosStore<Partner> _partnerCosmosStore;
private readonly GraphServiceClient _graphServiceClient;
// Use constructor injection to get a TelemetryClient instance.
public UserController(TelemetryClient telemetry,ICosmosStore<Partner> partnerCosmosStore, GraphServiceClient graphServiceClient)
{
this.telemetry = telemetry;
_partnerCosmosStore = partnerCosmosStore;
_graphServiceClient = graphServiceClient;
}
/// <summary>
/// Gets all partners
/// </summary>
/// <returns></returns>
[HttpGet]
public async Task<ActionResult> GetUsers()
{
this.telemetry.TrackEvent("GetPartners");
try
{
var me = await _graphServiceClient.Me.Request().WithForceRefresh(true).GetAsync();
return Ok(me);
}
catch (Exception ex)
{
string guid = Guid.NewGuid().ToString();
var dt = new Dictionary<string, string>
{
{ "Error Lulo: ", guid }
};
telemetry.TrackException(ex, dt);
return BadRequest("Error Lulo: " + guid);
}
}
}
但我想我在 Startupcs 中漏掉了一步。我如何在所有控制器中实际注入它?
我认为你应该让你的方法 return 成为一个 IServiceCollection 然后在你的 startup.cs.
中调用它
public class GraphConfiguration
{
public static IServiceCollection AddGraphComponent(this IServiceCollection services, IConfiguration configuration)
{
//your code
services.AddSingleton<ClientCredentialProvider>(x =>
{
return new GraphServiceClient(authenticationProvider);
});
services.AddSingleton<GraphServiceClient>(x =>
{
return new ClientCredentialProvider(confidentialClientApplication);
});
return services
}
}
然后在你的startup.cs中的ConfigureServices方法中调用这个方法。
services.AddGraphComponent(yourConfiguration);
我建议用 DI 容器注册 GraphServiceClient
public static class GraphConfiguration {
//Called in Startup - services.ConfigureGraphComponent(configuration)
public static IServiceCollection ConfigureGraphComponent(this IServiceCollection services, IConfiguration configuration) {
//Look at appsettings.Development.json | https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.1
AppSettingsSection graphConfig = configuration.GetSection("AzureAD").Get<AppSettingsSection>();
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(graphConfig.ClientId)
.WithTenantId(graphConfig.TenantId)
.WithClientSecret(graphConfig.ClientSecret)
.Build();
ClientCredentialProvider authenticationProvider = new ClientCredentialProvider(confidentialClientApplication);
services.AddScoped<GraphServiceClient>(sp => {
return new GraphServiceClient(authenticationProvider);
});
return services;
}
}
这样容器就会知道如何在解析控制器时注入所需的依赖项
我想用 .NET 6.0 中对我有用的内容扩展@Nkosi 的回答
需要的包:
Microsoft.Graph 4.x.x
Microsoft.Graph.Auth 1.0.0-preview (not production-ready if that's an issue)
我的 GraphConfiguration class 略有不同,因为 AppSettingsSection 没有公开 .ClientId
、.TenantId
等
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Graph;
using Microsoft.Graph.Auth;
using Microsoft.Identity.Client;
namespace EMF.Events.Business.Providers.Graph
{
public static class GraphConfiguration
{
public static IServiceCollection ConfigureGraphClient( this IServiceCollection services, IConfiguration configuration )
{
var graphConfig = configuration.GetSection( "AzureAd" );
var confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create( graphConfig["ClientId"] )
.WithTenantId( graphConfig["TenantId"] )
.WithClientSecret( graphConfig["ClientSecret"] )
.Build();
ClientCredentialProvider authenticationProvider = new ClientCredentialProvider( confidentialClientApplication );
services.AddScoped( sp =>
{
return new GraphServiceClient( authenticationProvider );
} );
return services;
}
}
}
然后在我的 Program.cs...
builder.Services.ConfigureGraphClient( builder.Configuration );
你的 appsettings.json 应该有以下内容(可能还有一些你应该 不删除的其他键 :
"AzureAd": {
...
"TenantId": "<TENANT_ID>",
"ClientId": "<CLIENT_ID>",
"ClientSecret": "<CLIENT_SECRET>",
},
该部分的另一个注意事项是 case-sensitive 因此,如果您的是“AzureAD”而不是“AzureAd”,请相应地进行调整。
我有一个 .net web api 核心项目,我将调用 microsoft graph
所以我创建了一个配置class:
public class GraphConfiguration
{
public static void Configure(IServiceCollection services, IConfiguration configuration)
{
//Look at appsettings.Development.json | https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.1
var graphConfig = new AppSettingsSection();
configuration.GetSection("AzureAD").Bind(graphConfig);
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(graphConfig.ClientId)
.WithTenantId(graphConfig.TenantId)
.WithClientSecret(graphConfig.ClientSecret)
.Build();
ClientCredentialProvider authenticationProvider = new ClientCredentialProvider(confidentialClientApplication);
GraphServiceClient graphServiceClient = new GraphServiceClient(authenticationProvider);
}
}
在我的控制器中我有这个:
public class UserController : ControllerBase
{
private TelemetryClient telemetry;
private readonly ICosmosStore<Partner> _partnerCosmosStore;
private readonly GraphServiceClient _graphServiceClient;
// Use constructor injection to get a TelemetryClient instance.
public UserController(TelemetryClient telemetry,ICosmosStore<Partner> partnerCosmosStore, GraphServiceClient graphServiceClient)
{
this.telemetry = telemetry;
_partnerCosmosStore = partnerCosmosStore;
_graphServiceClient = graphServiceClient;
}
/// <summary>
/// Gets all partners
/// </summary>
/// <returns></returns>
[HttpGet]
public async Task<ActionResult> GetUsers()
{
this.telemetry.TrackEvent("GetPartners");
try
{
var me = await _graphServiceClient.Me.Request().WithForceRefresh(true).GetAsync();
return Ok(me);
}
catch (Exception ex)
{
string guid = Guid.NewGuid().ToString();
var dt = new Dictionary<string, string>
{
{ "Error Lulo: ", guid }
};
telemetry.TrackException(ex, dt);
return BadRequest("Error Lulo: " + guid);
}
}
}
但我想我在 Startupcs 中漏掉了一步。我如何在所有控制器中实际注入它?
我认为你应该让你的方法 return 成为一个 IServiceCollection 然后在你的 startup.cs.
中调用它 public class GraphConfiguration
{
public static IServiceCollection AddGraphComponent(this IServiceCollection services, IConfiguration configuration)
{
//your code
services.AddSingleton<ClientCredentialProvider>(x =>
{
return new GraphServiceClient(authenticationProvider);
});
services.AddSingleton<GraphServiceClient>(x =>
{
return new ClientCredentialProvider(confidentialClientApplication);
});
return services
}
}
然后在你的startup.cs中的ConfigureServices方法中调用这个方法。
services.AddGraphComponent(yourConfiguration);
我建议用 DI 容器注册 GraphServiceClient
public static class GraphConfiguration {
//Called in Startup - services.ConfigureGraphComponent(configuration)
public static IServiceCollection ConfigureGraphComponent(this IServiceCollection services, IConfiguration configuration) {
//Look at appsettings.Development.json | https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.1
AppSettingsSection graphConfig = configuration.GetSection("AzureAD").Get<AppSettingsSection>();
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(graphConfig.ClientId)
.WithTenantId(graphConfig.TenantId)
.WithClientSecret(graphConfig.ClientSecret)
.Build();
ClientCredentialProvider authenticationProvider = new ClientCredentialProvider(confidentialClientApplication);
services.AddScoped<GraphServiceClient>(sp => {
return new GraphServiceClient(authenticationProvider);
});
return services;
}
}
这样容器就会知道如何在解析控制器时注入所需的依赖项
我想用 .NET 6.0 中对我有用的内容扩展@Nkosi 的回答
需要的包:
Microsoft.Graph 4.x.x
Microsoft.Graph.Auth 1.0.0-preview (not production-ready if that's an issue)
我的 GraphConfiguration class 略有不同,因为 AppSettingsSection 没有公开 .ClientId
、.TenantId
等
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Graph;
using Microsoft.Graph.Auth;
using Microsoft.Identity.Client;
namespace EMF.Events.Business.Providers.Graph
{
public static class GraphConfiguration
{
public static IServiceCollection ConfigureGraphClient( this IServiceCollection services, IConfiguration configuration )
{
var graphConfig = configuration.GetSection( "AzureAd" );
var confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create( graphConfig["ClientId"] )
.WithTenantId( graphConfig["TenantId"] )
.WithClientSecret( graphConfig["ClientSecret"] )
.Build();
ClientCredentialProvider authenticationProvider = new ClientCredentialProvider( confidentialClientApplication );
services.AddScoped( sp =>
{
return new GraphServiceClient( authenticationProvider );
} );
return services;
}
}
}
然后在我的 Program.cs...
builder.Services.ConfigureGraphClient( builder.Configuration );
你的 appsettings.json 应该有以下内容(可能还有一些你应该 不删除的其他键 :
"AzureAd": {
...
"TenantId": "<TENANT_ID>",
"ClientId": "<CLIENT_ID>",
"ClientSecret": "<CLIENT_SECRET>",
},
该部分的另一个注意事项是 case-sensitive 因此,如果您的是“AzureAD”而不是“AzureAd”,请相应地进行调整。