// Create a subscription.
        public async Task <IActionResult> Create()
        {
            string userId      = User.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier")?.Value;
            string tenantId    = User.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid")?.Value;
            string clientState = Guid.NewGuid().ToString();

            Subscription newSubscription = new Subscription();

            try
            {
                // Initialize the GraphServiceClient.
                // This sample passes in the tenant ID to use as a cache key.
                GraphServiceClient graphClient = sdkHelper.GetAuthenticatedClient(tenantId);

                // Create a subscription.
                // The `Resource` property targets the `users/{user-id}` or `users/{user-principal-name}` path (not `me`) when using application permissions.
                // The NotificationUrl requires the `https` protocol and supports custom query parameters.
                newSubscription = await graphClient.Subscriptions.Request().AddAsync(new Subscription
                {
                    Resource        = $"users/{ userId }/mailFolders('Inbox')/messages",
                    ChangeType      = "created",
                    NotificationUrl = appSettings.NotificationUrl,
                    ClientState     = clientState,
                    //ExpirationDateTime = DateTime.UtcNow + new TimeSpan(0, 0, 4230, 0) // current maximum lifespan for messages
                    ExpirationDateTime = DateTime.UtcNow + new TimeSpan(0, 0, 15, 0)     // shorter duration useful for testing
                });

                // Verify client state, then store the subscription ID and client state to validate incoming notifications.
                if (newSubscription.ClientState == clientState)
                {
                    // This sample temporarily stores the subscription data, but production apps will likely use some method of persistent storage.
                    // This sample stores the client state to validate the subscription, the tenant ID to reuse tokens, and the user ID to filter
                    // messages to display by user.
                    subscriptionStore.SaveSubscriptionInfo(newSubscription.Id,
                                                           newSubscription.ClientState,
                                                           userId,
                                                           tenantId);
                }
                else
                {
                    ViewBag.Message = "Warning! Mismatched client state.";
                }
            }
            catch (Exception e)
            {
                // If a tenant admin hasn't granted consent, this operation returns an Unauthorized error.
                // This sample caches the initial unauthorized token, so you'll need to start a new browser session.
                ViewBag.Message = BuildErrorMessage(e);
                return(View("Error"));
            }

            return(View("Subscription", newSubscription));
        }
Example #2
0
        // Get information about the changed messages and send to browser via SignalR.
        // A production application would typically queue a background job for reliability.
        private async Task GetChangedMessagesAsync(IEnumerable <Notification> notifications)
        {
            List <Message> messages = new List <Message>();

            foreach (var notification in notifications)
            {
                if (notification.ResourceData.ODataType != "#Microsoft.Graph.Message")
                {
                    continue;
                }

                // Get the stored user object ID.
                var    subscriptionParams = (Tuple <string, string>)_memoryCache.Get("subscriptionId_" + notification.SubscriptionId);
                string userObjectId       = subscriptionParams.Item2;

                // Initialize the GraphServiceClient, using the user ID associated with the subscription.
                GraphServiceClient graphClient = _sdkHelper.GetAuthenticatedClient(userObjectId);
                MessageRequest     request     = new MessageRequest(graphClient.BaseUrl + "/" + notification.Resource, graphClient, null);
                try
                {
                    messages.Add(await request.GetAsync());
                }
                catch (Exception)
                {
                    continue;
                }
            }

            if (messages.Count > 0)
            {
                //NotificationService notificationService = new NotificationService();
                //notificationService.SendNotificationToClient(messages);
            }
        }
Example #3
0
        // Create a subscription.
        // https://graph.microsoft.io/en-us/docs/api-reference/v1.0/resources/webhooks
        public async Task <IActionResult> Create()
        {
            // Initialize the GraphServiceClient.
            string             userObjectID = (User.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier"))?.Value;
            GraphServiceClient graphClient  = sdkHelper.GetAuthenticatedClient(userObjectID);

            Subscription newSubscription = new Subscription();
            string       state           = Guid.NewGuid().ToString();

            try
            {
                // Send the `POST /subscriptions` request.
                newSubscription = await graphClient.Subscriptions.Request().AddAsync(new Subscription
                {
                    Resource           = "me/mailFolders('Inbox')/messages",
                    ChangeType         = "created",
                    NotificationUrl    = "https://6b6b3cf8.ngrok.io/notification/listen",
                    ClientState        = state,
                    ExpirationDateTime = DateTime.UtcNow + new TimeSpan(0, 0, 4230, 0)
                });

                // Verify client state.
                if (newSubscription.ClientState != state)
                {
                    ViewBag.Message = "Warning: Mismatched client state.";
                }

                // Store the subscription ID to correlate a notification to the corresponding subscription.
                else
                {
                    // This sample temporarily stores the current subscription ID, client state, and user object ID.
                    // The NotificationController, which is not authenticated, uses this info to validate the subscription and get an access token keyed from the subscription ID.
                    // Production apps will typically use some method of persistent storage.
                    memoryCache.Set("subscriptionId_" + newSubscription.Id,
                                    Tuple.Create(newSubscription.ClientState, HttpContext.User.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value),
                                    new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromHours(24)));
                }
            }
            catch (Exception e)
            {
                ViewBag.Message = BuildErrorMessage(e);
                return(View("Error", e));
            }
            return(View("Subscription", newSubscription));
        }
        // Get information about the changed messages and send to browser via SignalR.
        // A production application would typically queue a background job for reliability.
        private async Task GetChangedMessagesAsync(IEnumerable <Notification> notifications)
        {
            List <MessageViewModel> messages = new List <MessageViewModel>();

            foreach (var notification in notifications)
            {
                if (notification.ResourceData.ODataType != "#Microsoft.Graph.Message")
                {
                    continue;
                }

                SubscriptionStore subscription = subscriptionStore.GetSubscriptionInfo(notification.SubscriptionId);

                // Initialize the GraphServiceClient. This sample uses the tenant ID the cache key.
                GraphServiceClient graphClient = sdkHelper.GetAuthenticatedClient(subscription.TenantId);

                MessageRequest request = new MessageRequest(graphClient.BaseUrl + "/" + notification.Resource, graphClient, null);
                try
                {
                    messages.Add(new MessageViewModel(await request.GetAsync(), subscription.UserId));
                }
                catch (ServiceException se)
                {
                    string errorMessage = se.Error.Message;
                    string requestId    = se.Error.InnerError.AdditionalData["request-id"].ToString();
                    string requestDate  = se.Error.InnerError.AdditionalData["date"].ToString();

                    logger.LogError($"RetrievingMessages: { errorMessage } Request ID: { requestId } Date: { requestDate }");
                }
            }

            if (messages.Count > 0)
            {
                NotificationService notificationService = new NotificationService();

                // Clients use the subscribedUserId to filter for messages that belong to the current user.
                notificationService.SendNotificationToClient(connectionManager, messages);
            }
        }