Introduction
I searched and searched, but I couldn't find any complete examples which showed how to directly work with the Google Calendar API, so after piecing together
my solution from many many different examples, I decided to publish this small project as much for my own needs to cement the methodologies in my own mind as to help
others who may also need to do the same.
Background
There are several similar articles that I draw from, one of those is here on The Code Project: Using Google Calendar with ASP.NET
by Igor Alekseev.
In fact, up to the point when I found his article, I'd been having a very hard time getting my events to go into the particular calendar where I wanted them to go,
and Igor's code was the first that I'd come across that clearly defined out which URIs were which for the Google service.
I've sort of mimicked Igor's method of passing the CalendarService
object ByRef
to subsequent functions, because this is key in avoiding getting smacked
by the Google Ban Hammer, which can provide some interesting errors in the middle of your testing!
Most importantly of all, however, might have been his intuition about this line of code:
calFeed.Entries(x).Id.AbsoluteUri.Substring(63)
Up until I discovered "substring(63)
" I was having a helluva time getting reliable calendar IDs!
Thanks Igor!
Using the Code
I strived to maintain two different methodologies with this code, one being a single call, and the other being a compound call... the single call is used in my own application when,
for instance, a new row is added to a table of our database. I can make one call and push that data to the calendar... that method also makes it very well suited for Web Service calls.
The other method is nice when you need to perform multiple steps from your client code, it allows you to get your CalendarService
object in one call, and then continually reuse
it in your subsequent actions so that your login is not repeated against Google for each call.
A single call will usually look like this:
Dim g As New GoogleCalSvc, str as String
str = g.A1ListMyCalendars
While a multiple or compound call might look like this:
Dim g As New GoogleCalendar_KellyTours, str as string
str = str & g.FindEvent(g.GetCalendarService, "123")
Or maybe even like this, where the service object, s
, is used repeatedly:
Dim g As New GoogleCalSvc
Dim s = g.GetCalendarService
Dim out As String = g.FindEvent(s, "Primary", "123")
out = out & g.FindEvent(s, "Primary", "456")
out = out & g.FindEvent(s, "Primary", "789")
Me.output.InnerHtml = out
Points of Interest
Once you get over the fact that most of the code and documentation on the internet is for projects in C#, with a little work, you end up finding that the API
is actually pretty easy to work with. With continued development, this project could easily progress into a full featured wrapper interface for all calendar access.
In my own usage, I also have extra database code right within this file, so I can just pass a record ID to some functions, and they automatically publish, update, etc.,
the needed record to/from the calendar in a pretty much real time fashion.
Code Listing
Imports System.IO
Imports System.Data.SqlClient
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.ComponentModel
Imports Google.GData.Calendar
Imports Google.GData.Client
Imports Google.GData.Extensions
<System.Web.Services.WebService(Namespace:="http://localhost/GoogleCalendarInVBNET/")> _
<System.Web.Services.WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<ToolboxItem(False)> _
Public Class GoogleCalSvc
Inherits System.Web.Services.WebService
Private Const userName As String = "SomeUser@GMailOrGoogleAppsDomain.com"
Private Const userPassword As String = "SomeStrongPassword"
Private feedUri As String = _
"https://www.google.com/calendar/feeds/default/private/full?max-results=9999"
Private Const feedOwnCalendars As String = _
"https://www.google.com/calendar/feeds/default/owncalendars/full"
Private Const CALENDAR_TEMPLATE As String = _
"https://www.google.com/calendar/feeds/{0}/private/full?max-results=9999"
#Region "Single Call Public Functions"
<WebMethod()> _
Public Function A1ListMyCalendars() As String
Dim str As String
str = ListAllCalendars()
Return str
End Function
<WebMethod()> _
Public Function A1CreateEvent(ByVal stCalName As String, ByVal strWhere As String, _
ByVal strStart As String, ByVal strEnd As String, _
ByVal strSubject As String, ByVal strBody As String, _
ByVal strRecurData As String) As String
Return CreateEvent(GetCalendarService, stCalName, strWhere, _
strStart, strEnd, strSubject, strBody, strRecurData)
End Function
<WebMethod()> _
Public Function A1DeleteEvent(ByVal intTripNo As Integer, ByVal stCalName As String) As String
Return DeleteEvent(GetCalendarService, intTripNo, stCalName)
End Function
<WebMethod()> _
Public Function A1ListUsersCalendars() As String
Dim Service As CalendarService = GetCalendarService()
Dim query As New FeedQuery
query.Uri = New Uri(feedUri)
Dim calFeed As AtomFeed
calFeed = Service.Query(query)
Dim str As String = ""
For x As Integer = 0 To calFeed.Entries.Count - 1
str = str & calFeed.Entries(x).Title.Text
If calFeed.Entries.Count > 1 And x < (calFeed.Entries.Count - 1) Then
str = str & ", " & calFeed.Title.Text & vbCrLf
End If
Next
Return str
End Function
#End Region
#Region "Public GET Functions"
Public Function GetCalendarService() As CalendarService
Dim Service As CalendarService = New CalendarService("My-exampleApp-1")
Service.setUserCredentials(userName, userPassword)
Return Service
End Function
<WebMethod()> _
Public Function GetCalendarID(ByRef Service As CalendarService, ByVal strCalName As String) As String
Dim query As New FeedQuery
Dim str As String = ""
query.Uri = New Uri(feedOwnCalendars)
Dim calFeed As AtomFeed
calFeed = Service.Query(query)
For x As Integer = 0 To calFeed.Entries.Count - 1
If calFeed.Entries(x).Title.Text = strCalName Then
str = calFeed.Entries(x).Id.AbsoluteUri.Substring(63)
End If
Next
Return str
End Function
<WebMethod()> _
Public Function GetCalendarURI(ByRef Service As CalendarService, ByVal stCalName As String) As String
Dim stURI As String = String.Format(CALENDAR_TEMPLATE, GetCalendarID(Service, stCalName))
If stCalName = "Primary" Then
stURI = feedUri
End If
Return stURI
End Function
#End Region
<WebMethod()> _
Public Function ListAllCalendars() As String
Dim Service As CalendarService = GetCalendarService()
Dim query As New FeedQuery
query.Uri = New Uri(feedOwnCalendars)
Dim calFeed As AtomFeed
calFeed = Service.Query(query)
Dim str As String = ""
For x As Integer = 0 To calFeed.Entries.Count - 1
str = str & calFeed.Entries(x).Title.Text & "|" & _
calFeed.Entries(x).Id.AbsoluteUri.Substring(63) & vbCrLf
Next
Return str
End Function
<WebMethod()> _
Public Function DeleteAllEvents(ByVal strCalName As String) As String
Dim str As String = ""
Dim Service As CalendarService = GetCalendarService()
Dim query As New FeedQuery
query.Uri = New Uri(GetCalendarURI(Service, strCalName))
Dim calFeed As AtomFeed
calFeed = Service.Query(query)
If calFeed.Entries.Count > 0 Then
For x As Integer = 0 To calFeed.Entries.Count - 1
str = str & calFeed.Entries(x).Title.Text & vbCrLf
calFeed.Entries(x).Delete()
Next
End If
Return str
End Function
Public Function DeleteEvent(ByRef Service As CalendarService, _
ByVal strSearchFor As String, ByVal stCalName As String) As String
Dim str As String = ""
Dim query As New FeedQuery
query.Uri = New Uri(GetCalendarURI(Service, stCalName))
query.Query = strSearchFor
Dim sFeed As EventFeed = Service.Query(query)
Dim Exists As Boolean = False
If sFeed.TotalResults > 0 Then
Exists = True
Dim calFeed As AtomFeed
calFeed = Service.Query(query)
If calFeed.Entries.Count > 0 Then
For x As Integer = 0 To calFeed.Entries.Count - 1
str = str & calFeed.Entries(x).Title.Text
calFeed.Entries(x).Delete()
Next
End If
End If
Return str
End Function
Private Function CreateEvent(ByRef Service As CalendarService, _
ByVal strCalName As String, _
ByVal strWhere As String, _
ByVal strStart As String, _
ByVal strEnd As String, _
ByVal strSubject As String, _
ByVal strBody As String, _
ByVal strRecurData As String) As String
Dim entry As New EventEntry
entry.Title.Text = strSubject
entry.Content.Content = strBody
Dim eventLocation As New Where
eventLocation.ValueString = strWhere
entry.Locations.Add(eventLocation)
Dim eventTime As New [When](strStart, strEnd)
entry.Times.Add(eventTime)
Dim postUri As Uri = New Uri(GetCalendarURI(Service, strCalName))
Dim insertedEntry As AtomEntry = Service.Insert(postUri, entry)
Return insertedEntry.ToString
End Function
Public Function FindEvent(ByRef Service As CalendarService, _
ByVal strCalName As String, ByVal strSearchFor As String) As String
Dim strOut As String = ""
Dim query As EventQuery = New EventQuery
query.Uri = New Uri(GetCalendarURI(Service, strCalName))
query.Query = strSearchFor.ToString
Dim calFeed As EventFeed = Service.Query(query)
Dim feedEntry As EventEntry
If calFeed.TotalResults > 0 Then
For Each feedEntry In calFeed.Entries
strOut = strOut & (feedEntry.Title.Text) & vbCrLf
Next
Else
strOut = "No Results found"
End If
Return strOut
End Function
<WebMethod()> _
Public Function ListUserEvents() As String
Dim strOut As String = ""
Dim query As EventQuery = New EventQuery
Dim service As CalendarService = GetCalendarService()
query.Uri = New Uri(GetCalendarURI(service, "Primary"))
Dim calFeed As EventFeed = service.Query(query)
Dim feedEntry As EventEntry
For Each feedEntry In calFeed.Entries
strOut = strOut & (feedEntry.Title.Text) & vbCrLf
Next
Return strOut
End Function
<WebMethod()> _
Public Function ListEvents(ByVal strCalName As String) As String
Dim strOut As String = ""
Dim query As EventQuery = New EventQuery
Dim Service As CalendarService = GetCalendarService()
query.Uri = New Uri(GetCalendarURI(Service, strCalName))
Dim calFeed As EventFeed = Service.Query(query)
Dim feedEntry As EventEntry
For Each feedEntry In calFeed.Entries
strOut = strOut & (feedEntry.Title.Text) & vbCrLf
Next
Return strOut
End Function
<WebMethod()> _
Public Function DeDupeEvents(ByVal strCalName As String) As String
Dim strOut As String = "", strVal As String = ""
Dim vals As New Collection
Dim query As EventQuery = New EventQuery
Dim service As CalendarService = GetCalendarService()
query.Uri = New Uri(GetCalendarURI(service, strCalName))
Dim calFeed As EventFeed = service.Query(query)
Dim feedEntry As EventEntry
For Each feedEntry In calFeed.Entries
strVal = (feedEntry.Title.Text)
If Not vals.Contains(strVal) Then
strOut = strOut & strVal
vals.Add(strVal, strVal)
Else
feedEntry.Delete()
End If
Next
Return strOut
End Function
End Class
History
- 12/31/2011 - This is my first publishing of this article and code, and I'm sure there'll need to be some updates as this is the first time that I've separated
it from the rest of my application.