Пример #1
0
        public ActionResult Index(string mode = "all", int page = 1)
        {
            List <StructurePostToRender> lst = new List <StructurePostToRender>();
            EWSDbContext db = new EWSDbContext();

            ViewBag.userId      = Session["uid"];
            ViewBag.userName    = Session["uname"];
            ViewBag.ufacultyid  = Session["ufacultyid"];
            ViewBag.uroleid     = Session["uroleid"];
            ViewBag.facultyname = Session["facultyname"];
            ViewBag.opentime    = Session["opentime"];

            int pageSize  = 5;
            int rowCount  = (from s in db.Posts where s.isActive == true select s).Count();
            int pageCount = rowCount / pageSize;

            ViewBag.pageCount = rowCount / pageSize;
            //ViewBag.pageSize = pageSize;
            ViewBag.pageCur = page;
            //ViewBag.mode = mode;
            if (rowCount % pageSize > 0)
            {
                ViewBag.pageCount = rowCount / pageSize + 1;
                pageCount         = rowCount / pageSize + 1;
            }
            if (page > pageCount)
            {
                page = pageCount;
            }
            if (page <= 0)
            {
                page = 1;
            }
            int roleid_temp    = Int32.Parse(Session["uroleid"].ToString());
            int facultyid_temp = Int32.Parse(Session["ufacultyid"].ToString());

            if (roleid_temp == 1 || roleid_temp == 5)
            {
                lst = PostBLL.Post_GetAllPost_Guest(page, pageSize);
            }
            else
            {
                if (mode == "all")
                {
                    lst = PostBLL.Post_GetAllPost(page, pageSize, Int32.Parse(Session["ufacultyid"].ToString()));
                }
                if (mode == "popular")
                {
                    lst = PostBLL.Post_GetTopPopularPost(facultyid_temp);
                }
                if (mode == "topview")
                {
                    lst = PostBLL.Post_GetTopViewPost(facultyid_temp);
                }
            }
            return(View(lst));
        }
Пример #2
0
 /// <summary>
 /// Reconnect StreamingSubscriptionConnections [if not in a disconnecting or error'd state]
 /// </summary>
 public void ReconnectToSubscriptions()
 {
     // Go through our connections and reconnect any that have closed
     _reconnect = false;
     lock (_reconnectLock)  // Prevent this code being run concurrently (i.e. if an event fires in the middle of the processing)
     {
         using (EWSDbContext context = new EWSDbContext(EWSConstants.Config.Database))
         {
             foreach (var _connectionPair in _connections)
             {
                 var connectionGroupName = _connectionPair.Key;
                 var groupInfo           = _groups[connectionGroupName];
                 var _connection         = _connections[connectionGroupName];
                 if (!_connection.IsOpen)
                 {
                     try
                     {
                         try
                         {
                             _connection.Open();
                             _traceListener.Trace("SyncProgram", $"Re-opened connection for group {connectionGroupName}");
                         }
                         catch (Exception ex)
                         {
                             if (ex.Message.StartsWith("You must add at least one subscription to this connection before it can be opened"))
                             {
                                 // Try recreating this group
                                 AddGroupSubscriptions(context, connectionGroupName);
                             }
                             else
                             {
                                 _traceListener.Trace("SyncProgram", $"Failed to reopen connection: {ex.Message}");
                             }
                         }
                     }
                     catch (Exception ex)
                     {
                         _traceListener.Trace("SyncProgram", $"Failed to reopen connection: {ex.Message}");
                     }
                 }
             }
         }
     }
 }
Пример #3
0
        /// <summary>
        /// Adds streamingsubscription to the GroupInfo
        /// </summary>
        /// <param name="context">Database context</param>
        /// <param name="Group"></param>
        /// <param name="smtpAddress"></param>
        /// <returns></returns>
        private StreamingSubscription AddSubscription(EWSDbContext context, GroupInfo Group, string smtpAddress)
        {
            StreamingSubscription subscription = null;

            if (_subscriptions.Any(email => email.SmtpAddress.Equals(smtpAddress)))
            {
                var email = _subscriptions.FirstOrDefault(s => s.SmtpAddress.Equals(smtpAddress));
                _subscriptions.Remove(email);
            }

            try
            {
                ExchangeService exchange = Group.ExchangeService;
                exchange.Credentials        = ServiceCredentials;
                exchange.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, smtpAddress);
                subscription = exchange.SubscribeToStreamingNotifications(new FolderId[] { WellKnownFolderName.Calendar },
                                                                          EventType.Created,
                                                                          EventType.Deleted,
                                                                          EventType.Modified,
                                                                          EventType.Moved,
                                                                          EventType.Copied);


                _traceListener.Trace("SyncProgram", $"CreateStreamingSubscriptionGrouping to room {smtpAddress} with SubscriptionId {subscription.Id}");


                var subscriptions = context.SaveChanges();
                _traceListener.Trace("SyncProgram", $"Streaming subscription persisted {subscriptions} persisted.");

                _subscriptions.Add(new SubscriptionCollection()
                {
                    SmtpAddress = smtpAddress,
                    Streaming   = subscription
                });
            }
            catch (Microsoft.Exchange.WebServices.Data.ServiceRequestException srex)
            {
                _traceListener.Trace("SyncProgram", $"Failed to provision subscription {srex.Message}");
                throw new Exception($"Subscription could not be created for {smtpAddress} with MSG:{srex.Message}");
            }

            return(subscription);
        }
        public ActionResult Index(string mode = "all", int page = 1)
        {
            List <StructurePostToRender> lst = new List <StructurePostToRender>();
            EWSDbContext db        = new EWSDbContext();
            int          pageSize  = 5;
            int          rowCount  = (from s in db.Posts select s).Count();
            int          pageCount = rowCount / pageSize;

            ViewBag.pageCount = rowCount / pageSize;
            //ViewBag.pageSize = pageSize;
            ViewBag.pageCur = page;
            //ViewBag.mode = mode;
            ViewBag.userId     = Session["uid"];
            ViewBag.userName   = Session["uname"];
            ViewBag.ufacultyid = Session["ufacultyid"];
            ViewBag.uroleid    = Session["uroleid"];
            if (rowCount % pageSize > 0)
            {
                ViewBag.pageCount = rowCount / pageSize + 1;
                pageCount         = rowCount / pageSize + 1;
            }
            if (page > pageCount)
            {
                page = pageCount;
            }
            if (page <= 0)
            {
                page = 1;
            }
            if (mode == "all")
            {
                lst = PostBLL.Post_GetAllPost(page, pageSize);
            }
            if (mode == "popular")
            {
                lst = PostBLL.Post_GetTopPopularPost();
            }
            if (mode == "topview")
            {
                lst = PostBLL.Post_GetTopViewPost();
            }
            return(View(lst));
        }
