We are doing Exchange web server synchronization with our application. To identify EWS changes we use; service.SyncFolderItems() method, like explain on MSDN. But, while doing initial sync it takes all the events in calendar, very older ones too. To avoid getting older events we need to use time period or Sync Start From time while requesting changes from SyncFolderItems() method.
1) Can SyncFolderItems() method accept user given time period when getting events from EWS ? & How ?
2) If not, Any workaround ?
There is a way to avoid older events in calendar using service.SyncFolderItems() method.
<SyncFolderItems>
<ItemShape/>
<SyncFolderId/>
<SyncState/>
<Ignore/>
<MaxChangesReturned/> <SyncScope/>
</SyncFolderItems>
That Ignore parameter will accept List of event Ids. and ignore them while syncing. To do that , First we need to retrieve older event IDs, Exchange will only accept two years old event
DateTime startDate = DateTime.Now.AddYears(-2); //start from two years earlier
DateTime endDate = DateTime.Now.AddMonths(-1); // End One Month before,
//you can use Convert.ToDateTime("01/01/2013"); what ever date you wanted.
Create Item id List;
List<ItemId> itmid = new List<ItemId>();
Create Calendar View object;
CalendarView cView = new CalendarView(startDate, endDate);
Retrieve Appointments;
// Retrieve a collection of appointments by using the calendar view.
FindItemsResults<Item> appointments = service.FindItems(WellKnownFolderName.Calendar, cView);
Or you can use this, But previous code have some optimization. (Google)
FindItemsResults<Appointment> appointments = service.FindAppointments(WellKnownFolderName.Calendar, cView);
Add retrieve event ids into list,
foreach (var item in appointments)
{
itmid.Add(item.Id);
}
Finally, in your SyncFolderItems method will looks like this;
service.SyncFolderItems(new FolderId(WellKnownFolderName.Calendar), PropertySet.IdOnly, itmid, 10, SyncFolderItemsScope.NormalItems, sSyncState);
Hope this will help any of you.
Currently, SyncFolderItems only supports synchronizing the entire mailbox. It doesn't support synchronizing starting from a specific time period. This type of request has been shared with the product planners. Hopefully we'll see this type of functionality.
In terms of workarounds, you could:
1) Sync all of the events with only the ItemId. Throw away items don't need.
2) Perform a FindItems with your intended time period, use GetItem (Bind) to get the events, and then use notifications to learn when a new item arrives, or when an item is updated. What you won't get with this is what has changed. For new items, this isn't an issue. But for updated items, you'll have to perform a GetItem (Load) and then diff the updated and old items to see what has changed.
Related
I was developing one application where I want to retrieve the available rooms from the "All Rooms" of the outlook address book. I am able to retrieve all the room entries from "All Rooms" Address Entry List. And then able to search for individual room's availability by calling AddressEntry.GetFreeBusy().
But the problem I am facing is the time performance of the code. If the number of rooms is high(let's say 500) then the time take to search availability of the room(worst case scenario where available room locates near to last of the list) is very high.
Microsoft.Office.Interop.Outlook.Application app = new Microsoft.Office.Interop.Outlook.Application()
var allRooms = app.Session.AddressLists["All Rooms"].Cast<Microsoft.Office.Interop.Outlook.AddressEntry>().ToLis();
DateTime today = DateTime.Today;
foreach(var room in allRooms)
{
//the below function will return the room status in a string of 1&0 for an interval of 1 min
string status = room.GetFreeBusy(today, 1, true); //sequentially calling this method is costly. What improvement can I do here?
//process the status and make some if free for certain time period add to list of available list
}
The GetFreeBusy method accepts three parameters and the default value for the MinPerChar parameter is 30 minutes. But your code only checks the first minute of the appointment. You need to go over the whole duration of your meeting (at least 30 minutes). Take a look at the similar forum thread.
If you are a .Net Developer then use Microsoft Graph APIs for this purpose. I used
POST /me/calendar/getSchedule
POST /users/{id|userPrincipalName}/calendar/getSchedule
from to achieve this. You can login as your userid and use ME option or you can use application mode login to login and use {id|userPrincipalName} to get calendar details for a room.
This link provides the basics on how to login and have good examples for Graph in general.
https://developer.microsoft.com/en-us/graph/graph-explorer
Ref:
https://learn.microsoft.com/en-us/graph/api/calendar-getschedule?view=graph-rest-1.0&tabs=http
An external process emails messages to an Exchange mailbox. I then have an Exchange Web Services (EWS) 2.0 application to fetch those email messages for subsequent processing. The EWS application is designed to fetch messages received on the current date, eg "received:today" in AQS parlance. The messages, however, are never retrieved - none are returned to the ItemView of the FindItems method:
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013);
// sharedMailbox is a FolderId type set to a valid well-known location not reproduced here
FindItemsResults<Item> findResults = service.FindItems(sharedMailbox,"(subject:flotsam) AND (received:today)", new ItemView(20));
On a lark, changing this date to "received:yesterday" finally caught the desired messages, but an inspection of each message's explicit received date for each of the messages was not yesterday, but today:
Console.WriteLine(item.DateTimeReceived.ToLocalTime());
Console.WriteLine(item.DateTimeReceived.ToUniversalTime());
10/24/2016 1:05:38 AM
10/24/2016 6:05:38 AM
I suspected an oddity in the translation of the constants, and opted to provide explicit dates. However, explicitly defining the receipt date in "received:MM/DD/YYYY" form (rather than 'today' or 'yesterday') exhibited the same results:
FindItemsResults<Item> findResults = service.FindItems(sharedMailbox,"(subject:flotsam) AND (received:10/23/2016)", new ItemView(20));
Although the date is yesterday, this code did fetch messages retrieved today, which is 10/24/2016 (not 10/23/2016). Code specifying today, which should fetch the desired messages, actually fetched no messages:
FindItemsResults<Item> findResults = service.FindItems(sharedMailbox,"(subject:flotsam) AND (received:10/24/2016)", new ItemView(20));
In effect, the explicit dates are behaving exactly as the 'received:yesterday' and 'received:today' querystring values, so that implies these constants are simply being mapped to the values I hard-coded.
I then suspected timezone differences, or UTC conversion differences, but our local timezone is behind UTC, meaning that specifying "received:today" should, in reality, work in fetching messages received....today.
I am at a loss to know or understand why we are seeing this single-day discrepancy in fetched messages. What aspect of message date interpretation am I handling incorrectly?
EDIT: Per suggestion in comments, I modified the FindItems call to use a SearchFilter object, using a DateTime value of Now minus one day (actually, a value 24 hours from DateTime.Now. This created a datetime value that crossed into 10/23/2016, and retrieved the messages received today. So I cannot be sure that the filter really found the messages because they were received on 10/24, or because the search date range included yesterday (which caused the other searches to work):
SearchFilter sf = new SearchFilter.IsGreaterThan(ItemSchema.DateTimeReceived, new DateTime.Now.AddDays(-1));
Taking a cue from this, I modified the filter to use a DateTime without an explicit time element:
SearchFilter sf = new SearchFilter.IsGreaterThan(ItemSchema.DateTimeReceived, new DateTime(2016,10,24));
This search filter worked, returning both messages received today. This tends to suggest some semantic hiccup or uncertainty with the 'today' and 'yesterday' keywords.
I would prefer to find an AQS-based solution, if possible, or at least find a better understanding of why the querystring values aren't working as expected.
If you are using AQS with Exchange, you are allowed to use relational operators in the search query with date values and relative date keywords.
Although odd, the following expression worked the way you expected the relative date keyword "today" to work:
>Yesterday
Excerpted from "How to: Perform an AQS search by using EWS in Exchange"
"Date value types can also be compared with relational operators like greater than or less than, or specified as a range with the range operator ... For example, received:>11/30/2013, sent:>=yesterday, and received:12/1/2013..today are all valid query strings."
I am trying to query Google's Calendar API to get a list with Events that matches the List with EventIds.
So i have a list of EventIds and i want to get the corresponding events from Google Calendar.
I found the parameter 'q' with the following description:
"Free text search terms to find events that match these terms in any field, except for extended properties. Optional."
It's from this page: https://developers.google.com/google-apps/calendar/v3/reference/events/list
My problem is that i have no idea what to pass into 'q' (no documentation on that page or any reference to where that can be found) and if this parameter can help me get the list back with the specific ids?
The API method you found is GET https://www.googleapis.com/calendar/v3/calendars/calendarId/events and is used to get a list of all events from a particular calendar. This is done by changing calendarId to the ID of the calendar you want to get events from. q is an optional parameter you can pass when you make this GET request that limits the events returned from the calendar to those events matching a particular search term.
Since you already have a list of eventId's, this is not the method you are looking for. You should instead use the Events.get method: GET https://www.googleapis.com/calendar/v3/calendars/calendarId/events/eventId. In this URI, you replace calendarId with the ID of the calendar that has the event and you replace eventId with the particular event id from your list of events. You can make repeated calls to this API URI while changing the eventId each time to get the Event resource for each of the events in your list.
The Events.get method above will work for you, but is not the most efficient way to retrieve your events. You can look into batch requests in the future to group all your API calls together to more efficiently retrieve the events.
I'm working on an application that displays (highlighted) the dates on which a certain event will occur.
In the database that I have to use there is a table that contains date intervals or collections of dates that have special meaning (like collection of holidays, school breaks...). When an event is defined, the user defines on which day(s) that event occurs (if it occurs periodically), but the user can also define that that particular event does or does not occur on special interval.
For instance - there can be an event that occurs every Sunday, if that days is not a holiday.
Now, I've solved the periodical part by reading data from the database for that event (determining on which day does that event occur) and then filling a list with dates that will be highlighted (for graphical representation I use MotnhCalendar and its BoldedDates array):
for (DateTime day = start; day < end;day = day.AddDays(1))
{
if (Sunday && day.DayOfWeek == DayOfWeek.Sunday)
{
MarkedDates.Add(day);
}
monthCalendar1.BoldedDates = MarkedDates.ToArray();
}
Now, for this code to work properly, I need to skip the dates that belong to a special interval (in this case if that date is a holiday). It could be easily done by adding another condition into the if clause:
!SpecialDates.Contains(day)
The problem is that I don't know how to fill the list with these special dates from the database. I can't simply "hard code" it, because these special date collections/intervals can be changed at any time. So, my question is - how can I, by using SQL and C# commands, read data from database and save it in the list.
Thanks
As it looks like your using SQL Server 2008 R2 I would recommend using an ORM tool like ADO.NET Entity Framework to access your database - best going with the latest release EF 5.
There are tons of tutorials online on how to get up & running with it - a good one being Creating Model Classes with the Entity Framework.
To give you an idea of how simple it makes it, here is an example of the minimal amount of code you would need to achieve what it is your looking to do:
using (var db = new MyDbContext())
{
var specialDates = db.SpecialDatesTable.ToList();
}
We are currently working on creating a sync service between our product and Exchange using Exchange Web Services Managed API. Specifically we want to sync (on a time schedule) specific Appointments back and forth on a users calender. As part of the sync, we don't necessarily want to sync ALL appointments, but have built up some complex SearchFilters to return only the appointments we want. Our problem is that in order to use the SearchFilters, we need to use the ExchangeService.FindItems method, but this method only returns the Master Recurrence of recurring events. Our other option is to use ExchangeService.FindAppointment, this will do the Recurrence Expansion for us, but has the new problem that we can only limit the result appointments using a start and end date. Looking at how the ExchangeService.FindAppointment is implemented, we can see that it is implemented using the FindItems method, which leads me to believe that I should be able to tell the ExchangeService.FindItems method to do a recurrence expansion.
How can I get a list of expanded appointments from exchange using a complex SearchFilter?
Just found this on MSDN:
http://msdn.microsoft.com/en-us/library/hh148195(v=exchg.140).aspx
Considerations for searching calendar appointments
Calendar appointments are a special case for searches. Some calendar appointments, such as recurring appointments, can have exceptions and deleted occurrences. To ensure that the Exchange server expands recurring appointments when searching a calendar folder, you need to use calendar paging. When you use calendar paging, however, you can’t use any other search restrictions. This means that if, for example, you want to display all of the calendar appointments this month for a particular organizer, you can't create a search filter that is based on the organizer. Instead, you can use the CalendarView class to query for all appointments in the month and then filter the appointments on the client side based on the organizer. The following example shows how to use a calendar view to search for appointments in a calendar.
For anyone that finds guxiyou's solution with FindAppointments/CalendarView impractical, my solution below. CalendarView is especially not convenient in a situation of automatic synchronization where you'd preferably use a "last modified" filter instead of retrieving everything and filtering client-side, which is not very performant.
I used the regular FindItems way which does support filters, and while iterating the appointments checked AppointmentType, which in case of a RecurrenceMaster type would find the linked occurrences and add these to the to-be-synced list.
Below the method to subsequently get the occurrences of these appointments. Recurrent patterns with no end date are ignored as these would make your loop infinite. These recurrences would have to be handled differently to be synchronized anyway, unless you limit the synchronization window.
private IEnumerable<Appointment> GetRecurrentAppointments(Appointment masterAppointment)
{
Recurrence recurrence = masterAppointment.Recurrence;
if (recurrence == null || !recurrence.HasEnd)
yield break;
for (int i = 1; i <= recurrence.NumberOfOccurrences; i++)
{
Appointment occurrence = Appointment.BindToOccurrence(ExchangeServiceProxy, masterAppointment.Id, i);
yield return occurrence;
}
}