none
EWS Managed API: FindAppointments + LoadPropertiesForItems RRS feed

  • General discussion

  • The EWS Managed API makes it easy to retrieve a list of all appointments in a calendar, including occurrences of recurring appointments, using the ExchangeService.FindAppointments method. FindAppointments however translates into an EWS FindItem Web service call under the covers, and FindItem is not able to return all the properties one may need on the retrieved appointments. For instance, FindItem cannot return the Body property.

    ExchangeService exposes another method, LoadPropertiesForItems that makes it possible to load the properties of multiple items in one call to EWS (it translates into a batch GetItem Web service call under the covers). Unfortunately, the results of a call to FindAppointments cannot be directly passed to LoadPropertiesForItems, which takes an argument of type IEnumerable<Item> whereas FindItemsResults<Appointment> is of type IEnumerable<Appointment>.

    One simple solution to this is to create an intermediate list of type List<Item> and add all the appointments from the FindAppointments results:
    FindItemsResults<Appointment> findResults = service.FindAppointments(
        WellKnownFolderName.Calendar,
        new CalendarView(DateTime.Now, DateTime.Now.AddDays(7)));
    
    List<Item> items = new List<Item>();
    
    foreach (Appointment appointment in findResults)
    {
        items.Add(appointment);
    }
    
    service.LoadPropertiesForItems(items, PropertySet.FirstClassProperties);
    
    There are two main drawbacks to this approach:
    • There is extra code to write,
    • An intermediate list is created, consuming twice as much memory as should be necessary.

    Fortunately, thanks to Linq, it is possible to write something much cleaner that does not create an intermediate list:
    FindItemsResults<Appointment> findResults = service.FindAppointments(
        WellKnownFolderName.Calendar,
        new CalendarView(DateTime.Now, DateTime.Now.AddDays(7)));
    
    service.LoadPropertiesForItems(
        from Item item in findResults select item,
        PropertySet.FirstClassProperties);
    
    Happy coding!

    David Claux | Program Manager - Exchange Web Services
    Monday, July 6, 2009 10:44 PM

