Create project on Google API Console here
- Create new project
- Activate the calendar API under “All services”
- Agree to Google Api “terms of service”
- Click the “Overview” link at right top
- Click “Register” link in front of “Project ID”
- Write “googlecalendarapidemo” or any text as the project ID and register
- Click “API Access” and click “Create an oAuth 2.0 clientID”
- Choose a product name, logo and Home page url
- Choose web application as Application type
- Click ‘more options’ and type the address of the page where you will receive the result of google calendar registration
- For testing purpose, type the address of your visual studio assigned port i.e http://localhost:58392/GoogleCalandarDemo/Default.aspx
- To restrict Visual studio to assign a specific port
- Click on project name in solution explorer
- Click f4 to show its properties
- Select false for “Use dynamic ports”
- For deployment use the appropriate registered address (Google does not allow IP address based address e.g http://192.168.0.1:58392/GoogleCalandarDemo/Default.aspx
- To restrict Visual studio to assign a specific port
- Click create client ID
- Save the ClientID and ClientSecret values in web.config to be used later
- You can change the Redirect URL by clicking the edit settings link at left side
Add the following files in your new website project
——————————-Default.aspx————————————
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:HiddenField runat="server" ID="HdnEventID" Value="" />
<div style="margin-bottom: 20px">
<asp:Label runat="server" ID="LblMessage"></asp:Label>
</div>
<div>
<asp:Panel runat="server" ID="PnlLogin">
UserName:<asp:TextBox ID="TxtBoxUserName" runat="server"></asp:TextBox>
<br />
Pwd:<asp:TextBox ID="TxtBoxPwd" runat="server"></asp:TextBox>
<br />
<asp:Button runat="server" ID="BtnLogin" Text="Login" OnClick="BtnLogin_Click" />
</asp:Panel>
<asp:Panel runat="server" ID="PnlRegister">
<asp:Button runat="server" ID="BtnRegisterWithGoogleCalendar" Text="Register With Google Calendar"
OnClick="BtnRegisterWithGoogleCalendar_Click" />
</asp:Panel>
<asp:Panel runat="server" ID="PnlEvents">
<%--<asp:DropDownList runat="server" ID="DDLEvent" AutoPostBack="true"
onselectedindexchanged="DDLEvent_SelectedIndexChanged">
<asp:ListItem Enabled="true" Text="-Select-"></asp:ListItem>
</asp:DropDownList>--%>
<div id="DivEventDescription">
Title:
<asp:TextBox runat="server" ID="TxtTitle"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator0" ControlToValidate="TxtTitle"
ErrorMessage="*" ToolTip="Required" runat="server"></asp:RequiredFieldValidator>
<br />
Start Time:
<asp:TextBox runat="server" ID="TxtStartTime" Enabled="false"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" ControlToValidate="TxtStartTime"
ErrorMessage="*" ToolTip="Required" runat="server"></asp:RequiredFieldValidator>
<br />
End Time:
<asp:TextBox runat="server" ID="TxtEndTime" Enabled="false"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator2" ControlToValidate="TxtEndTime"
ErrorMessage="*" ToolTip="Required" runat="server"></asp:RequiredFieldValidator>
<br />
Details:
<br />
<asp:TextBox runat="server" ID="TxtEventDetails" TextMode="MultiLine"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator3" ControlToValidate="TxtEventDetails"
ErrorMessage="*" ToolTip="Required" runat="server"></asp:RequiredFieldValidator>
<br />
<asp:Button ID="BtnCreateEvent" Text="Create / Update Event" runat="server" OnClick="BtnCreateUpdateEvent_Click" />
</div>
<br />
<br />
<asp:Button ID="BtnRevoke" Text="Revoke google calendar rights" runat="server" OnClick="BtnRevoke_Click" />
</asp:Panel>
</div>
</form>
</body>
</html>
——————————-Default.aspx.cs————————————
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;
using Google.AccessControl;
using Google.GData;
using Google.GData.Calendar;
using Google.GData.AccessControl;
using Google.GData.Client;
public partial class _Default : System.Web.UI.Page
{
XmlDocument XmlDoc = new XmlDocument();
static string UserID = "UserID";
static string UserName = "UserName";
static string Password = "Password";
static string AccessToken = "AccessToken";
static string RefreshToken = "RefreshToken";
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
try
{
if (XmlDoc.HasChildNodes == false)
{
XmlDoc.Load(AppDomain.CurrentDomain.BaseDirectory + "App_Data\\XMLfile.xml");
}
//check if the user has logged in
if (Session[UserID] != null && string.IsNullOrEmpty(Session[UserID].ToString()) == false)
{
//if the user is registered
if (string.IsNullOrEmpty(XmlDoc.DocumentElement.ChildNodes[0].Attributes[AccessToken].Value.ToString()) == false)
{
PnlLogin.Visible = false;
PnlRegister.Visible = false;
PnlEvents.Visible = true;
TxtStartTime.Text = DateTime.Now.ToString();
TxtEndTime.Text = DateTime.Now.AddHours(2).ToString();
}
else
{
PnlLogin.Visible = false;
PnlRegister.Visible = true;
PnlEvents.Visible = false;
}
}
else
{
PnlLogin.Visible = true;
PnlRegister.Visible = false;
PnlEvents.Visible = false;
LblMessage.Text = "Please login";
}
}
catch { }
}
}
protected void BtnLogin_Click(object sender, EventArgs e)
{
if (XmlDoc.HasChildNodes == false)
{
XmlDoc.Load(AppDomain.CurrentDomain.BaseDirectory + "App_Data\\XMLfile.xml");
}
//check the user credentials
if (string.IsNullOrEmpty(XmlDoc.DocumentElement.ChildNodes[0].Attributes[UserName].Value.ToString()) == false
&& XmlDoc.DocumentElement.ChildNodes[0].Attributes[UserName].Value.ToLower() == TxtBoxUserName.Text.ToLower()
&& string.IsNullOrEmpty(XmlDoc.DocumentElement.ChildNodes[0].Attributes[Password].Value.ToString()) == false
&& XmlDoc.DocumentElement.ChildNodes[0].Attributes[Password].Value.ToLower() == TxtBoxPwd.Text.ToLower())
{
Session[UserID] = XmlDoc.DocumentElement.ChildNodes[0].Attributes[UserID].Value.ToLower();
//check if the user is registered or not
//if not then ask the user to register
if (string.IsNullOrEmpty(XmlDoc.DocumentElement.ChildNodes[0].Attributes[AccessToken].Value.ToString()) == true ||
string.IsNullOrEmpty(XmlDoc.DocumentElement.ChildNodes[0].Attributes[RefreshToken].Value.ToString()) == true)
{
PnlLogin.Visible = false;
PnlRegister.Visible = true;
PnlEvents.Visible = false;
LblMessage.Text = "Login Successful. Please click the register button to register with google calendar ";
}
else
{
PnlLogin.Visible = false;
PnlRegister.Visible = false;
PnlEvents.Visible = true;
//PopulateDDLEvent();
}
}
else
{
LblMessage.Text = "Login UnSuccessful. Please provide the correct credentials";
}
}
protected void BtnRegisterWithGoogleCalendar_Click(object sender, EventArgs e)
{
string GoogleReturnPageAddress = System.Configuration.ConfigurationManager.AppSettings["GoogleReturnPageAddress"];
Response.Redirect(GoogleCalendarManager.GenerateGoogleOAuthURL());
}
protected void BtnRevoke_Click(object sender, EventArgs e)
{
if (XmlDoc.HasChildNodes == false)
{
XmlDoc.Load(AppDomain.CurrentDomain.BaseDirectory + "App_Data\\XMLfile.xml");
}
string Access_Token = XmlDoc.DocumentElement.SelectSingleNode("//User[@UserID='1']").Attributes[AccessToken].Value;
string Refresh_Token = XmlDoc.DocumentElement.SelectSingleNode("//User[@UserID='1']").Attributes[RefreshToken].Value;
//Attempt the revoke from google
//if successful then do a db / xml delete as well
if (GoogleCalendarManager.RevokeAccessToken(Access_Token, Refresh_Token) == true)
{
XmlDoc.DocumentElement.SelectSingleNode("//User[@UserID='1']").Attributes[AccessToken].Value = "";
XmlDoc.DocumentElement.SelectSingleNode("//User[@UserID='1']").Attributes[RefreshToken].Value = "";
XmlDoc.Save(AppDomain.CurrentDomain.BaseDirectory + "App_Data\\XMLfile.xml");
}
}
protected void BtnCreateUpdateEvent_Click(object sender, EventArgs e)
{
List<GoogleCalendarAppointmentModel> GoogleCalendarAppointmentModelList = new List<GoogleCalendarAppointmentModel>();
List<GoogleTokenModel> GoogleTokenModelList = new List<GoogleTokenModel>();
GoogleCalendarAppointmentModel GoogleCalendarAppointmentModelObj = new GoogleCalendarAppointmentModel();
GoogleTokenModel GoogleTokenModelObj = new GoogleTokenModel();
#region populate GoogleAppointment values
GoogleCalendarAppointmentModelObj.EventID = "1";
GoogleCalendarAppointmentModelObj.EventTitle = "New Event from google api";
GoogleCalendarAppointmentModelObj.EventStartTime = DateTime.Now;
GoogleCalendarAppointmentModelObj.EventEndTime.AddHours(2);
GoogleCalendarAppointmentModelObj.EventLocation = "New Location";
GoogleCalendarAppointmentModelObj.EventDetails = "New Details";
#endregion
#region populate GoogleToken values
GoogleTokenModelObj.Access_Token = XmlDoc.DocumentElement.SelectSingleNode("//User[@UserID='1']").Attributes[AccessToken].Value;
GoogleTokenModelObj.Refresh_Token = XmlDoc.DocumentElement.SelectSingleNode("//User[@UserID='1']").Attributes[RefreshToken].Value;
GoogleTokenModelList.Add(GoogleTokenModelObj);
#endregion
#region Add event to google calendar
if (GoogleCalendarManager.AddUpdateDeleteEvent(GoogleTokenModelList, GoogleCalendarAppointmentModelList, 0) == true)
{
if (XmlDoc.HasChildNodes == false)
{
XmlDoc.Load(AppDomain.CurrentDomain.BaseDirectory + "App_Data\\XMLfile.xml");
}
//save data in DB / xml
XmlDoc.DocumentElement.SelectSingleNode("//Event").Attributes["EventTitle"].Value = GoogleCalendarAppointmentModelObj.EventTitle;
XmlDoc.DocumentElement.SelectSingleNode("//Event").Attributes["StartTime"].Value = GoogleCalendarAppointmentModelObj.EventStartTime.ToString();
XmlDoc.DocumentElement.SelectSingleNode("//Event").Attributes["EndTime"].Value = GoogleCalendarAppointmentModelObj.EventEndTime.ToString();
XmlDoc.DocumentElement.SelectSingleNode("//Event").Attributes["EventLocation"].Value = GoogleCalendarAppointmentModelObj.EventLocation;
XmlDoc.Save(AppDomain.CurrentDomain.BaseDirectory + "App_Data\\XMLfile.xml");
}
#endregion
}
//private void PopulateDDLEvent()
//{
// if (XmlDoc.HasChildNodes == false)
// {
// XmlDoc.Load(AppDomain.CurrentDomain.BaseDirectory + "App_Data\\XMLfile.xml");
// }
// XmlNodeList AllEventNodes = XmlDoc.DocumentElement.SelectNodes("//Events/Event");
// if (AllEventNodes != null && AllEventNodes.Count > 0)
// {
// foreach (XmlNode XmlNodeObj in AllEventNodes)
// {
// DDLEvent.Items.Add(new ListItem(XmlNodeObj.Attributes["EventTitle"].Value, XmlNodeObj.Attributes["EventID"].Value));
// }
// }
//}
//protected void DDLEvent_SelectedIndexChanged(object sender, EventArgs e)
//{
// if (DDLEvent.SelectedIndex != 0)
// {
// HdnEventID.Value = DDLEvent.SelectedValue;
// }
//}
}
——————————-GoogleCalendarRegistration.aspx———————
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label runat="server" ID="LblMessage"></asp:Label>
<br /><br />
<asp:HyperLink NavigateUrl="~/Default.aspx" Text="Go to main page" runat="server"></asp:HyperLink>
</div>
</form>
</body>
</html>
——————————-GoogleCalendarRegistration.aspx.cs——————
'
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Script.Serialization;
using Google.GData.Client;
using Google.GData.Calendar;
using Google.GData.Extensions;
using System.Net;
using System.Text;
using System.IO;
using System.Xml;
public partial class GoogleCalendarRegistration : System.Web.UI.Page
{
private static string ReturnUrl = @System.Configuration.ConfigurationManager.AppSettings["GoogleReturnPageAddress"].ToString();
private static string OwnCalendarFeed = @"http://www.google.com/calendar/feeds/default/owncalendars/full";
private static string AllCalendarFeed = @"http://www.google.com/calendar/feeds/default/allcalendars/full";
private static string PrivateFeed = @"http://www.google.com/calendar/feeds/default/private/full";
private static string ClientID = System.Configuration.ConfigurationManager.AppSettings["GoogleCalendarApplicationClientID"].ToString();
private static string ClientSecret = System.Configuration.ConfigurationManager.AppSettings["GoogleCalendarApplicationClientSecret"].ToString();
private string AllCalendarFeedURL = @"https://www.google.com/calendar/feeds/default/allcalendars/full";
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack == false)
{
if (string.IsNullOrEmpty(Request.QueryString["code"]) == false)
{
GoogleTokenModel TokenData = new GoogleTokenModel();
string Result = "";
try
{
TokenData = ExchangeCodeWithAccessAndRefreshToken();
}
catch
{
Result = "?Error=Internet connectivity problem. Please try later";
}
//If no proper response is given
if (string.IsNullOrEmpty(TokenData.Access_Token) == true)
{
Result = "?Error=Some problem with google registration. Please try later or use a different gmail account to register";
}
//If the gmail account is already registered
else if (string.IsNullOrEmpty(TokenData.Access_Token) == false && string.IsNullOrEmpty(TokenData.Refresh_Token) == true)
{
Result = "?Error=This gmail account is already registered with this application. Please use a different gmail account to register";
}
//Check if the some error is thrown
if (string.IsNullOrEmpty(Result) == false)
{
LblMessage.Text = Result;
return;
}
//If proper token data is acquired
else if (string.IsNullOrEmpty(TokenData.Access_Token) == false && string.IsNullOrEmpty(TokenData.Refresh_Token) == false)
{
LblMessage.Text = "Registration Complete";
XmlDocument XmlDoc = new XmlDocument();
XmlDoc.Load(AppDomain.CurrentDomain.BaseDirectory + "App_Data\\XMLfile.xml");
XmlDoc.DocumentElement.SelectSingleNode("//User[@UserID='1']").Attributes["AccessToken"].Value = TokenData.Access_Token;
XmlDoc.DocumentElement.SelectSingleNode("//User[@UserID='1']").Attributes["RefreshToken"].Value = TokenData.Refresh_Token;
XmlDoc.Save(AppDomain.CurrentDomain.BaseDirectory + "App_Data\\XMLfile.xml");
}
}
else
{
//if access denied
if (Request.QueryString["error"] != null)
{
LblMessage.Text = "Access is Denied. Please grant access to continue to google calendar registration";
}
else
{
}
}
}
}
public static string GenerateGoogleOAuthURL()
{
string Url = "https://accounts.google.com/o/oauth2/auth?scope={0}&redirect_uri={1}&response_type={2}&client_id={3}&state={4}&access_type={5}&approval_prompt={6}";
//string scope = UrlEncodeForGoogle("http://www.google.com/calendar/feeds/default/private/full").Replace("%20", "+");
string scope = UrlEncodeForGoogle(PrivateFeed).Replace("%20", "+");
string redirect_uri_encode = UrlEncodeForGoogle(ReturnUrl);
string response_type = "code";
string state = "";
string access_type = "offline";
string approval_prompt = "auto";
return string.Format(Url, scope, redirect_uri_encode, response_type, ClientID, state, access_type, approval_prompt);
}
private static string UrlEncodeForGoogle(string url)
{
string UnReservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
var result = new StringBuilder();
foreach (char symbol in url)
{
if (UnReservedChars.IndexOf(symbol) != -1)
{
result.Append(symbol);
}
else
{
result.Append('%' + String.Format("{0:X2}", (int)symbol));
}
}
return result.ToString();
}
private GoogleTokenModel ExchangeCodeWithAccessAndRefreshToken()
{
string Url = "https://accounts.google.com/o/oauth2/token";
string grant_type = "authorization_code";
string redirect_uri_encode = UrlEncodeForGoogle(ReturnUrl);
string data = "code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type={4}";
string Code = Request.QueryString["Code"];
HttpWebRequest request = HttpWebRequest.Create(Url) as HttpWebRequest;
string result = null;
request.Method = "POST";
request.KeepAlive = true;
request.ContentType = "application/x-www-form-urlencoded";
string param = string.Format(data, Code, ClientID, ClientSecret, redirect_uri_encode, grant_type);
var bs = Encoding.UTF8.GetBytes(param);
using (Stream reqStream = request.GetRequestStream())
{
reqStream.Write(bs, 0, bs.Length);
}
using (WebResponse response = request.GetResponse())
{
var sr = new StreamReader(response.GetResponseStream());
result = sr.ReadToEnd();
sr.Close();
}
var jsonSerializer = new JavaScriptSerializer();
var tokenData = jsonSerializer.Deserialize<GoogleTokenModel>(result);
return tokenData;
}
private bool GetNewAccessToken(GoogleTokenModel GoogleTokenModelObj)
{
try
{
string Url = "https://accounts.google.com/o/oauth2/token";
string grant_type = "refresh_token";
string redirect_uri_encode = UrlEncodeForGoogle(ReturnUrl);
string data = "client_id={0}&client_secret={1}&refresh_token={2}&grant_type={3}";
HttpWebRequest request = HttpWebRequest.Create(Url) as HttpWebRequest;
string result = null;
request.Method = "POST";
request.KeepAlive = true;
request.ContentType = "application/x-www-form-urlencoded";
string param = string.Format(data, ClientID, ClientSecret, GoogleTokenModelObj.Refresh_Token, grant_type);
var bs = Encoding.UTF8.GetBytes(param);
using (Stream reqStream = request.GetRequestStream())
{
reqStream.Write(bs, 0, bs.Length);
}
using (WebResponse response = request.GetResponse())
{
var sr = new StreamReader(response.GetResponseStream());
result = sr.ReadToEnd();
sr.Close();
}
var jsonSerializer = new JavaScriptSerializer();
var TokenData = jsonSerializer.Deserialize<GoogleTokenModel>(result);
GoogleTokenModelObj.Access_Token = TokenData.Access_Token;
if (TokenData.Refresh_Token != null)
GoogleTokenModelObj.Refresh_Token = TokenData.Refresh_Token;
//GoogleTokenModelObj.LastAccessDateTime = DateTime.Now;
//Update the refresh and access token in DB for next login usage
//GoogleCalendarManager.UpdateRefreshTokenInGoogleAppointmentOAuth(GoogleTokenModelObj);
XmlDocument XmlDoc = new XmlDocument();
XmlDoc.Load(AppDomain.CurrentDomain.BaseDirectory + "App_Data\\XMLfile.xml");
XmlDoc.DocumentElement.SelectSingleNode("//User[@UserID='1']").Attributes["AccessToken"].Value = TokenData.Access_Token;
XmlDoc.DocumentElement.SelectSingleNode("//User[@UserID='1']").Attributes["RefreshToken"].Value = TokenData.Refresh_Token;
XmlDoc.Save(AppDomain.CurrentDomain.BaseDirectory + "App_Data\\XMLfile.xml");
return true;
}
catch
{
return false;
}
}
}
——————————-Web.config————————————
- You need to copy the ClientID, Client Secret from https://code.google.com/apis/console/ -> ApiAccess link
- The value of ‘GoogleReturnPageAddress’ below should match the Redirect URIs from https://code.google.com/apis/console/ -> ApiAccess link
<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0"/>
</system.web>
<appSettings>
<add key="GoogleCalendarApplicationClientID" value=""/>
<add key="GoogleCalendarApplicationClientSecret" value=""/>
<add key="GoogleReturnPageAddress" value="http://localhost:58392/GoogleCalandarDemo/GoogleCalendarRegistration.aspx"/>
</appSettings>
</configuration>
——————————AppData -> XMLFile.xml (This file serves as a DB here)————————–
- You can change your login credentials. Currently they are set to UserName=Waqas, POwd = 111
- When you register with google calendar, you will get a new AccessToken and RefreshToken which will be saved here
- When you create / update an event, its details are stored here.
- When you delete event, these details are removed, as you can see below that there are no values for the event attributes
- When you revoke rights your AccessToken and RefreshToken are removed from here
- YOU DON”T NEED TO EDIT THIS FILE MANUALLY, EXCEPT THE USERNAME, PWD AS THIS MAY RESULT IN EXCEPTIONS
<?xml version="1.0" encoding="utf-8"?> <UsersAndEvents> <User UserID="1" UserName="Waqas" Password="111" AccessToken="" RefreshToken=""> </User> <Event EventID="1" EventTitle="" EventStartTime="" EventEndTime="" EventLocation=""> </Event> </UsersAndEvents>
——————————AppCode -> GoogleCalendarAppointmentModel.cs———————————–
public class GoogleCalendarAppointmentModel
{
public DateTime EventStartTime;
public DateTime EventEndTime;
public bool DeleteAppointment;
public string EventID;
public string EventLocation;
public string EventTitle;
public string EventDetails;
}
—————————–AppCode -> GoogleCalendarManager.cs———————————–
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Google.GData.Client;
using Google.GData.Calendar;
using Google.GData.AccessControl;
using Google.GData.Extensions;
using System.Net;
using System.IO;
public class GoogleCalendarManager
{
private static string ReturnUrl = @System.Configuration.ConfigurationSettings.AppSettings["GoogleReturnPageAddress"].ToString();
private static string ClientID = System.Configuration.ConfigurationSettings.AppSettings["GoogleCalendarApplicationClientID"].ToString();
private static string ClientSecret = System.Configuration.ConfigurationSettings.AppSettings["GoogleCalendarApplicationClientSecret"].ToString();
private static string PrivateFeed = @"http://www.google.com/calendar/feeds/default/private/full";
private static string OwnCalendarFeed = @"http://www.google.com/calendar/feeds/default/owncalendars/full";
private static string AllCalendarFeed = @"http://www.google.com/calendar/feeds/default/allcalendars/full";
private static String userName, userPassword, feedUri;
/// <summary>
/// Prints a list of the user's calendars.
/// </summary>
/// <param name="service">The authenticated CalendarService object.</param>
#region Currently Required Functions
public static string GenerateGoogleOAuthURL()
{
string Url = "https://accounts.google.com/o/oauth2/auth?scope={0}&redirect_uri={1}&response_type={2}&client_id={3}&state={4}&access_type={5}&approval_prompt={6}";
//string scope = UrlEncodeForGoogle("http://www.google.com/calendar/feeds/default/private/full").Replace("%20", "+");
string scope = UrlEncodeForGoogle(PrivateFeed).Replace("%20", "+");
string redirect_uri_encode = UrlEncodeForGoogle(ReturnUrl);
string response_type = "code";
string state = "";
string access_type = "offline";
string approval_prompt = "auto";
return string.Format(Url, scope, redirect_uri_encode, response_type, ClientID, state, access_type, approval_prompt);
}
private static string GetCalendarID(CalendarService CalService)
{
Uri postUri = new Uri(AllCalendarFeed);
CalendarQuery CalendarQuery = new CalendarQuery();
CalendarQuery.Uri = postUri;
CalendarFeed calFeed = CalService.Query(CalendarQuery);
string CalendarID = "";
if (calFeed != null && calFeed.Entries.Count > 0)
{
foreach (CalendarEntry CalEntry in calFeed.Entries)
{
//Commented to post the new appointments on the main calendar instead of cleverfox calendar
//if (CalEntry.Title.Text.Contains("Cleverfox") == true)
//{
//CalendarID = CalEntry.Title.Text;
CalendarID = CalEntry.EditUri.ToString().Substring(CalEntry.EditUri.ToString().LastIndexOf("/") + 1);
break;
//}
}
}
#region Commented to post the new appointments on the main calendar instead of cleverfox calendar
/*if (string.IsNullOrEmpty(CalendarID) == false)
{
}
else
{
Google.GData.Client.AtomEntry cal = new AtomEntry();
cal.Title.Text = "Cleverfox";
CalService.Insert(new Uri(OwnCalendarFeed), cal);
}
calFeed = CalService.Query(CalendarQuery);
//if search contains result then update
if (calFeed != null && calFeed.Entries.Count > 0)
{
foreach (CalendarEntry CalEntry in calFeed.Entries)
{
if (CalEntry.Title.Text.Contains("Cleverfox") == true)
{
//CalendarName = CalEntry.Title.Text;
CalendarID = CalEntry.EditUri.ToString().Substring(CalEntry.EditUri.ToString().LastIndexOf("/") + 1);
//if (CalEntry.TimeZone != "Canada/Vancouver")
//{
// CalEntry.TimeZone = "(GMT-07:00) Arizona";
// CalEntry.Update();
//}
if (CalEntry.TimeZone != MerchantTimeZone)
{
CalEntry.TimeZone = MerchantTimeZone;
CalEntry.Update();
}
break;
}
}
}*/
#endregion
return CalendarID;
}
public static CalendarService GetCalendarService(GoogleTokenModel GoogleTokenModelObj)
{
GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("cl", "API Project");
authFactory.Token = GoogleTokenModelObj.Access_Token;
authFactory.KeepAlive = true;
CalendarService service = new CalendarService("cl");
service.RequestFactory = authFactory;
return service;
}
public static bool AddUpdateDeleteEvent(List<GoogleTokenModel> GoogleTokenModelList, List<GoogleCalendarAppointmentModel> GoogleCalendarAppointmentModelList, double TimeOffset)
{
bool result = false;
foreach (GoogleTokenModel GoogleAppointmentOAuthDetailsObj in GoogleTokenModelList)
{
//Get the calendar service for a user to add/update/delete events
CalendarService CalService = GetCalendarService(GoogleAppointmentOAuthDetailsObj);
//get the calendar id for this user to add/update/delete events
string CalendarID = GetCalendarID(CalService);
EventEntry InsertedEntry = new EventEntry();
if (GoogleCalendarAppointmentModelList != null && GoogleCalendarAppointmentModelList.Count > 0)
{
foreach (GoogleCalendarAppointmentModel GoogleCalendarAppointmentModelObj in GoogleCalendarAppointmentModelList)
{
//to restrict the appointment for specific staff only
//Delete this appointment from google calendar
if (GoogleCalendarAppointmentModelObj.DeleteAppointment == true)
{
Google.GData.Calendar.EventEntry Entry = new Google.GData.Calendar.EventEntry();
ExtendedProperty oExtendedProperty = new ExtendedProperty();
oExtendedProperty.Name = "EventID";
oExtendedProperty.Value = GoogleCalendarAppointmentModelObj.EventID;
//search the calendar so to update or add appointment in it
string ThisFeedUri = "http://www.google.com/calendar/feeds/" + CalendarID + "/private/full";
Uri postUri = new Uri(ThisFeedUri);
EventQuery Query = new EventQuery(ThisFeedUri);
Query.ExtraParameters = "extq=[EventID:" + GoogleCalendarAppointmentModelObj.EventID + "]";
Query.Uri = postUri;
Entry.ExtensionElements.Add(oExtendedProperty);
EventFeed calFeed = CalService.Query(Query);
//if search contains result then update
if (calFeed != null && calFeed.Entries.Count > 0)
{
foreach (EventEntry SearchedEntry in calFeed.Entries)
{
SearchedEntry.Delete();
result = true;
break;
}
//return null;
}
}
//Add if not found OR update if appointment already present on google calendar
else
{
Google.GData.Calendar.EventEntry Entry = new Google.GData.Calendar.EventEntry();
// Set the title and content of the entry.
Entry.Title.Text = "Event generated through google api";
System.Text.StringBuilder EventDetails = new System.Text.StringBuilder();
EventDetails.Append(GoogleCalendarAppointmentModelObj.EventDetails);
Entry.Content.Content = EventDetails.ToString();
When EventTime = new When();
EventTime.StartTime = GoogleCalendarAppointmentModelObj.EventStartTime.AddMinutes(-TimeOffset);
EventTime.EndTime = GoogleCalendarAppointmentModelObj.EventEndTime.AddMinutes(-TimeOffset);
Entry.Times.Add(EventTime);
// Set a location for the event.
Where eventLocation = new Where();
if (string.IsNullOrEmpty(GoogleCalendarAppointmentModelObj.EventLocation) == false)
{
eventLocation.ValueString = GoogleCalendarAppointmentModelObj.EventLocation;
Entry.Locations.Add(eventLocation);
}
//Add appointment ID to update/ delete the appointment afterwards
ExtendedProperty oExtendedProperty = new ExtendedProperty();
oExtendedProperty.Name = "EventID";
oExtendedProperty.Value = GoogleCalendarAppointmentModelObj.EventID;
Entry.ExtensionElements.Add(oExtendedProperty);
//search the calendar so to update or add appointment in it
string ThisFeedUri = "http://www.google.com/calendar/feeds/" + CalendarID + "/private/full";
Uri postUri = new Uri(ThisFeedUri);
EventQuery Query = new EventQuery(ThisFeedUri);
Query.ExtraParameters = "extq=[EventID:" + GoogleCalendarAppointmentModelObj.EventID + "]";
Query.Uri = postUri;
Entry.ExtensionElements.Add(oExtendedProperty);
EventFeed calFeed = CalService.Query(Query);
//if search contains result then update
if (calFeed != null && calFeed.Entries.Count > 0)
{
foreach (EventEntry SearchedEntry in calFeed.Entries)
{
SearchedEntry.Content = Entry.Content;
SearchedEntry.Title = Entry.Title;
SearchedEntry.Times.RemoveAt(0);
SearchedEntry.Times.Add(EventTime);
SearchedEntry.Locations.RemoveAt(0);
SearchedEntry.Locations.Add(eventLocation);
CalService.Update(SearchedEntry);
result = true;
break;
}
}
//otherwise add the entry
else
{
InsertedEntry = CalService.Insert(postUri, Entry);
result = true;
}
}
}
}
}
return result ;
}
public static bool RevokeAccessToken(string Access_Token, string Refresh_Token)
{
try
{
//check and revoke right from google if staff is registered i.e. he has proper acccess token
if (string.IsNullOrEmpty(Access_Token) == false)
{
string Url = "https://accounts.google.com/o/oauth2/revoke?token=" + Refresh_Token;
string redirect_uri_encode = UrlEncodeForGoogle(ReturnUrl);
string data = "refresh_token={0}";
HttpWebRequest request = HttpWebRequest.Create(Url) as HttpWebRequest;
string result = null;
request.Method = "POST";
request.KeepAlive = true;
request.ContentType = "application/x-www-form-urlencoded";
string param = string.Format(data, Refresh_Token);
var bs = Encoding.UTF8.GetBytes(param);
using (Stream reqStream = request.GetRequestStream())
{
//reqStream.Write(bs, 0, bs.Length);
}
using (WebResponse response = request.GetResponse())
{
var sr = new StreamReader(response.GetResponseStream());
result = sr.ReadToEnd();
sr.Close();
}
}
return true;
}
catch
{
//GoogleCalendarManager.DeleteGoogleAppointmentOAuthDetailsRecord(GoogleAppointmentOAuthDetailsObj.ID);
return false;
}
}
#region Utility functions
public static string UrlEncodeForGoogle(string url)
{
string UnReservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
var result = new StringBuilder();
foreach (char symbol in url)
{
if (UnReservedChars.IndexOf(symbol) != -1)
{
result.Append(symbol);
}
else
{
result.Append('%' + String.Format("{0:X2}", (int)symbol));
}
}
return result.ToString();
}
#endregion
#endregion
#region Other functions which are not used now
static void PrintUserCalendars(CalendarService service)
{
FeedQuery query = new FeedQuery();
query.Uri = new Uri("http://www.google.com/calendar/feeds/default");
// Tell the service to query:
AtomFeed calFeed = service.Query(query);
Console.WriteLine("Your calendars:");
Console.WriteLine();
for (int i = 0; i < calFeed.Entries.Count; i++)
{
Console.WriteLine(calFeed.Entries[i].Title.Text);
}
Console.WriteLine();
}
/// <summary>
/// Prints the titles of all events on the specified calendar.
/// </summary>
/// <param name="service">The authenticated CalendarService object.</param>
static void PrintAllEvents(CalendarService service)
{
EventQuery myQuery = new EventQuery(feedUri);
EventFeed myResultsFeed = service.Query(myQuery) as EventFeed;
Console.WriteLine("All events on your calendar:");
Console.WriteLine();
for (int i = 0; i < myResultsFeed.Entries.Count; i++)
{
Console.WriteLine(myResultsFeed.Entries[i].Title.Text);
}
Console.WriteLine();
}
/// <summary>
/// Prints the titles of all events matching a full-text query.
/// </summary>
/// <param name="service">The authenticated CalendarService object.</param>
/// <param name="queryString">The text for which to query.</param>
static void FullTextQuery(CalendarService service, String queryString)
{
EventQuery myQuery = new EventQuery(feedUri);
myQuery.Query = queryString;
EventFeed myResultsFeed = service.Query(myQuery) as EventFeed;
Console.WriteLine("Events matching \"{0}\":", queryString);
Console.WriteLine();
for (int i = 0; i < myResultsFeed.Entries.Count; i++)
{
Console.WriteLine(myResultsFeed.Entries[i].Title.Text);
}
Console.WriteLine();
}
/// <summary>
/// Prints the titles of all events in a specified date/time range.
/// </summary>
/// <param name="service">The authenticated CalendarService object.</param>
/// <param name="startTime">Start time (inclusive) of events to print.</param>
/// <param name="endTime">End time (exclusive) of events to print.</param>
static void DateRangeQuery(CalendarService service, DateTime startTime, DateTime endTime)
{
EventQuery myQuery = new EventQuery(feedUri);
myQuery.StartTime = startTime;
myQuery.EndTime = endTime;
EventFeed myResultsFeed = service.Query(myQuery) as EventFeed;
Console.WriteLine("Matching events from {0} to {1}:",
startTime.ToShortDateString(),
endTime.ToShortDateString());
Console.WriteLine();
for (int i = 0; i < myResultsFeed.Entries.Count; i++)
{
Console.WriteLine(myResultsFeed.Entries[i].Title.Text);
}
Console.WriteLine();
}
/// <summary>
/// Helper method to create either single-instance or recurring events.
/// For simplicity, some values that might normally be passed as parameters
/// (such as author name, email, etc.) are hard-coded.
/// </summary>
/// <param name="service">The authenticated CalendarService object.</param>
/// <param name="entryTitle">Title of the event to create.</param>
/// <param name="recurData">Recurrence value for the event, or null for
/// single-instance events.</param>
/// <returns>The newly-created EventEntry on the calendar.</returns>
public static Service GetService(string SessionToken)
{
GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("cl", "CalendarSampleApp");
authFactory.Token = SessionToken;
Service service = new Service("cl", authFactory.ApplicationName);
service.RequestFactory = authFactory;
return service;
}
/// <summary>
/// Creates a single-instance event on a calendar.
/// </summary>
/// <param name="service">The authenticated CalendarService object.</param>
/// <param name="entryTitle">Title of the event to create.</param>
/// <returns>The newly-created EventEntry on the calendar.</returns>
public static EventEntry CreateSingleEvent(CalendarService service, String entryTitle)
{
//return AddUpdateDeleteEvent(service, entryTitle, null, null, null);
return new EventEntry();
}
/// <summary>
/// Creates a recurring event on a calendar. In this example, the event
/// occurs every Tuesday from May 1, 2007 through September 4, 2007. Note
/// that we are using iCal (RFC 2445) syntax; see http://www.ietf.org/rfc/rfc2445.txt
/// for more information.
/// </summary>
/// <param name="service">The authenticated CalendarService object.</param>
/// <param name="entryTitle">Title of the event to create.</param>
/// <returns>The newly-created EventEntry on the calendar.</returns>
static EventEntry CreateRecurringEvent(CalendarService service, String entryTitle)
{
String recurData =
"DTSTART;VALUE=DATE:20070501\r\n" +
"DTEND;VALUE=DATE:20070502\r\n" +
"RRULE:FREQ=WEEKLY;BYDAY=Tu;UNTIL=20070904\r\n";
//return AddUpdateDeleteEvent(service, entryTitle, recurData, null, null);
return new EventEntry();
}
/// <summary>
/// Updates the title of an existing calendar event.
/// </summary>
/// <param name="entry">The event to update.</param>
/// <param name="newTitle">The new title for this event.</param>
/// <returns>The updated EventEntry object.</returns>
static EventEntry UpdateTitle(EventEntry entry, String newTitle)
{
entry.Title.Text = newTitle;
return (EventEntry)entry.Update();
}
/// <summary>
/// Adds a reminder to a calendar event.
/// </summary>
/// <param name="entry">The event to update.</param>
/// <param name="numMinutes">Reminder time, in minutes.</param>
/// <returns>The updated EventEntry object.</returns>
static EventEntry AddReminder(EventEntry entry, int numMinutes)
{
Reminder reminder = new Reminder();
reminder.Minutes = numMinutes;
entry.Reminder = reminder;
return (EventEntry)entry.Update();
}
/// <summary>
/// Adds an extended property to a calendar event.
/// </summary>
/// <param name="entry">The event to update.</param>
/// <returns>The updated EventEntry object.</returns>
static EventEntry AddExtendedProperty(EventEntry entry)
{
ExtendedProperty property = new ExtendedProperty();
property.Name = "http://www.example.com/schemas/2005#mycal.id";
property.Value = "1234";
entry.ExtensionElements.Add(property);
return (EventEntry)entry.Update();
}
/// <summary>
/// Retrieves and prints the access control lists of all
/// of the authenticated user's calendars.
/// </summary>
/// <param name="service">The authenticated CalendarService object.</param>
static void RetrieveAcls(CalendarService service)
{
FeedQuery query = new FeedQuery();
query.Uri = new Uri("http://www.google.com/calendar/feeds/default");
AtomFeed calFeed = service.Query(query);
Console.WriteLine();
Console.WriteLine("Sharing permissions for your calendars:");
// Retrieve the meta-feed of all calendars.
foreach (AtomEntry calendarEntry in calFeed.Entries)
{
Console.WriteLine("Calendar: {0}", calendarEntry.Title.Text);
AtomLink link = calendarEntry.Links.FindService(
AclNameTable.LINK_REL_ACCESS_CONTROL_LIST, null);
// For each calendar, retrieve its ACL feed.
if (link != null)
{
AclFeed feed = service.Query(new AclQuery(link.HRef.ToString()));
foreach (AclEntry aclEntry in feed.Entries)
{
Console.WriteLine("\tScope: Type={0} ({1})", aclEntry.Scope.Type,
aclEntry.Scope.Value);
Console.WriteLine("\tRole: {0}", aclEntry.Role.Value);
}
}
}
}
/// <summary>
/// Shares a calendar with the specified user. Note that this method
/// will not run by default.
/// </summary>
/// <param name="service">The authenticated CalendarService object.</param>
/// <param name="aclFeedUri">the ACL feed URI of the calendar being shared.</param>
/// <param name="userEmail">The email address of the user with whom to share.</param>
/// <param name="role">The role of the user with whom to share.</param>
/// <returns>The AclEntry returned by the server.</returns>
static AclEntry AddAccessControl(CalendarService service, string aclFeedUri,
string userEmail, AclRole role)
{
AclEntry entry = new AclEntry();
entry.Scope = new AclScope();
entry.Scope.Type = AclScope.SCOPE_USER;
entry.Scope.Value = userEmail;
entry.Role = role;
Uri aclUri =
new Uri("http://www.google.com/calendar/feeds/gdata.ops.test@gmail.com/acl/full");
AclEntry insertedEntry = service.Insert(aclUri, entry);
Console.WriteLine("Added user {0}", insertedEntry.Scope.Value);
return insertedEntry;
}
/// <summary>
/// Updates a user to have new access permissions over a calendar.
/// Note that this method will not run by default.
/// </summary>
/// <param name="entry">An existing AclEntry representing sharing permissions.</param>
/// <param name="newRole">The new role (access permissions) for the user.</param>
/// <returns>The updated AclEntry.</returns>
static AclEntry UpdateEntry(AclEntry entry, AclRole newRole)
{
entry.Role = newRole;
AclEntry updatedEntry = entry.Update() as AclEntry;
Console.WriteLine("Updated {0} to have role {1}", updatedEntry.Scope.Value,
entry.Role.Value);
return updatedEntry;
}
/// <summary>
/// Deletes a user from a calendar's access control list, preventing
/// that user from accessing the calendar. Note that this method will
/// not run by default.
/// </summary>
/// <param name="entry">An existing AclEntry representing sharing permissions.</param>
static void DeleteEntry(AclEntry entry)
{
entry.Delete();
}
#endregion
}
—————————–AppCode -> GoogleTokenModel.cs————————————–
public class GoogleTokenModel
{
public string Access_Token { get; set; }
public string Refresh_Token { get; set; }
public string Expires_In { get; set; }
public string Token_Type { get; set; }
}
——————————Bin folder————————–
These dlls need to be added in Bin folder.
Google.GData.Client
Google.GData.Calendar
Google.GData.AccessControl
Google.GData.Extensions
- Download Google Data API
- install the MSi
- get the above files from C:\Program Files\Google\Google Data API SDK\Samples
——————————Useful Links————————–
- https://developers.google.com/google-apps/calendar/v2/developers_guide_dotnet
- http://kelp.phate.org/2012/04/google-calendar-api-with-oauth-20.html
- http://www.tqis.com/eloquency/googlecalendar.htm#DOC81
To refresh access token
To revoke rights access token
