c# - 使用 Hangfire 进行 Microsoft Graph API 调用
问题描述
我正在努力使用 Hangfire 后台作业延迟进行图形 API 调用,因为我相信 HttpContext 在进行调用时为空,我不知道如何解决这个问题。
// 设置作业延迟触发
BackgroundJob.Schedule(() => this.HangfireTest("test@gmail.com", false), TimeSpan.FromSeconds(20));
// 进行图形 api 调用,它会返回“尚未计算”的结果
var userInfo = this.graphServiceClient.Me.Request().Select(Info.Fields).GetAsync();
我试过在上下文中传递,但这不起作用。不知道如何解决这个问题。谢谢!
解决方案
这是一个为我工作的 ASP.Net Core 3.1 MVC 原型实现。我在寻找解决方案时也遇到了很多问题,因此在这里发布。我已经编辑了一些代码,以便更容易阅读和删除解决此问题所需的臃肿。
请注意,该方法是从 GraphAPI 检索访问令牌并将其传递给后台作业,创建一个新的独立 GraphClient 实例并添加包含访问令牌所需的承载标头。
在 startup.cs 中,EnableTokenAcquisition 允许在控制器中检索访问令牌。
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(this.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
.AddMicrosoftGraph(this.Configuration.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();
控制器初始化...
using Microsoft.Graph;
using Microsoft.Identity.Web;
private readonly GraphServiceClient graphServiceClient;
private readonly ITokenAcquisition tokenAcquisition = null;
public HomeController(ILogger<HomeController> logger, IConfiguration iconfiguration, GraphServiceClient graphServiceClient, ITokenAcquisition tokenAcquisition)
{
this.graphServiceClient = graphServiceClient;
this.tokenAcquisition = tokenAcquisition;
}
计划作业控制器操作
public IActionResult ScheduleJob(BackgroundJobsViewModel model)
{
try
{
string accessToken = string.Empty;
try
{
accessToken = Task.Run(async () => await this.tokenAcquisition.GetAccessTokenForUserAsync(scopeList)).Result;
}
catch (MicrosoftIdentityWebChallengeUserException ex)
{
Task.Run(async () => await this.tokenAcquisition.ReplyForbiddenWithWwwAuthenticateHeaderAsync(scopeList, ex.MsalUiRequiredException));
}
catch (Microsoft.Identity.Client.MsalUiRequiredException ex)
{
Task.Run(async () => await this.tokenAcquisition.ReplyForbiddenWithWwwAuthenticateHeaderAsync(scopeList, ex));
}
if (!string.IsNullOrEmpty(accessToken))
{
// Recurring Job.
RecurringJob.AddOrUpdate(job.JobName, () => UpdateUsersBackroundJob.UpdateUsers(this.currentUser.Account, accessToken), $"{seconds} {minutes} {hours} {day} {month} {week}");
}
else
{
return this.View("BackgroundJobs", model);
}
}
catch (Exception ex)
{
var errorModel = this.HandleException(ex);
return this.View("Error", errorModel);
}
}
后台作业类和方法...注意 Info.Fields 我没有显示。
using Microsoft.Graph;
using Microsoft.Identity.Web;
/// <summary>
/// Class to encapsulate the background job to update users.
/// </summary>
public class UpdateUsersBackroundJob
{
/// <summary>
/// Gets or sets the Graph Client.
/// </summary>
private static GraphServiceClient GraphClient { get; set; }
public static void UpdateUsers(string upnName, string graphApiAccessToken)
{
if (string.IsNullOrEmpty(graphApiAccessToken))
{
throw new ApplicationException("Cannot run the update users background job without specifying an access token first.");
}
// Create our own new graph client using the provided token.
GraphClient = new GraphServiceClient(new DelegateAuthenticationProvider((requestMessage) =>
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", graphApiAccessToken);
return Task.FromResult(0);
}));
try
{
// Update DB User data from GraphAPI Azure AD
var userInfo = Task.Run(async () => await GraphClient.Me.Request().Select(Info.Fields).GetAsync()).Result;
...do something with userInfo in application.
}
catch
{
...Handle exception.
}
}
}
}
推荐阅读
- scala - Scala Play - 如何在响应消失之前修改 Cookie 设置值?
- python - 如果它以0开头,我如何计算任何数字的长度?
- sql-server - 会计年度sql server
- javascript - 如何直接从 Html 表单付款
- javascript - 我正在尝试使用 unsplash api 从 unsplash 获取一些信息,但出现错误,有人可以告诉我我做错了什么吗?
- class - 颤振,达特。创建匿名类
- list - 单个字典上的ansible嵌套循环
- swift - 如何在自定义 CALayer 子类的覆盖绘制函数中在 macOS 上绘制字符串?
- html - 将文本框和按钮设置为 100% 宽度
- delphi - 正确地从 TFramedVertScrollBar 中删除项目?