Пример #5
0
        /// <summary>
        /// Close connections and unsubscribe
        /// </summary>
        public void CloseConnections()
        {
            _traceListener.Trace("SyncProgram", $"ConsoleCtrlCheck CloseConnections at {DateTime.UtcNow}..");

            foreach (StreamingSubscriptionConnection connection in _connections.Values)
            {
                if (connection.IsOpen)
                {
                    connection.Close();
                }
            }

            // Unsubscribe all
            if (_subscriptions == null)
            {
                return;
            }


            using (EWSDbContext context = new EWSDbContext(EWSConstants.Config.Database))
            {
                var databaseItems = context.RoomListRoomEntities.ToList();

                try
                {
                    for (int i = _subscriptions.Count - 1; i >= 0; i--)
                    {
                        SubscriptionCollection subscriptionItem = _subscriptions[i];
                        var subscription = subscriptionItem.Streaming;
                        try
                        {
                            subscription.Unsubscribe();
                            _traceListener.Trace("SyncProgram", $"Unsubscribed from {subscriptionItem.SmtpAddress}");

                            if (databaseItems.Any(di => di.SmtpAddress == subscriptionItem.SmtpAddress))
                            {
                                var item = databaseItems.FirstOrDefault(di => di.SmtpAddress == subscriptionItem.SmtpAddress);
                                item.LastSyncDate = DateTime.UtcNow;
                            }
                        }
                        catch (Exception ex)
                        {
                            _traceListener.Trace("SyncProgram", $"Error when unsubscribing {subscriptionItem.SmtpAddress}: {ex.Message}");
                        }

                        _subscriptions.Remove(subscriptionItem);
                    }
                }
                catch (Exception subEx)
                {
                    _traceListener.Trace("SyncProgram", $"Failed in subscription disconnect {subEx.Message}");
                }
                finally
                {
                    var changes = context.SaveChanges();
                    _traceListener.Trace("SyncProgram", $"Subscription watermark sync changed {changes} rows.");
                }
            }

            _reconnect = false;
        }
Пример #6
0
        /// <summary>
        /// Process the GroupInfo and create subscriptions based on AnchorMailbox
        /// </summary>
        /// <param name="context">Database context for subscription update</param>
        /// <param name="groupName">EWS GroupInfo or Dynamic Groupname if Mailboxes > 200</param>
        /// <returns></returns>
        public bool AddGroupSubscriptions(EWSDbContext context, string groupName)
        {
            if (!_groups.ContainsKey(groupName))
            {
                return(false);
            }

            if (_connections == null)
            {
                _connections = new Dictionary <string, StreamingSubscriptionConnection>();
            }


            if (_connections.ContainsKey(groupName))
            {
                var _connection = _connections[groupName];

                foreach (StreamingSubscription subscription in _connection.CurrentSubscriptions)
                {
                    try
                    {
                        subscription.Unsubscribe();
                    }
                    catch { }
                }
                try
                {
                    _connection.Close();

                    _groups[groupName].IsConnectionOpen = false;
                }
                catch { }
            }

            try
            {
                // Create the connection for this group, and the primary mailbox subscription
                var groupInfo      = _groups[groupName];
                var PrimaryMailbox = groupInfo.PrimaryMailbox;
                // Return the subscription, or create a new one if we don't already have one
                StreamingSubscription mailboxSubscription = AddSubscription(context, groupInfo, PrimaryMailbox);
                if (_connections.ContainsKey(groupName))
                {
                    _connections[groupName] = new StreamingSubscriptionConnection(mailboxSubscription.Service, pollingTimeout);
                }
                else
                {
                    _connections.Add(groupName, new StreamingSubscriptionConnection(mailboxSubscription.Service, pollingTimeout));
                }


                SubscribeConnectionEvents(_connections[groupName]);
                _connections[groupName].AddSubscription(mailboxSubscription);
                _traceListener.Trace("SyncProgram", $"{PrimaryMailbox} (primary mailbox) subscription created in group {groupName}");

                // Now add any further subscriptions in this group
                foreach (string sMailbox in groupInfo.Mailboxes.Where(w => !w.Equals(PrimaryMailbox)))
                {
                    try
                    {
                        var localSubscription = AddSubscription(context, groupInfo, sMailbox);
                        _connections[groupName].AddSubscription(localSubscription);
                        _traceListener.Trace("Add secondary subscription", $"{sMailbox} subscription created in group {groupName}");
                    }
                    catch (Exception ex)
                    {
                        _traceListener.Trace("Exception", $"ERROR when subscribing {sMailbox} in group {groupName}: {ex.Message}");
                    }
                }
            }
            catch (Exception ex)
            {
                _traceListener.Trace("Exception", $"ERROR when creating subscription connection group {groupName}: {ex.Message}");
            }
            return(true);
        }
