I'm trying to fetch FreeBusy data from my Google calendar using the .NET client API V3.
The following code allows me to login using a service authentication and fetch the calendar list and calendar settings. I can also fetch the events as shown.
To make this work I have shared my calendar with my development Id:
<my-id>@developer.gserviceaccount.com
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Google.Apis.Calendar;
using Google.Apis.Calendar.v3;
using Google.Apis.Authentication;
using Google.Apis.Authentication.OAuth2;
using Google.Apis.Authentication.OAuth2.DotNetOpenAuth;
using DotNetOpenAuth.OAuth2;
using System.Diagnostics;
using Google.Apis.Calendar.v3.Data;
using System.Security.Cryptography.X509Certificates;
using Google.Apis.Discovery;
using Google.Apis.Drive.v2;
using Google.Apis.Util;
namespace consoleGoogleResearch
{
class Program
{
private const string SERVICE_ACCOUNT_EMAIL = "<your-value>@developer.gserviceaccount.com";
private const string SERVICE_ACCOUNT_PKCS12_FILE_PATH = @"<path-to\<your-value>-privatekey.p12";
/// <summary>
/// Build a Calendar service object authorized with the service account.
/// </summary>
/// <returns>Drive service object.</returns>
static CalendarService BuildCalendarService()
{
AssertionFlowClient client = new AssertionFlowClient(
GoogleAuthenticationServer.Description, new X509Certificate2(SERVICE_ACCOUNT_PKCS12_FILE_PATH, "notasecret", X509KeyStorageFlags.Exportable))
{
Scope = CalendarService.Scopes.Calendar.GetStringValue(),
ServiceAccountId = SERVICE_ACCOUNT_EMAIL,
};
OAuth2Authenticator<AssertionFlowClient> authenticator = new OAuth2Authenticator<AssertionFlowClient>(client, AssertionFlowClient.GetState);
return new CalendarService(authenticator);
}
public static void Main(string[] args)
{
var service = BuildCalendarService();
// Get the calendar service
Google.Apis.Calendar.v3.CalendarListResource.ListRequest clrq = service.CalendarList.List();
var result = clrq.Fetch();
// Prove we can get the settings.
SettingsResource.ListRequest slr = service.Settings.List();
var sr = slr.Fetch();
try
{
Console.WriteLine("Calendars: ");
foreach (CalendarListEntry calendar in result.Items)
{
Console.WriteLine("{0}", calendar.Id);
Console.WriteLine("\tAppointments:");
Google.Apis.Calendar.v3.EventsResource.ListRequest elr = service.Events.List(calendar.Id);
var events = elr.Fetch();
if (events.Items != null)
{
foreach (Event e in events.Items)
{
Console.WriteLine("\tSummary: {0}, Location: {1}", e.Summary, e.Location);
if (e.IsAllDayEvent())
{
Console.WriteLine("\t\tAll Day: {0}", e.Start.GetDateTime().ToLongDateString());
}
else
{
Console.WriteLine("\t\tFrom: {0}", e.Start.GetDateTime());
Console.WriteLine("\t\tTo: {0}", e.End.GetDateTime());
}
if (e.Attendees != null)
{
foreach (var att in e.Attendees)
{
Console.WriteLine("Attendee:\t\t\t{0}<{1}>", att.DisplayName, att.Email);
}
}
Console.WriteLine();
}
}
}
}
catch (Exception ex)
{
log.DebugFormat("Error: {0}", ex.Message);
}
// Attempt to get free busy data.
FreebusyResource.QueryRequest fbq = service.Freebusy.Query(new FreeBusyRequest());
FreeBusyRequestItem c = new FreeBusyRequestItem();
c.Id = "<your calendar id>";
fbq.Body.Items = new List<FreeBusyRequestItem>();
fbq.Body.Items.Add(c);
fbq.Body.TimeZone = "Europe/London";
fbq.Body.TimeMin = "2013-01-101T00:00:00.000Z";
fbq.Body.TimeMax = "2013-01-301T00:00:00.000Z";
// This call fails with global bad request
var fbres = fbq.Fetch();
Console.ReadKey();
}
}
static internal class Extensions
{
static internal DateTime GetDateTime(this EventDateTime edt)
{
if (String.IsNullOrEmpty(edt.DateTime))
{
if (String.IsNullOrEmpty(edt.Date))
{
return DateTime.MinValue;
}
else
{
return DateTime.Parse(edt.Date);
}
}
else
{
return DateTime.Parse(edt.DateTime);
}
}
static internal Boolean IsAllDayEvent(this Event e)
{
return (e.Start.DateTime == null && e.Start.Date != null);
}
}
}
However the code that attempts to fetch free busy information always receives a "bad request" error.
I have checked the request sent using fiddler and as far as I can see it is correct.
POST https://www.googleapis.com/calendar/v3/freeBusy?alt=json&prettyPrint=true HTTP/1.1
Authorization: Bearer <removed>
Content-Type: application/json; charset=utf-8
User-Agent: ConsoleApplication1 google-api-dotnet-client/ Win32NT/6.1.7601.65536 (gzip)
Host: www.googleapis.com
Content-Length: 144
Accept-Encoding: gzip, deflate
{"items":[{"id":"[email protected]"}],"timeMax":"2013-01-301T00:00:00.000Z","timeMin":"2013-01-101T00:00:00.000Z","timeZone":"Europe/London"}
Can anyone tell me why I'm receiving the bad request error and more importantly how to fix it?
Many thanks
Chris.