Microsoft graph api ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier)。值不返回任何值
我正在创建一个mvc web应用程序,用于读取用户邮件、向用户发送邮件以及使用Microsoft Graph Api接收通知。我的应用程序已在中注册。我能够在登录和订阅通知后获取“ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).value”的返回值。但是我无法在用于侦听通知的Listen()函数中获取返回值。“对象引用未设置为对象的实例”是给定的错误。这是Listen()函数Microsoft graph api ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier)。值不返回任何值,microsoft-graph-api,Microsoft Graph Api,我正在创建一个mvc web应用程序,用于读取用户邮件、向用户发送邮件以及使用Microsoft Graph Api接收通知。我的应用程序已在中注册。我能够在登录和订阅通知后获取“ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).value”的返回值。但是我无法在用于侦听通知的Listen()函数中获取返回值。“对象引用未设置为对象的实例”是给定的错误。这是Listen()函数 public async Task<Ac
public async Task<ActionResult> Listen()
{
// Validate the new subscription by sending the token back to Microsoft Graph.
// This response is required for each subscription.
if (Request.QueryString["validationToken"] != null)
{
var token = Request.QueryString["validationToken"];
return Content(token, "plain/text");
}
// Parse the received notifications.
else
{
try
{
var notifications = new Dictionary<string, NotificationModel>();
using (var inputStream = new System.IO.StreamReader(Request.InputStream))
{
JObject jsonObject = JObject.Parse(inputStream.ReadToEnd());
if (jsonObject != null)
{
// Notifications are sent in a 'value' array. The array might contain multiple notifications for events that are
// registered for the same notification endpoint, and that occur within a short timespan.
JArray value = JArray.Parse(jsonObject["value"].ToString());
foreach (var notification in value)
{
NotificationModel current = JsonConvert.DeserializeObject<NotificationModel>(notification.ToString());
// Check client state to verify the message is from Microsoft Graph.
SubscriptionStore subscription = SubscriptionStore.GetSubscriptionInfo(current.SubscriptionId);
// This sample only works with subscriptions that are still cached.
if (subscription != null)
{
if (current.ClientState == subscription.ClientState)
{
// Just keep the latest notification for each resource.
// No point pulling data more than once.
notifications[current.Resource] = current;
}
}
}
if (notifications.Count > 0)
{
// Query for the changed messages.
await GetChangedMessagesAsync(notifications.Values);
}
}
}
}
catch (Exception)
{
// TODO: Handle the exception.
// Still return a 202 so the service doesn't resend the notification.
}
return new HttpStatusCodeResult(202);
}
}
// Get information about the changed messages and send to the browser via SignalR.
// A production application would typically queue a background job for reliability.
public async Task GetChangedMessagesAsync(IEnumerable<NotificationModel> notifications)
{
List<MessageViewModel> messages = new List<MessageViewModel>();
MessageModel message = new MessageModel();
string serviceRootUrl = "https://graph.microsoft.com/v1.0/";
foreach (var notification in notifications)
{
SubscriptionStore subscription = SubscriptionStore.GetSubscriptionInfo(notification.SubscriptionId);
string token;
try
{
// Get the access token for the subscribed user.
// accessToken = await GetAccessToken();
HttpContextBase httpContext = HttpContext;
token = await AuthHelper.GetAccessToken(httpContext);
}
catch (Exception e)
{
throw e;
}
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, serviceRootUrl + notification.Resource);
// Send the 'GET' request.
GraphHttpClient graphHttpClient = new GraphHttpClient(token);
HttpResponseMessage response = await graphHttpClient.SendAsync(request);
// Get the messages from the JSON response.
if (response.IsSuccessStatusCode)
{
string stringResult = await response.Content.ReadAsStringAsync();
string type = notification.ResourceData.ODataType;
if (type == "#Microsoft.Graph.Message")
{
message = JsonConvert.DeserializeObject<MessageModel>(stringResult);
MessageViewModel messageViewModel = new MessageViewModel(message);
messages.Add(messageViewModel);
}
}
}
if (messages.Count > 0)
{
NotificationService notificationService = new NotificationService();
notificationService.SendNotificationToClient(messages);
}
}
公共异步任务侦听()
{
//通过将令牌发送回Microsoft Graph来验证新订阅。
//每个订阅都需要此响应。
if(Request.QueryString[“validationToken”!=null)
{
var token=Request.QueryString[“validationToken”];
返回内容(标记,“纯/文本”);
}
//解析收到的通知。
其他的
{
尝试
{
var notifications=newdictionary();
使用(var inputStream=new System.IO.StreamReader(Request.inputStream))
{
JObject jsonObject=JObject.Parse(inputStream.ReadToEnd());
if(jsonObject!=null)
{
//通知是以“值”数组发送的。该数组可能包含多个通知,用于以下事件:
//为同一通知终结点注册,并在短时间内发生。
JArray value=JArray.Parse(jsonObject[“value”].ToString());
foreach(值中的var通知)
{
NotificationModel current=JsonConvert.DeserializeObject(notification.ToString());
//检查客户端状态以验证消息是否来自Microsoft Graph。
SubscriptionStore subscription=SubscriptionStore.GetSubscriptionInfo(current.SubscriptionId);
//此示例仅适用于仍缓存的订阅。
if(订阅!=null)
{
if(current.ClientState==subscription.ClientState)
{
//只需保留每个资源的最新通知。
//多次拉取数据没有意义。
通知[current.Resource]=当前;
}
}
}
如果(notifications.Count>0)
{
//查询已更改的消息。
等待GetChangedMessageAsync(notifications.Values);
}
}
}
}
捕获(例外)
{
//TODO:处理异常。
//仍然返回202,因此服务不会重新发送通知。
}
返回新的HttpStatusCodeResult(202);
}
}
//获取有关更改消息的信息,并通过信号器发送到浏览器。
//生产应用程序通常会将后台作业排队以确保可靠性。
公共异步任务GetChangedMessageAsync(IEnumerable通知)
{
列表消息=新列表();
MessageModel message=newmessagemodel();
字符串serviceRootUrl=”https://graph.microsoft.com/v1.0/";
foreach(通知中的var通知)
{
SubscriptionStore subscription=SubscriptionStore.GetSubscriptionInfo(notification.SubscriptionId);
字符串标记;
尝试
{
//获取订阅用户的访问令牌。
//accessToken=等待GetAccessToken();
HttpContextBase httpContext=httpContext;
token=wait AuthHelper.GetAccessToken(httpContext);
}
捕获(例外e)
{
投掷e;
}
HttpRequestMessage请求=新的HttpRequestMessage(HttpMethod.Get,serviceRootUrl+notification.Resource);
//发送“获取”请求。
GraphHttpClient GraphHttpClient=新GraphHttpClient(令牌);
HttpResponseMessage response=等待图HttpClient.SendAsync(请求);
//从JSON响应获取消息。
if(响应。IsSuccessStatusCode)
{
string stringResult=await response.Content.ReadAsStringAsync();
字符串类型=notification.ResourceData.ODataType;
if(type==“#Microsoft.Graph.Message”)
{
message=JsonConvert.DeserializeObject(stringResult);
MessageViewModel MessageViewModel=新建MessageViewModel(消息);
messages.Add(messageViewModel);
}
}
}
如果(messages.Count>0)
{
NotificationService NotificationService=新建NotificationService();
notificationService.SendNotificationToClient(消息);
}
}
这是GetAccessToken()方法,其中使用了“ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value”
公共静态异步任务GetAccessToken(HttpContextBase HttpContext)
{
string accessToken=string.Empty;
//从web.config加载应用程序配置
字符串appId=ConfigurationManager.AppSettings[“ida:appId”];
字符串appPassword=ConfigurationManager.AppSettings[“ida:appPassword”];
public static async Task<string> GetAccessToken(HttpContextBase HttpContext)
{
string accessToken = string.Empty; ;
// Load the app config from web.config
string appId = ConfigurationManager.AppSettings["ida:AppId"];
string appPassword = ConfigurationManager.AppSettings["ida:AppPassword"];
string redirectUri = ConfigurationManager.AppSettings["ida:RedirectUri"];
string[] scopes = ConfigurationManager.AppSettings["ida:AppScopes"]
.Replace(' ', ',').Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
string userId = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
if (!string.IsNullOrEmpty(userId))
{
// Get the user's token cache
SessionTokenCache tokenCache = new SessionTokenCache(userId, HttpContext);
ConfidentialClientApplication cca = new ConfidentialClientApplication(
appId, redirectUri, new Microsoft.Identity.Client.ClientCredential(appPassword), tokenCache.GetMsalCacheInstance(), null);
// Call AcquireTokenSilentAsync, which will return the cached
// access token if it has not expired. If it has expired, it will
// handle using the refresh token to get a new one.
AuthenticationResult result = await cca.AcquireTokenSilentAsync(scopes, cca.Users.FirstOrDefault());
accessToken = result.AccessToken;
}
// Get the current user's ID
return accessToken;
}