Пример #7
0
        /// <summary>
        /// Enable the synchronization of individual folders or Room[s]
        /// </summary>
        /// <param name="folderInfo"></param>
        public void ProcessChanges(EWSFolderInfo folderInfo)
        {
            bool moreChangesAvailable = false;

            _traceListener.Trace("SyncProgram", $"Entered ProcessChanges for {folderInfo.SmtpAddress} at {DateTime.UtcNow}");

            using (EWSDbContext context = new EWSDbContext(EWSConstants.Config.Database))
            {
                var room          = context.RoomListRoomEntities.FirstOrDefault(f => f.SmtpAddress.Equals(folderInfo.SmtpAddress));
                var email         = room.SmtpAddress;
                var syncState     = room.SynchronizationState;
                var syncTimestamp = room.SynchronizationTimestamp;

                try
                {
                    do
                    {
                        // Get all changes since the last call. The synchronization cookie is stored in the _SynchronizationState field.
                        _traceListener.Trace("SyncProgram", $"Sync changes {email} with timestamp {syncTimestamp}");

                        // Just get the IDs of the items.
                        // For performance reasons, do not use the PropertySet.FirstClassProperties.
                        var changes = folderInfo.Service.Current.SyncFolderItems(folderInfo.Folder, PropertySet.IdOnly, null, 512, SyncFolderItemsScope.NormalItems, syncState);

                        // Update the synchronization
                        syncState = changes.SyncState;

                        // Process all changes. If required, add a GetItem call here to request additional properties.
                        foreach (ItemChange itemChange in changes)
                        {
                            // This example just prints the ChangeType and ItemId to the console.
                            // A LOB application would apply business rules to each
                            _traceListener.Trace("SyncProgram", $"ChangeType = {itemChange.ChangeType} with ItemId {itemChange.ItemId.ToString()}");

                            // Send an item event you can bind to
                            var service = System.Threading.Tasks.Task.Run(async() =>
                            {
                                _traceListener.Trace("SyncProgram", "In Thread run await....");
                                await Messenger.SendQueueO365SyncFoldersAsync(queueSync, email, itemChange);
                            }, CancellationTokenSource.Token);
                            service.Wait();
                        }

                        // If more changes are available, issue additional SyncFolderItems requests.
                        moreChangesAvailable = changes.MoreChangesAvailable;

                        room.SynchronizationState     = syncState;
                        room.SynchronizationTimestamp = DateTime.UtcNow;

                        var roomchanges = context.SaveChanges();
                        _traceListener.Trace("SyncProgram", $"Room event folder sync {roomchanges} persisted.");
                    }while (moreChangesAvailable);
                }
                catch (Exception processEx)
                {
                    Trace.TraceError($"Failed to send queue {processEx.Message}");
                }
                finally
                {
                    room.SynchronizationState     = syncState;
                    room.SynchronizationTimestamp = DateTime.UtcNow;

                    var roomchanges = context.SaveChanges();
                    _traceListener.Trace("SyncProgram", $"Failed ProcessChanges({email}) folder sync {roomchanges} persisted.");
                }
            }
        }
