This week at TechEd Europe 2009, Microsoft officially launched Exchange Server 2010 and the Exchange Web Services Managed API 1.0 SDK. This API provides a managed wrapper around Exchange Web Services, eliminating the need to work directly with SOAP or with proxy classes generated when adding a web reference to your environment’s Exchange Web Services url.
The release version of EWSMA includes improved support for Exchange Web Services features such as:
- Free/Busy
- Autodiscover
- Timezones
- Impersonation
- Search
In this post, I’ll demonstrate using EWSMA to query the Exchange free/busy service to find a meeting time that is most suitable for a set of participants.
Referencing the Exchange Web Services Managed API 1.0 SDK
The Exchange Web Services Managed API 1.0 SDK is installed by default to C:\Program Files\Microsoft\Exchange\Web Services\1.0, you need to reference Microsoft.Exchange.WebServices.dll.
Improved Autodiscover
The Exchange Autodiscover service provides clients with a way to retrieve the url to use to connect to Exchange Web Services. For a majority of deployments, there is one url for Exchange Web Services. However, consider large, global Exchange deployments…the Autodiscover server can for example “auto discover” the most geographically appropriate web service endpoint for a client such as Outlook to connect to.
If you’ve worked with Exchange Web Services in the past, you know that autodiscover’ing the url for Exchange Web Services involved a lot of code, this is what it looks like now:
1: ExchangeService service = new ExchangeService();
2: service.AutodiscoverUrl(String.Format(
3: "{0}@{1}.com",
4: Environment.UserName,
5: Environment.UserDomainName));
Set up Availability Options
Before querying the free/busy service, you need to specify some options that the service will use to retrieve a list of meeting time suggestions – this is represented by a class called AvailabilityOptions.
1: AvailabilityOptions availabilityOptions = new AvailabilityOptions();
2: availabilityOptions.MeetingDuration = 60;
3: availabilityOptions.MaximumNonWorkHoursSuggestionsPerDay = 4;
4: availabilityOptions.MinimumSuggestionQuality = SuggestionQuality.Good;
5: availabilityOptions.RequestedFreeBusyView = FreeBusyViewType.FreeBusy;
Check out the SDK documentation to explore other options you can set when creating an instance of AvailabilityOptions. In this case, we’re looking for a 60 minute time slot, allowing some flexibility to schedule the meeting outside of working hours, setting the minimum suggestion quality to Good, and only requesting the FreeBusy view after querying the service.
Get Availability Results
First, create a List<AttendeeInfo> to store the list of contacts to include in the request to the free/busy service. In this case, you can see how to add different attendee types to the list, e.g. the organizer, a required attendee, and a room resource.
1: List<AttendeeInfo> attendees = new List<AttendeeInfo>();
2:
3: attendees.Add(
4: new AttendeeInfo()
5: {
6: SmtpAddress = "rl@fabrikam.com",
7: AttendeeType = MeetingAttendeeType.Organizer
8: });
9:
10: attendees.Add(
11: new AttendeeInfo()
12: {
13: SmtpAddress = "sc@fabrikam.com",
14: AttendeeType = MeetingAttendeeType.Required
15: });
16:
17: attendees.Add(
18: new AttendeeInfo()
19: {
20: SmtpAddress = "boardroom@fabrikam.com",
21: AttendeeType = MeetingAttendeeType.Room
22: });
With the attendee list set up, create an instance of GetUserAvailabilityResults to store the meeting suggestions returned by the free/busy service.
1: GetUserAvailabilityResults availabilityResults =
2: service.GetUserAvailability(
3: attendees,
4: new TimeWindow(DateTime.Now, DateTime.Now.AddDays(1)),
5: AvailabilityData.FreeBusyAndSuggestions,
6: availabilityOptions);
I want to point out a gotcha here. When AvailabilityOptions.RequestedFreeBusyView is set to FreeBusyViewType.FreeBusy, the time window for the call to GetUserAvailability needs to be at least 24 hours. I’m not sure of the reasoning for this but if its set to a shorter time window, the call sometimes throws an exception about an invalid time window.
Explore Suggested Meeting Times
You can now explore the suggested meeting times returned by the free/busy service.
The results are in the form of a List<Suggestion> where Suggestion describes the date and quality of the suggestion, and a collection of individual TimeSuggestions. A TimeSuggestion describes any conflicts at the suggested time, whether or not the suggestion occurs during working hours, the suggested time and quality of the meeting.
Unless you set a time window of more than 1 day, you’ll probably just want to grab availabilityResults.Suggestions[0] and pick the most suitable TimeSuggestion in availabilityResults.Suggestions[0].TimeSuggestions according to whatever criteria are suitable for your application.
Book the Meeting
It’s just as easy to book the appointment directly from your application. Assuming that suggestion is an instance of a TimeSuggestion that you want to book:
1: // Create the appointment and set its properties
2: Appointment appointment = new Appointment(service);
3: // Set the appointment title
4: appointment.Subject = "Team Meeting";
5: // Set the appointment start and end time
6: appointment.Start = suggestion.MeetingTime;
7: appointment.End = suggestion.MeetingTime.AddMinutes(availabilityOptions.MeetingDuration);
8: // Add the conference room as a meeting resource
9: appointment.Resources.Add("Board Room", boardroom@fabrikam.com);
10: // Set the meeting location to display name of the conference room
11: appointment.Location = "Board Room";
12: // Save the appointment
13: appointment.Save();
Summary
You’ve seen how easy it is to include Outlook-style functionality into your custom applications. This didn’t use to be as simple, unless you loved working with WebDAV or CDO, or writing some sweet asynchronous WebRequest code…