All replies

  • Hello,

    Thanks for the post, it answered many questions for me about this issue.

    I'm relatively new to EWS Managed API stuff, but wouldn't the following simple code do the same trick?

    CalendarView cView = new CalendarView(DateTime.Now, DateTime.Now.AddDays(7);
    cView.PropertySet = PropertySet.FirstClassProperties;

    FindItemsResults<Appointment> findResults = service.FindAppointments(WellKnownFolderName.Calendar,cView);

    Or does this result differ somehow from your example? (at least I got the attribute that I was looking for out of this solution).

    br,
    -Juha
    Tuesday, August 11, 2009 6:45 AM
  • Hi,

    It might have been unclear in my original post, but FindAppointments (like FindItems) cannot return all first class properties. Thus one may need to load the full details of an item after a call to FindAppointment.

    A CalendarView's PropertySet property defaults to PropertySet.FirstClassProperties, so your code above is essentially the same as the one I posted. The problemis not the sepcified property set, it is that FindItems/FindAppointments are not able to retrieve all first class properties.
    David Claux | Program Manager - Exchange Web Services
    Tuesday, August 11, 2009 7:37 AM
  • Hello,

    Thanks for the quick clarification. Understood it now...

    thanks & br,
    -Juha
    Tuesday, August 11, 2009 8:57 AM
  • Just commented on the other thread.
    David Sterling | Microsoft Exchange Web Services | http://www.microsoft.com/MSPress/books/10724.aspx
    Monday, August 31, 2009 7:13 PM
  • Thanks for the example, it is very helpful.

    I just tested it, it works fine as soon as the findResults collaction is not empty.

    When it's empty, the Linq request fails.

    So I added the following test before :

    if (findResults.Count() > 0)
    {
    ...
    }


    Nicolas Faugout
    Tuesday, February 16, 2010 3:56 PM
  • Hi David. I post the same question for the different thread. Basically somehow "IsRecurring" field is only returned for FindAppointments if appointment is not recurring.

    Do you have any clue?

     

    Brian.

    Wednesday, August 4, 2010 8:59 PM
  • It seems like IsRecurring might not be loaded for non-recurring appointment.
    I am doing this following but it will be nice if API just returns null if a property is not loaded.

        try
                {
                    return appointment.IsRecurring;
                }
                catch (ServiceObjectPropertyException exception)
                {
                    return false;
                }
    Wednesday, August 4, 2010 9:43 PM
  • Or you can use IEnumerable<T> extension method Cast<T>() like this:
    FindItemsResults<Appointment> findResults = service.FindAppointments(
        WellKnownFolderName.Calendar,
        new CalendarView(DateTime.Now, DateTime.Now.AddDays(7)));
    service.LoadPropertiesForItems(
        findResults.Cast<Item>(),
        PropertySet.FirstClassProperties);
    Tuesday, May 17, 2011 8:02 PM
  • Hi All,

    I am trying to get Appointments from Exchange server using this API. But it looks like I have to load each property before reading. I am always getting following error.

    You must load or assign this property before you can read its value.

    Essentially, i am trying to get 1. subject 2. Organizer 3. Timespan 4. Body.

    So these are member of Appointment class except body which is member of Item class. Can some one please help me out in solving this problem.

     

    This is how my sample code looks like

            WellKnownFolderName.Calendar);
                FindItemsResults<Appointment> findResults = cf
                        .findAppointments(new CalendarView(startDate, endDate));
                List<Item> items = new ArrayList<Item>();
                 service.loadPropertiesForItems(findResults, new
                 PropertySet(ItemSchema.Subject));

                if (findResults.getItems().size() > 0) {

                    for (Appointment appt : findResults.getItems()) {
                        items.add(appt);
                        System.out.println("SUBJECT=====" + appt.getSubject());
                        System.out.println("Organizer========" + appt.getOrganizer());
                        System.out.println("Timespan========" + appt.getDuration().toString());
                    }
                    service.loadPropertiesForItems(items,
                            PropertySet.FirstClassProperties);
                   
                    for (Item appt : items) {
                       
                        // System.out.println("SUBJECT=====" + appt.getSubject());
                         System.out.println("BODY========" + appt.getBody());
                    }
                }

     

    Thanks

    raj

    Tuesday, January 24, 2012 11:34 PM
  • I found what i want.

    this is how my code looks like

     

    SimpleDateFormat formatter = new SimpleDateFormat(
                        "yyyy-MM-dd HH:mm:ss");
                formatter.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
                Date startDate = formatter.parse("2012-1-18 00:00:00");
                Date endDate = formatter.parse("2012-1-26 23:59:59");
                //CalendarFolder cf = CalendarFolder.bind(service,
                    //    WellKnownFolderName.Calendar);
               
                CalendarView cView = new CalendarView(startDate, endDate);
                cView.setPropertySet(PropertySet.FirstClassProperties);
                FindItemsResults<Appointment> findResults = service.findAppointments(WellKnownFolderName.Calendar, cView);
                service.loadPropertiesForItems(findResults,
                        PropertySet.FirstClassProperties);
                for (Appointment appt : findResults.getItems()) {
                    //items.add(appt);
                    System.out.println("SUBJECT=====" + appt.getSubject());
                    System.out.println("Organizer========" + appt.getOrganizer().getName());
                    System.out.println("Timespan========" + appt.getDuration().toString());
                   
                    System.out.println("BODY========" + appt.getBody());
                }
               

    Wednesday, January 25, 2012 12:31 AM
  • Hi , 

    I need to confirm that all occurences of an recurrencemaster shares the ICalUId or not , because somewhere on net read that all occurences share the same icaluid with reccurrence master

    i am using this property to filter out the all related occurences of a perticular master after doin FindAppointment for a date range .. for a time it was working fine but suddenly today i am getting different IcalUid for all occurences

    Please help me

    this is very urgent


    Thank you Dheeraj Kumar



    Tuesday, March 13, 2012 11:02 AM
  • All occurrences share the same ICalUID.
    Tuesday, March 13, 2012 10:26 PM
  • Thanx PythonCoder5 ,

    I also used to believe that but i have checked it at least for 10 times and yes it is giving me different ICalUid(s).

    My Exchange Server Version : 2007

    Please help me guys , or tell some other way to achieve this

    very urgent ....


    Thank you Dheeraj Kumar

    Wednesday, March 14, 2012 4:05 AM
  • Can you post your code showing how you are getting the master ICalUID?
    Wednesday, March 14, 2012 4:57 AM