Пример #8
0
        /// <summary>
        /// Creates pull subscriptions for all rooms and waits on timer delay to pull subscriptions
        /// </summary>
        /// <param name="mailboxOwner"></param>
        /// <returns></returns>
        private async System.Threading.Tasks.Task PullSubscriptionChangesAsync(string mailboxOwner)
        {
            _traceListener.Trace("SyncProgram", $"PullSubscriptionChangesAsync({mailboxOwner}) starting");

            var service = new EWService(EwsToken);

            service.SetImpersonation(ConnectingIdType.SmtpAddress, mailboxOwner);

            if (_subscriptions == null)
            {
                _subscriptions = new List <SubscriptionCollection>();
            }

            var EwsService = new EWService(EwsToken);

            EwsService.SetImpersonation(ConnectingIdType.SmtpAddress, mailboxOwner);

            // Retreive and Store PullSubscription Details
            using (var _context = new EWSDbContext(EWSConstants.Config.Database))
            {
                foreach (var room in _context.RoomListRoomEntities.Where(w => !string.IsNullOrEmpty(w.Identity)))
                {
                    EntitySubscription dbSubscription = null;
                    string             watermark      = null;
                    if (_context.SubscriptionEntities.Any(rs => rs.SmtpAddress == room.SmtpAddress))
                    {
                        dbSubscription = _context.SubscriptionEntities.FirstOrDefault(rs => rs.SmtpAddress == room.SmtpAddress);
                        watermark      = dbSubscription.Watermark;
                    }
                    else
                    {
                        // newup a subscription to track the watermark
                        dbSubscription = new EntitySubscription()
                        {
                            LastRunTime = DateTime.UtcNow,
                            SmtpAddress = room.SmtpAddress
                        };
                        _context.SubscriptionEntities.Add(dbSubscription);
                    }

                    try
                    {
                        var roomService  = new EWService(EwsToken);
                        var subscription = roomService.CreatePullSubscription(ConnectingIdType.SmtpAddress, room.SmtpAddress, pollingTimeout, watermark);

                        // close out the old subscription
                        dbSubscription.PreviousWatermark = (!string.IsNullOrEmpty(watermark)) ? watermark : null;
                        dbSubscription.Watermark         = subscription.Watermark;


                        _traceListener.Trace("SyncProgram", $"ListenToRoomReservationChangesAsync.Subscribed to room {room.SmtpAddress}");
                        _subscriptions.Add(new SubscriptionCollection()
                        {
                            Pulling     = subscription,
                            SmtpAddress = room.SmtpAddress
                        });

                        var rowChanged = _context.SaveChanges();
                        _traceListener.Trace("SyncProgram", $"Pull subscription persisted {rowChanged} rows");
                    }
                    catch (Microsoft.Exchange.WebServices.Data.ServiceRequestException srex)
                    {
                        _traceListener.Trace("SyncProgram", $"Failed to provision subscription {srex.Message}");
                        throw new Exception($"Subscription could not be created for {room.SmtpAddress} with MSG:{srex.Message}");
                    }
                }
            }


            try
            {
                var waitTimer = new TimeSpan(0, 5, 0);
                while (!CancellationTokenSource.IsCancellationRequested)
                {
                    var milliseconds = (int)waitTimer.TotalMilliseconds;

                    using (var _context = new EWSDbContext(EWSConstants.Config.Database))
                    {
                        foreach (var item in _subscriptions)
                        {
                            bool?ismore = default(bool);
                            do
                            {
                                PullSubscription subscription = item.Pulling;
                                var events    = subscription.GetEvents();
                                var watermark = subscription.Watermark;
                                ismore = subscription.MoreEventsAvailable;
                                var email        = item.SmtpAddress;
                                var databaseItem = _context.SubscriptionEntities.FirstOrDefault(rs => rs.SmtpAddress == email);

                                // pull last event from stack TODO: need heuristic for how meetings can be stored
                                var filteredEvents = events.ItemEvents.OrderBy(x => x.TimeStamp);
                                foreach (ItemEvent ev in filteredEvents)
                                {
                                    var itemId = ev.ItemId;
                                    try
                                    {
                                        // Send an item event you can bind to
                                        await Messenger.SendQueueO365ChangesAsync(queueSubscription, email, ev);
                                    }
                                    catch (ServiceResponseException ex)
                                    {
                                        _traceListener.Trace("SyncProgram", $"ServiceException: {ex.Message}");
                                        continue;
                                    }
                                }


                                databaseItem.Watermark   = watermark;
                                databaseItem.LastRunTime = DateTime.UtcNow;

                                // Save Database changes
                                await _context.SaveChangesAsync();
                            }while (ismore == true);
                        }
                    }

                    _traceListener.Trace("SyncProgram", $"Sleeping at {DateTime.UtcNow} for {milliseconds} milliseconds...");
                    System.Threading.Thread.Sleep(milliseconds);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            _traceListener.Trace("SyncProgram", $"PullSubscriptionChangesAsync({mailboxOwner}) exiting");
        }
Пример #9
0
        /// <summary>
        /// Creates grouping subscriptions and waits for the notification events to flow
        /// </summary>
        /// <param name="impersonationId"></param>
        /// <returns></returns>
        async public System.Threading.Tasks.Task CreateStreamingSubscriptionGroupingAsync(string impersonationId)
        {
            var database = EWSConstants.Config.Database;

            using (EWSDbContext context = new EWSDbContext(database))
            {
                var smtpAddresses = await context.RoomListRoomEntities.ToListAsync();

                foreach (var sMailbox in smtpAddresses)
                {
                    var addedBox = _mailboxes.AddMailbox(sMailbox.SmtpAddress);
                    if (!addedBox)
                    {
                        _traceListener.Trace("SyncProgram", $"Failed to add SMTP {sMailbox.SmtpAddress}");
                    }

                    MailboxInfo mailboxInfo = _mailboxes.Mailbox(sMailbox.SmtpAddress);
                    if (mailboxInfo != null)
                    {
                        GroupInfo groupInfo = null;
                        if (_groups.ContainsKey(mailboxInfo.GroupName))
                        {
                            groupInfo = _groups[mailboxInfo.GroupName];
                        }
                        else
                        {
                            groupInfo = new GroupInfo(mailboxInfo.GroupName, mailboxInfo.SMTPAddress, mailboxInfo.EwsUrl, EwsToken, _traceListener);
                            _groups.Add(mailboxInfo.GroupName, groupInfo);
                        }

                        if (groupInfo.Mailboxes.Count > 199)
                        {
                            // We already have enough mailboxes in this group, so we rename it and create a new one
                            // Renaming it means that we can still put new mailboxes into the correct group based on GroupingInformation
                            int i = 1;
                            while (_groups.ContainsKey($"{groupInfo.Name}-{i}"))
                            {
                                i++;
                            }

                            // Remove previous grouping name from stack
                            _groups.Remove(groupInfo.Name);

                            // Add the grouping back with the new grouping name [keep the GroupInfo with previous name]
                            _groups.Add($"{groupInfo.Name}-{i}", groupInfo);

                            // Provision a new GroupInfo with the GroupName
                            groupInfo = new GroupInfo(mailboxInfo.GroupName, mailboxInfo.SMTPAddress, mailboxInfo.EwsUrl, EwsToken, _traceListener);

                            // Add GroupInfo to stack
                            _groups.Add(mailboxInfo.GroupName, groupInfo);
                        }

                        // Add the mailbox to the collection
                        groupInfo.Mailboxes.Add(sMailbox.SmtpAddress);
                    }
                }

                // Enable the Grouping
                foreach (var _group in _groups)
                {
                    _traceListener.Trace("SyncProgram", $"Opening connections for {_group.Key}");

                    var groupName = _group.Key;
                    var groupInfo = _group.Value;

                    // Create a streaming connection to the service object, over which events are returned to the client.
                    // Keep the streaming connection open for 30 minutes.
                    if (AddGroupSubscriptions(context, groupName))
                    {
                        _traceListener.Trace("SyncProgram", $"{groupInfo.Mailboxes.Count()} mailboxes primed for StreamingSubscriptions.");
                    }
                    else
                    {
                        _traceListener.Trace("SyncProgram", $"Group {groupInfo.Name} failed in StreamingSubscription events.");
                    }
                }
            }

            using (var semaphore = new System.Threading.SemaphoreSlim(1))
            {
                // Block the Thread
                semaphore.Wait();

                // Establish the StreamingSubscriptionConnections based on the GroupingInfo
                foreach (var connection in _connections)
                {
                    var _group      = _groups[connection.Key];
                    var _connection = connection.Value;
                    if (_connection.IsOpen)
                    {
                        _group.IsConnectionOpen = true;
                        return;
                    }

                    try
                    {
                        _connection.Open();
                        _group.IsConnectionOpen = true;
                    }
                    catch (Exception ex)
                    {
                        _traceListener.Trace("SyncProgram", $"Error opening streamingsubscriptionconnection for group {_group.Name} MSG {ex.Message}");
                    }
                }

                // Lock the Thread Until its cancelled or fails
                await semaphore.WaitAsync(CancellationTokenSource.Token);
            }
        }
Пример #10
0
        /// <summary>
        /// Establish the connection
        /// </summary>
        /// <returns></returns>
        async private System.Threading.Tasks.Task RunAsync()
        {
            _traceListener = new ClassTraceListener();

            IsDisposed = false;

            EwsToken = await EWSConstants.AcquireTokenAsync();

            Messenger = new MessageManager(CancellationTokenSource);

            ServiceCredentials = new OAuthCredentials(EwsToken.AccessToken);

            _reconnect     = true;
            _groups        = new Dictionary <string, GroupInfo>();
            _mailboxes     = new Mailboxes(ServiceCredentials, _traceListener);
            _subscriptions = new List <SubscriptionCollection>();
            _connections   = new Dictionary <string, StreamingSubscriptionConnection>();


            var impersonationId = EWSConstants.Config.Exchange.ImpersonationAcct;

            try
            {
                var list = new List <EWSFolderInfo>();
                using (EWSDbContext context = new EWSDbContext(EWSConstants.Config.Database))
                {
                    foreach (var room in context.RoomListRoomEntities.Where(w => !string.IsNullOrEmpty(w.Identity)))
                    {
                        var mailboxId = room.SmtpAddress;

                        try
                        {
                            var roomService = new EWService(EwsToken);
                            roomService.SetImpersonation(ConnectingIdType.SmtpAddress, mailboxId);
                            var folderId = new FolderId(WellKnownFolderName.Calendar, mailboxId);
                            var info     = new EWSFolderInfo()
                            {
                                SmtpAddress = mailboxId,
                                Service     = roomService,
                                Folder      = folderId
                            };
                            list.Add(info);
                        }
                        catch (Exception srex)
                        {
                            _traceListener.Trace("SyncProgram", $"Failed to ProcessChanges{srex.Message}");
                            throw new Exception($"ProcessChanges for {mailboxId} with MSG:{srex.Message}");
                        }
                    }
                }

                // Parallel ForEach (on RoomMailbox Grouping and SyncFolders)
                await System.Threading.Tasks.Task.Run(() =>
                {
                    ParallelOptions options = new ParallelOptions
                    {
                        MaxDegreeOfParallelism = maxConcurrency
                    };

                    // Fireoff folder sync in background thread
                    Parallel.ForEach(list, options,
                                     (bodyInfo) =>
                    {
                        ProcessChanges(bodyInfo);
                    });
                });


                var tasks = new List <System.Threading.Tasks.Task>();


                if (EWSConstants.Config.Exchange.PullEnabled)
                {
                    // Upon completion tick repeater to poll subscriptions
                    tasks.Add(PullSubscriptionChangesAsync(impersonationId));
                }
                else
                {
                    // Upon completion kick of streamingsubscription
                    tasks.Add(CreateStreamingSubscriptionGroupingAsync(impersonationId));
                }

                System.Threading.Tasks.Task.WaitAll(tasks.ToArray());
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.Message);
            }
        }
Пример #11
0
        /// <summary>
        /// Poll localDB events and push service bus events to the Queue
        /// </summary>
        /// <param name="queueConnection"></param>
        /// <returns></returns>
        public async System.Threading.Tasks.Task SendQueueDatabaseChangesAsync(string queueConnection)
        {
            var sender = new MessageSender(queueConnection, SBQueueSyncDb);

            var token = await RetreiveToken();

            var EwsService = new EWService(token);

            EwsService.SetImpersonation(ConnectingIdType.SmtpAddress, MailboxOwner);

            // Poll the rooms to store locally
            var roomlisting = EwsService.GetRoomListing();

            using (var EwsDatabase = new EWSDbContext(EWSConstants.Config.Database))
            {
                foreach (var roomlist in roomlisting)
                {
                    foreach (var room in roomlist.Value)
                    {
                        EntityRoomListRoom databaseRoom = null;
                        if (EwsDatabase.RoomListRoomEntities.Any(s => s.SmtpAddress == room.Address))
                        {
                            databaseRoom = await EwsDatabase.RoomListRoomEntities.FirstOrDefaultAsync(f => f.SmtpAddress == room.Address);
                        }
                        else
                        {
                            databaseRoom = new EntityRoomListRoom()
                            {
                                SmtpAddress = room.Address,
                                Identity    = room.Address,
                                RoomList    = roomlist.Key
                            };
                            EwsDatabase.RoomListRoomEntities.Add(databaseRoom);
                        }
                    }
                }

                var roomchanges = await EwsDatabase.SaveChangesAsync();

                Trace.WriteLine($"Rooms {roomchanges} saved to database.");
            }

            var waitTimer = new TimeSpan(0, 5, 0);

            while (!_cancel.IsCancellationRequested)
            {
                var milliseconds = (int)waitTimer.TotalMilliseconds;

                // whatever you want to happen every 5 minutes
                Trace.WriteLine($"SendQueueDatabaseChangesAsync({MailboxOwner}) starting at {DateTime.UtcNow.ToShortTimeString()}");


                using (var EwsDatabase = new EWSDbContext(EWSConstants.Config.Database))
                {
                    var i        = 0;
                    var bookings = EwsDatabase.AppointmentEntities.Include(ictx => ictx.Room)
                                   .Where(w => !w.ExistsInExchange || !w.SyncedWithExchange || (w.DeletedLocally && !w.SyncedWithExchange));

                    foreach (var booking in bookings)
                    {
                        Microsoft.Exchange.WebServices.Data.EventType eventType = Microsoft.Exchange.WebServices.Data.EventType.Deleted;
                        if (!booking.ExistsInExchange)
                        {
                            eventType = Microsoft.Exchange.WebServices.Data.EventType.Created;
                        }
                        else if (!booking.SyncedWithExchange)
                        {
                            eventType = Microsoft.Exchange.WebServices.Data.EventType.Modified;
                        }

                        if (string.IsNullOrEmpty(booking.BookingReference))
                        {
                            booking.BookingReference = $"Ref{booking.Id.ToString().PadLeft(6, '0')}";
                        }

                        var ewsbooking = new EWS.Common.Models.UpdatedBooking()
                        {
                            DatabaseId        = booking.Id,
                            MailBoxOwnerEmail = booking.OrganizerSmtpAddress,
                            SiteMailBox       = booking.Room.SmtpAddress,
                            Subject           = booking.Subject,
                            Location          = booking.Location,
                            StartUTC          = booking.StartUTC,
                            EndUTC            = booking.EndUTC,
                            ExchangeId        = booking.BookingId,
                            ExchangeChangeKey = booking.BookingChangeKey,
                            BookingReference  = booking.BookingReference,
                            ExchangeEvent     = eventType
                        };

                        var message = new Message(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(ewsbooking)))
                        {
                            ContentType = "application/json",
                            Label       = SBMessageSyncDb,
                            MessageId   = i.ToString()
                        };

                        await sender.SendAsync(message);

                        Trace.WriteLine($"{++i}. Sent: Id = {message.MessageId} w/ Subject:{booking.Subject}");
                    }

                    Trace.WriteLine($"Sent {i} messages");
                }

                Trace.WriteLine($"Sleeping at {DateTime.UtcNow} for {milliseconds} milliseconds...");
                System.Threading.Thread.Sleep(milliseconds);
            }
        }
