Friday, 27 May 2011

Access Google public Calender and contacts of a g-mail account on Windows Azure


Google exposes Google API to access details of Google public calendar and also to access contacts for a g-mail account.  The scope of my investigation is restricted to APIs Google.Contacts and Google.GData.Calendar. 
The problem statement is:
The manager should be able to add meeting request to this subordinates. The manager will be the organizer of meeting, should be able to add event into calendar event attendees.  If there are some clashes it should be notified by application.
The scope is divided into  
  •  Make calendar as public
  •  Give permission to organizer to add events 
  • To get Calendar events
  • To add calendar event
  • To get all contacts
  • To add contact

APIs can be downloaded from location:
http://google-gdata.googlecode.com/svn/docs/index.html



Make Calendar as Public

Go to Calendar -><Name of calendar> calendar -> Calendar settings (Please see figure 1) -> Check “Make this Calendar as Public” (Please see Figure 2)




Figure 1: Calendar settings




Figure 2: Make calendar as public

Give permission to organizer to add events
The organizer of meeting should be given a particular permission to add event into calendar event attendees.  Please see figure 3.

Figure 3: To give permission to organizer to add event into calendar of Attendees.

To access Calendar
The public calendar can be access though Google Data APIs by giving a sharing link. This link is available in calendar setting. Please see figure mentioned below: 

Figure 4: Get link to access calendar 

There are 3 types of link that are provided:
1.       XML
2.       ICAL
3.       HTML
To access calendar, link that is provided by XML button should be used.


To access events by Google APIs
    To add/ remove/ view events of attendees, project should have reference of
usingGoogle.GData.Calendar;
using Google.GData.Client;
using Google.GData.Extensions;
     
     To access contacts from Google APIs
     To access contacts though google APIs, project should have reference of
usingGoogle.GData.Contacts;
using Google.GData.Client;
using Google.GData.Extensions;


   Code Snippets:
     a.   To get Calendar events


CalendarServiceoSrv = newCalendarService("GoogleAPIs_Cal_V1");
ArrayListentryList = newArrayList(50);

EventQueryoQuery = newEventQuery();
oQuery.Uri = newUri(
"https: <Calendar URI> @group.calendar.google.com/private/full.");
if (strUserName != null&&strUserName.Length> 0)
                {
oSrv.setUserCredentials(strUserName, strPwd);
                }
oQuery.StartTime = DateTime.Now.AddHours(-11);
oQuery.EndDate = DateTime.Now.AddDays(1);
EventFeedcalFeed = oSrv.Query(oQuery) asEventFeed;
ArrayList dates = newArrayList(50);
while (calFeed != null&&calFeed.Entries.Count> 0)
                {
// look for the one with dinner time...
foreach (Google.GData.Calendar.EventEntry entry incalFeed.Entries)
                    {
dtRow["EventTitle"] = entry.Title.Text;

foreach (Wherelocinentry.Locations)
strLoc += loc.ValueString + ";";

foreach (AtomPersonlocinentry.Authors)
strAuth += loc.Name + ";";

this.entryList.Add(entry);
if (entry.Times.Count> 0)
                        {
foreach (When w inentry.Times)
                            {
dtRow["StartTime"] = w.StartTime;
dtRow["EndTime"] = w.EndTime;
dates.Add(w.StartTime);
                            }
                        }
                    }
// just query the same query again.
if (calFeed.NextChunk != null)
                    {
oQuery.Uri = newUri(calFeed.NextChunk);
calFeed = oSrv.Query(oQuery) asEventFeed;
                    }
else
calFeed = null;
                }

b. Add Calendar event


Google.GData.Calendar.EventEntry entry = newGoogle.GData.Calendar.EventEntry();

entry.Title = newAtomTextConstruct(
AtomTextConstructElementType.Title,
                                    title);
entry.Authors.Add(newAtomPerson(AtomPersonType.Author, author));
entry.Published = DateTime.Now;
entry.Updated = DateTime.Now;

WherenewPlace = newWhere();
newPlace.ValueString = place;
entry.Locations.Add(newPlace);

WhennewTime = newWhen();

newTime.StartTime = startTime;
newTime.EndTime = endTime;
newTime.AllDay = fAllDay;
entry.Times.Add(newTime);

Google.GData.Calendar.EventEntry test = feed.Insert(entry) asGoogle.GData.Calendar.EventEntry;

