예제 #1
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();
        }
예제 #2
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();
        }