Пример #12
0
        /// <summary>
        /// Read Queue for O365 Sync Folder events and write it to the database [preferably on a separate thread]
        /// </summary>
        /// <param name="queueConnection"></param>
        /// <returns></returns>
        public async System.Threading.Tasks.Task ReceiveQueueO365SyncFoldersAsync(string queueConnection)
        {
            Trace.WriteLine($"ReceiveQueueO365SyncFoldersAsync() starting");

            var token = await RetreiveToken();

            var EwsService = new EWService(token);

            var receiver = new MessageReceiver(queueConnection, SBQueueSyncO365, ReceiveMode.ReceiveAndDelete);

            _cancel.Token.Register(() => receiver.CloseAsync());


            var filterPropertyList = new List <PropertyDefinitionBase>()
            {
                AppointmentSchema.Location,
                ItemSchema.Subject,
                AppointmentSchema.Start,
                AppointmentSchema.End,
                AppointmentSchema.IsMeeting,
                AppointmentSchema.IsOnlineMeeting,
                AppointmentSchema.IsAllDayEvent,
                AppointmentSchema.IsRecurring,
                AppointmentSchema.IsCancelled,
                ItemSchema.IsUnmodified,
                AppointmentSchema.TimeZone,
                AppointmentSchema.ICalUid,
                ItemSchema.ParentFolderId,
                ItemSchema.ConversationId,
                AppointmentSchema.ICalRecurrenceId,
                EWSConstants.RefIdPropertyDef,
                EWSConstants.DatabaseIdPropertyDef
            };

            // With the receiver set up, we then enter into a simple receive loop that terminates
            using (var EwsDatabase = new EWSDbContext(EWSConstants.Config.Database))
            {
                // when the cancellation token if triggered.
                while (!_cancel.Token.IsCancellationRequested)
                {
                    try
                    {
                        // ask for the next message "forever" or until the cancellation token is triggered
                        var message = await receiver.ReceiveAsync();

                        if (message != null)
                        {
                            if (message.Label != null &&
                                message.ContentType != null &&
                                message.Label.Equals(SBMessageSyncO365, StringComparison.InvariantCultureIgnoreCase) &&
                                message.ContentType.Equals("application/json", StringComparison.InvariantCultureIgnoreCase))
                            {
                                // service bus
                                // #TODO: Read bus events from O365 and write to Database
                                var booking = JsonConvert.DeserializeObject <EWS.Common.Models.ChangeBooking>(Encoding.UTF8.GetString(message.Body));
                                Trace.WriteLine($"Msg received: {booking.SiteMailBox} status: {booking.EventType.ToString("f")}");

                                var eventType          = booking.EventType;
                                var itemId             = booking.ExchangeId;
                                var changeKey          = booking.ExchangeChangeKey;
                                var appointmentMailbox = booking.SiteMailBox;
                                try
                                {
                                    Appointment meeting = null;


                                    var dbroom = EwsDatabase.RoomListRoomEntities.Include(idxt => idxt.Appointments).FirstOrDefault(f => f.SmtpAddress == appointmentMailbox);


                                    if (eventType == ChangeType.Delete)
                                    {
                                        var entity = dbroom.Appointments.FirstOrDefault(f => f.BookingId == itemId);
                                        entity.IsDeleted          = true;
                                        entity.ModifiedDate       = DateTime.UtcNow;
                                        entity.SyncedWithExchange = true;
                                        entity.ExistsInExchange   = true;
                                    }
                                    else
                                    {
                                        var appointmentTime = EwsService.GetAppointment(ConnectingIdType.SmtpAddress, appointmentMailbox, itemId, filterPropertyList);

                                        if (!filterPropertyList.Any(fp => fp == AppointmentSchema.Recurrence))
                                        {
                                            filterPropertyList.Add(AppointmentSchema.Recurrence);
                                        }
                                        var parentAppointment = EwsService.GetParentAppointment(appointmentTime, filterPropertyList);
                                        meeting = parentAppointment.Item;

                                        var mailboxId  = parentAppointment.Organizer.Address;
                                        var refId      = parentAppointment.ReferenceId;
                                        var meetingKey = parentAppointment.MeetingKey;

                                        // TODO: move this to the ServiceBus Processing
                                        if ((!string.IsNullOrEmpty(refId) || meetingKey.HasValue) &&
                                            dbroom.Appointments.Any(f => f.BookingReference == refId || f.Id == meetingKey))
                                        {
                                            var entity = dbroom.Appointments.FirstOrDefault(f => f.BookingReference == refId || f.Id == meetingKey);

                                            entity.EndUTC               = meeting.End.ToUniversalTime();
                                            entity.StartUTC             = meeting.Start.ToUniversalTime();
                                            entity.ExistsInExchange     = true;
                                            entity.IsRecurringMeeting   = meeting.IsRecurring;
                                            entity.Location             = meeting.Location;
                                            entity.OrganizerSmtpAddress = mailboxId;
                                            entity.Subject              = meeting.Subject;
                                            entity.RecurrencePattern    = (meeting.Recurrence == null) ? string.Empty : meeting.Recurrence.ToString();
                                            entity.BookingReference     = refId;
                                            entity.BookingChangeKey     = changeKey;
                                            entity.BookingId            = itemId;
                                            entity.ModifiedDate         = DateTime.UtcNow;
                                            entity.SyncedWithExchange   = true;
                                        }
                                        else
                                        {
                                            var entity = new EntityRoomAppointment()
                                            {
                                                BookingReference     = refId,
                                                BookingId            = itemId,
                                                BookingChangeKey     = changeKey,
                                                EndUTC               = meeting.End.ToUniversalTime(),
                                                StartUTC             = meeting.Start.ToUniversalTime(),
                                                ExistsInExchange     = true,
                                                IsRecurringMeeting   = meeting.IsRecurring,
                                                Location             = meeting.Location,
                                                OrganizerSmtpAddress = mailboxId,
                                                Subject              = meeting.Subject,
                                                RecurrencePattern    = (meeting.Recurrence == null) ? string.Empty : meeting.Recurrence.ToString(),
                                                ModifiedDate         = DateTime.UtcNow
                                            };
                                            dbroom.Appointments.Add(entity);
                                        }
                                    }

                                    var appointmentsSaved = EwsDatabase.SaveChanges();
                                    Trace.WriteLine($"Saved {appointmentsSaved} rows");
                                }
                                catch (Exception dbex)
                                {
                                    Trace.WriteLine($"Error occurred in Appointment creation or Database change {dbex}");
                                }
                                finally
                                {
                                    //await receiver.CompleteAsync(message.SystemProperties.LockToken);
                                }
                            }
                            else
                            {
                                // purge / log it
                                await receiver.DeadLetterAsync(message.SystemProperties.LockToken);//, "ProcessingError", "Don't know what to do with this message");
                            }
                        }
                    }
                    catch (ServiceBusException e)
                    {
                        if (!e.IsTransient)
                        {
                            Trace.WriteLine(e.Message);
                            throw;
                        }
                    }
                }
            }
            await receiver.CloseAsync();
        }