c. Get Contact


RequestSettingsrs = newRequestSettings("GoogleAPIs_Cal_V1", strUserName, strPwd);
rs.AutoPaging = true;
ContactsRequestcr = newContactsRequest(rs);

Feed<Contact> f = cr.GetContacts();
IEnumerable<Contact> list = f.Entries;

foreach (Contact entry inf.Entries)
                {
if (entry.Name != null)
                    {
string strContactName = entry.ContactEntry.Name.FullName;
ExtensionCollection<PhoneNumber> phones = entry.ContactEntry.Phonenumbers;
ExtensionCollection<EMail>emAils = entry.ContactEntry.Emails;
                    }
                }
      d. Add Contact
     
R  RequestSettingsrs = new RequestSettings("GoogleAPIs_Cal_V1", strUserName, strPwd);
   rs.AutoPaging = true;
   ContactsRequestcr = newContactsRequest(rs);


   ContactnewEntry = newContact();
   Namename = newName();
   name.FullName = "Matt John";

   EMailprimaryEmail = newEMail("liz@gmail.com");
   newEntry.Emails.Add(primaryEmail);

   PhoneNumberphoneNumber = newPhoneNumber("555-555-5555");
   newEntry.Phonenumbers.Add(phoneNumber);

   StructuredPostalAddresspostalAddress = new
   StructuredPostalAddress();
   postalAddress.Country = "United States";
   postalAddress.Primary = true;
   newEntry.PostalAddresses.Add(postalAddress);

   newEntry.Content = "Contact information for Liz";
   Feed<Contact> fc = cr.GetContacts();
   ContactinsertedEntry = cr.Insert(fc, newEntry);


a.    To get through proxy

     In .NET, any HTTP connection object can have proxy as set as a property.  It can  be handled though code as below:

<Snippet>
GDataRequestFactoryrequestFactory = (GDataRequestFactory)oSrv.RequestFactory;
IWebProxyiProxy = WebRequest.DefaultWebProxy;
WebProxymyProxy = new WebProxy(iProxy.GetProxy(oQuery.Uri));
myProxy.Credentials = CredentialCache.DefaultCredentials;
myProxy.UseDefaultCredentials = true;
requestFactory.Proxy = myProxy;
oSrv.RequestFactory = requestFactory;
</snippet>

However after running application it will throw an error as:

        Error Code: 407 Proxy Authentication Required. The ISA Server requires authorization to fulfill the request. Access to the Web Proxy filter is denied. (12209)

Solution:This can be resolved by setting default proxy in web.config file.

To access public calendar, a link should be provided to calendar service. If this provided link is in format of ICAL, it will throw as error:

Google.GData.Client.ClientFeedException was caught
 Message=Parsing failed
 Source=Google.GData.Client

Solution:Use XML format link to access calendar.


c.   Insertion of contact

An error might be thrown when new contact entry is inserted

Error Code: 407 Proxy Authentications Required. The ISA Server requires authorization to fulfill the request. Access to the Web Proxy filter is denied.
Message = "Cannot update a read-only feed"

Code generating error:
Uri feedUri = new Uri(strCalendarURI);
Contact createdEntry = cr.Insert(feedUri, newEntry);

Solution:
This can be resolved by adding contact as:
Feed<Contact> fc = cr.GetContacts();
ContactinsertedEntry = cr.Insert(fc, newEntry);

d.    Insertion of Events

While linking to calendar we use XML link. 
E.g.

If while adding new entry of events is into public calendar of attendees, we use same link it will throw an error

“Feed is read-only”

To add specific user's primary calendar: This can be resolved by using link
Using this link, event entry will be added to default calendar or to a specific user's primary calendar. It will not be added into public calendar of someone else.

To add public calendar: 
To insert data into public calendar of someone 1, we should use link like

e.   Deployed application on Azure

The deployed application will throw an error as mentioned below:

<Snippet>
Google.GData.Client.GDataRequestException: Execution of request failed: http://www.google.com/m8/feeds/contacts/default/full --->System.Net.WebException: Unable to connect to the remote server --->System.Net.Sockets.SocketException:
A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 209.85.231.104:443
  </Snippet>

Solution: Host web role in HWC (Hostable-Web-Core) mode. To use hwc, open csdef file, remove <sites> section.

Posted the problem on forum:

Reference:


No comments:

Post a Comment