Пример #13
0
        /// <summary>
        /// Read Queue for Database Changes [preferably on a separate thread] and Store in Office 365
        /// </summary>
        /// <param name="queueConnection"></param>
        /// <returns></returns>
        public async System.Threading.Tasks.Task ReceiveQueueDatabaseChangesAsync(string queueConnection)
        {
            var token = await RetreiveToken();

            var EwsService = new EWService(token);


            var propertyIds = new List <PropertyDefinitionBase>()
            {
                ItemSchema.Subject,
                AppointmentSchema.Location,
                AppointmentSchema.Start,
                AppointmentSchema.End,
                EWSConstants.RefIdPropertyDef,
                EWSConstants.DatabaseIdPropertyDef
            };

            var receiver = new MessageReceiver(queueConnection, SBQueueSyncDb, ReceiveMode.ReceiveAndDelete);

            _cancel.Token.Register(() => receiver.CloseAsync());

            // when the cancellation token if triggered.
            while (!_cancel.Token.IsCancellationRequested)
            {
                // whatever you want to happen every 5 minutes
                Trace.WriteLine($"ReceiveQueueDatabaseChangesAsync({MailboxOwner}) starting at {DateTime.UtcNow.ToShortTimeString()}");


                // With the receiver set up, we then enter into a simple receive loop that terminates
                using (var _context = new EWSDbContext(EWSConstants.Config.Database))
                {
                    try
                    {
                        // ask for the next message "forever" or until the cancellation token is triggered
                        var message = await receiver.ReceiveAsync();

                        if (message != null)
                        {
                            if (message.Label != null &&
                                message.ContentType != null &&
                                message.Label.Equals(SBMessageSyncDb, StringComparison.InvariantCultureIgnoreCase) &&
                                message.ContentType.Equals("application/json", StringComparison.InvariantCultureIgnoreCase))
                            {
                                // service bus
                                // #TODO: Read bus events from database and write to O365
                                var booking = JsonConvert.DeserializeObject <EWS.Common.Models.UpdatedBooking>(Encoding.UTF8.GetString(message.Body));
                                Trace.WriteLine($"Msg received: {booking.SiteMailBox} - {booking.Subject}. Cancel status: {booking.ExchangeEvent.ToString("f")}");

                                var eventType   = booking.CancelStatus;
                                var eventStatus = booking.ExchangeEvent;
                                var itemId      = booking.ExchangeId;
                                var changeKey   = booking.ExchangeChangeKey;

                                var appointmentMailbox = booking.SiteMailBox;
                                try
                                {
                                    Appointment meeting = null;

                                    if (!string.IsNullOrEmpty(itemId))
                                    {
                                        var exchangeId = new ItemId(itemId);


                                        if (eventStatus == EventType.Deleted)
                                        {
                                        }
                                        else
                                        {
                                            if (string.IsNullOrEmpty(booking.BookingReference))
                                            {
                                                booking.BookingReference = $"Ref{booking.DatabaseId.ToString().PadLeft(6, '0')}";
                                            }

                                            EwsService.SetImpersonation(ConnectingIdType.SmtpAddress, booking.MailBoxOwnerEmail);

                                            var subAppointment = EwsService.GetAppointment(ConnectingIdType.SmtpAddress, booking.SiteMailBox, exchangeId, propertyIds);

                                            var parentAppt = EwsService.GetParentAppointment(subAppointment, propertyIds);

                                            meeting          = parentAppt.Item;
                                            meeting.Subject  = booking.Subject;
                                            meeting.Start    = booking.StartUTC;
                                            meeting.End      = booking.EndUTC;
                                            meeting.Location = booking.Location;
                                            //meeting.ReminderDueBy = DateTime.Now;
                                            meeting.SetExtendedProperty(EWSConstants.RefIdPropertyDef, booking.BookingReference);
                                            meeting.SetExtendedProperty(EWSConstants.DatabaseIdPropertyDef, booking.DatabaseId);
                                            meeting.Update(ConflictResolutionMode.AutoResolve, SendInvitationsOrCancellationsMode.SendOnlyToChanged);

                                            // Verify that the appointment was created by using the appointment's item ID.
                                            var item = Item.Bind(EwsService.Current, meeting.Id, new PropertySet(propertyIds));
                                            Trace.WriteLine($"Appointment modified: {item.Subject} && ReserveRoomAsync({booking.Location}) completed");

                                            if (item is Appointment)
                                            {
                                                Trace.WriteLine($"Item is Appointment");
                                            }
                                        }
                                    }
                                    else
                                    {
                                        if (string.IsNullOrEmpty(booking.BookingReference))
                                        {
                                            booking.BookingReference = $"Ref{booking.DatabaseId.ToString().PadLeft(6, '0')}";
                                        }

                                        EwsService.SetImpersonation(ConnectingIdType.SmtpAddress, booking.MailBoxOwnerEmail);

                                        meeting = new Appointment(EwsService.Current);
                                        meeting.Resources.Add(booking.SiteMailBox);
                                        meeting.Subject  = booking.Subject;
                                        meeting.Start    = booking.StartUTC;
                                        meeting.End      = booking.EndUTC;
                                        meeting.Location = booking.Location;
                                        //meeting.ReminderDueBy = DateTime.Now;
                                        meeting.SetExtendedProperty(EWSConstants.RefIdPropertyDef, booking.BookingReference);
                                        meeting.SetExtendedProperty(EWSConstants.DatabaseIdPropertyDef, booking.DatabaseId);
                                        meeting.Save(SendInvitationsMode.SendOnlyToAll);

                                        // Verify that the appointment was created by using the appointment's item ID.
                                        var item = Item.Bind(EwsService.Current, meeting.Id, new PropertySet(propertyIds));
                                        Trace.WriteLine($"Appointment created: {item.Subject} && ReserveRoomAsync({booking.Location}) completed");

                                        if (item is Appointment)
                                        {
                                            Trace.WriteLine($"Item is Appointment");
                                        }
                                    }

                                    // this should exists as this particular message was sent by the database
                                    var dbAppointment = _context.AppointmentEntities.FirstOrDefault(a => a.Id == booking.DatabaseId);
                                    if (dbAppointment != null)
                                    {
                                        dbAppointment.ExistsInExchange   = true;
                                        dbAppointment.SyncedWithExchange = true;
                                        dbAppointment.ModifiedDate       = DateTime.UtcNow;

                                        if (meeting != null)
                                        {
                                            dbAppointment.BookingId        = meeting.Id.UniqueId;
                                            dbAppointment.BookingChangeKey = meeting.Id.ChangeKey;
                                        }
                                        else
                                        {
                                            dbAppointment.IsDeleted = true;
                                        }

                                        if (string.IsNullOrEmpty(dbAppointment.BookingReference) ||
                                            !dbAppointment.BookingReference.Equals(booking.BookingReference))
                                        {
                                            dbAppointment.BookingReference = booking.BookingReference;
                                        }
                                    }

                                    var appointmentsSaved = _context.SaveChanges();
                                    Trace.WriteLine($"Saved {appointmentsSaved} rows");
                                }
                                catch (Exception dbex)
                                {
                                    Trace.WriteLine($"Error occurred in Appointment creation or Database change {dbex}");
                                }
                                finally
                                {
                                    //await receiver.CompleteAsync(message.SystemProperties.LockToken);
                                }
                            }
                            else
                            {
                                // purge / log it
                                await receiver.DeadLetterAsync(message.SystemProperties.LockToken);//, "ProcessingError", "Don't know what to do with this message");
                            }
                        }
                    }
                    catch (ServiceBusException e)
                    {
                        if (!e.IsTransient)
                        {
                            Trace.WriteLine(e.Message);
                            throw;
                        }
                    }
                }
            }
            await receiver.CloseAsync();
        }