Have you been trying to connect your website or application to Google Calendar? Would you like to be able to show your users a Google Calendar for your website? If you are you trying to work with the Google Calendar API in C# .net I might be able to help. In this tutorial series we will be looking into how to connect to Google Calendar API using OAuth2, as well as a service account. I will show you how to get a list of the users Calendars. How to add events to a Calendar, and a number of other things as this tutorial series extends.
Google Calendar API – Tutorial Series
- Google Calendar API Authentication
- Google Calendar API Sample Project
Project Setup
Make sure your project is at least set to .net 4.0.
Add the following NuGet Package
//Nuget package https://www.nuget.org/packages/Google.Apis.Calendar.v3/
PM> Install-Package Google.Apis.Calendar.v3
Usings
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Google.Apis.Auth.OAuth2; using System.Threading; using Google.Apis.Util.Store; using Google.Apis.Calendar.v3; using Google.Apis.Services; using System.IO; using System.Security.Cryptography.X509Certificates;
[wp_ad_camp_3]
Authenticating Google Calendar API With C#
Authentication is the key to everything here. If you want to be able to access data you will need to be authenticated.
The two types of Authentication you can use are:
- Open Authentication or OAuth2 – Which is designed to allow you to access other peoples data. For Example: A user installs your application that will allow them to view there Google Calendar Data, before your application can view there data the user will be asked to authenticate your application giving your application permission to access their data.
- Service Account Authentication – Which is designed to allow you to access your own data. For example: You would like to display a Calendar for your website. For this there is no reason to ask permission because you already own this data.
I have created a separate tutorial that explains how to create the different credentials. Decide which type of authentication you need and please read though that tutorial and come back to continue this one.
Types of Authentication
There are two types of Authentication OAuth2 which will allow you to access another users data, and a service account which can be set up to access your own data. The code for them is slightly different.
Google Calendar API OAuth2 Authentication
If you want to be able to access data owned by someone else you will need to be authenticated. The code for authentication simply displays a webpage for your user asking them to give you permission to access there data. If the user gives you permission a file is then stored on the machine in the %AppData% directory containing all the information you will need in the future to access there data. For my testing purpose I use Environment.UserName as the name of the user, but if you are doing this web based you could use it as a session var of some kind.
That’s just fine but how does Google know what kind of permission you want to ask the user for? That’s where scopes come in, with scopes you define what permissions you need.
The code below will basically ask for everything, you should only include the scopes you NEED.
string clientId = "";//From Google Developer console https://console.developers.google.com string clientSecret = "";//From Google Developer console https://console.developers.google.com string userName = ""// A string used to identify a user. string[] scopes = new string[] { CalendarService.Scope.Calendar, // Manage your calendars CalendarService.Scope.CalendarReadonly // View your Calendars }; // here is where we Request the user to give us access, or use the Refresh Token that was previously stored in %AppData% UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets { ClientId = clientId, ClientSecret = clientSecret }, scopes, userName, CancellationToken.None, new FileDataStore("Daimto.GoogleCalendar.Auth.Store")).Result;
Assuming the user clicks Accept and gives you permission you will then have a valid user credential you can build upon.
The main problem you may have with this is that it is useing FileDataStore which stores the data in the users %AppData% directory while this is probably fine for an installed application this is probably not the optimal solution for a web application. If you want to store the data in the database you need to create your own implementation of IDataStore. You are in luck I have a working version of that on GitHub.
Google Calendar API Service Account Authentication
[wp_ad_camp_1]If you are only accessing data that you own there is no reason to ask a user for permission to access it. You can use a Service account. When setting up a service account for use with Google Calendar API you only need to take the Service account email address. Go to the Google Calendar website. Find the Calendar Settings , then go to the Calendars tab, find the calendar you want to access and click on “Shared: Edit settings” add the service account email address like you would a persons email address. This will give the service account the same access as if you where sharing it with any other user.
You will then use the keyfile loaded on the developer console along with the service account email address to get authorization.
string[] scopes = new string[] { CalendarService.Scope.Calendar, // Manage your calendars CalendarService.Scope.CalendarReadonly // View your Calendars }; var certificate = new X509Certificate2(keyFilePath, "notasecret", X509KeyStorageFlags.Exportable); ServiceAccountCredential credential = new ServiceAccountCredential( new ServiceAccountCredential.Initializer(serviceAccountEmail) { Scopes = scopes }.FromCertificate(certificate));
Google Calendar Service
Now that you are authenticated its only a matter of passing your credentials to create a new CalendarService. The service is where all of the magic is. It is though the service that all of the calls will be made to the Google Calendar API.
// Create the service. CalendarService service = new CalendarService(new BaseClientService.Initializer() { HttpClientInitializer = credential, ApplicationName = "Calendar API Sample", });
Conclusion
You should now understand how to access the Google Calendar API with an authenticated user. Join me for the next tutorial where we will look at how to get a list Calendars
If you had any problems with this tutorial you can check the a sample project for working with Google Calendar API on GitHub as part of the Google-Dotnet-Samples project. With in that project you will find a helper class for Authentication with Google Calendar . Authentication.cs
Hi Linda,
is there a way to configure the auth-uri before calling the GoogleWebAuthorizationBroker.AuthorizeAsync method?
I want to append the “login_hint=user@example.com” with a given user email to open the browser-login-process with this user prefilled! I want to prevent that the user authorize the app with the wrong user account.
Is this possible?
Cheers,
Ronny
I have been trying to find that as well. If you get it to work let me know please…!!
Hi,
i have looked at the source and I found no option to do that… maybe change the source of the library and use that instead directly from google…
The important class is the GoogleAuthorizationCodeFlow.Initializer class, because it holds the auth-url. it is defined in GoogleAuthConsts as a const string…
I tried to subclass GoogleAuthorizationCodeFlow.Initializer and override the getter/setter for AuthorizationServerUrl but the problem is the conversion back to GoogleAuthorizationCodeFlow.Initializer…
Any ideas?
Hi Linda,
here is my solution:
using Google.Apis.Auth.OAuth2;
using Google.Apis.Auth.OAuth2.Flows;
using Google.Apis.Auth.OAuth2.Requests;
using Google.Apis.Util.Store;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace MyOAuth2
{
//own implementation to append login_hint parameter to uri
public class MyOAuth2WebAuthorizationBroker : GoogleWebAuthorizationBroker
{
public new static async Task AuthorizeAsync(ClientSecrets clientSecrets,
IEnumerable scopes, string user, CancellationToken taskCancellationToken,
IDataStore dataStore = null)
{
var initializer = new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = clientSecrets,
};
return await AuthorizeAsyncCore(initializer, scopes, user, taskCancellationToken, dataStore)
.ConfigureAwait(false);
}
private static async Task AuthorizeAsyncCore(
GoogleAuthorizationCodeFlow.Initializer initializer, IEnumerable scopes, string user,
CancellationToken taskCancellationToken, IDataStore dataStore = null)
{
initializer.Scopes = scopes;
initializer.DataStore = dataStore ?? new FileDataStore(Folder);
var flow = new MyAuthorizationCodeFlow(initializer, user);
// Create an authorization code installed app instance and authorize the user.
return await new AuthorizationCodeInstalledApp(flow, new LocalServerCodeReceiver()).AuthorizeAsync
(user, taskCancellationToken).ConfigureAwait(false);
}
}
public class MyAuthorizationCodeFlow : GoogleAuthorizationCodeFlow
{
private readonly string userId;
/// Constructs a new Google authorization code flow.
public MyAuthorizationCodeFlow(Initializer initializer, string userId)
: base(initializer)
{
this.userId = userId;
}
public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(string redirectUri)
{
return new GoogleAuthorizationCodeRequestUrl(new Uri(AuthorizationServerUrl))
{
ClientId = ClientSecrets.ClientId,
Scope = string.Join(” “, Scopes),
//append user to url
LoginHint = userId,
RedirectUri = redirectUri
};
}
}
}
It appears the problem is the async and await keywords, deleting those all work correctly
following the working code:
using Google.Apis.Auth.OAuth2;
using Google.Apis.Auth.OAuth2.Flows;
using Google.Apis.Auth.OAuth2.Requests;
using Google.Apis.Util.Store;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Google.Apis.Json;
using System.Net.Http;
using Google.Apis.Auth.OAuth2.Responses;
using Google.Apis.Requests;
using Google.Apis.Requests.Parameters;
namespace MobiSync.Providers.GMAIL.Helpers
{
//own implementation to append login_hint parameter to uri
public class CustomOAuth2WebAuthorizationBroker : GoogleWebAuthorizationBroker
{
public new static Task AuthorizeAsync( ClientSecrets clientSecrets,
IEnumerable scopes, string user, CancellationToken taskCancellationToken,
IDataStore dataStore = null )
{
var initializer = new MyAuthorizationCodeFlow.Initializer
{
ClientSecrets = clientSecrets,
};
return AuthorizeAsyncCore( initializer, scopes, user, taskCancellationToken, dataStore );
}
private new static Task AuthorizeAsyncCore(
MyAuthorizationCodeFlow.Initializer initializer, IEnumerable scopes, string user,
CancellationToken taskCancellationToken, IDataStore dataStore = null )
{
initializer.Scopes = scopes;
initializer.DataStore = dataStore ?? new FileDataStore( Folder );
var flow = new MyAuthorizationCodeFlow( initializer, user );
// Create an authorization code installed app instance and authorize the user.
return new AuthorizationCodeInstalledApp( flow, new LocalServerCodeReceiver( ) ).AuthorizeAsync
( user, taskCancellationToken );
}
}
public class MyAuthorizationCodeFlow : GoogleAuthorizationCodeFlow
{
private readonly string userId;
/// Constructs a new Google authorization code flow.
public MyAuthorizationCodeFlow( Initializer initializer, string userId )
: base( initializer )
{
this.userId = userId;
}
public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest( string redirectUri )
{
System.Diagnostics.Debug.WriteLine( “I’m here”);
return new GoogleAuthorizationCodeRequestUrl( new Uri( AuthorizationServerUrl ) )
{
ClientId = ClientSecrets.ClientId,
Scope = string.Join( ” “, Scopes ),
//append user to url
LoginHint = userId,
RedirectUri = redirectUri
};
}
}
}
Can you please write tutorial on google calendar api push notification
Unfortunately i don’t think that i can. This requires that you have a domain registered. The only domain i own is this one and it runs PHP. I would need access to a domain on a windows server to test this.
I can not get the api google.Apis.services What i can do ??
your missing one of the reference dlls. make sure the package installed correctly. Install-Package Google.Apis.Calendar.v3
can you write tutorial on gmail calendar service push notification in charp.
https://developers.google.com/google-apps/calendar/v3/push.
I am following the steps described in this walkthroug but still failed to received notifications.
Thanks
Unfortunately i don’t think that i can. This requires that you have a domain registered. The only domain i own is this one and it runs PHP. I would need access to a domain on a windows server to test this.
Hi Linda
I read your tutorials for Oauth 2 and all found to be very helpful. Thanks for sharing the tutorials. However I am facing one problem. I am accessing calendars using my C# application. Application is authenticate using user credentials. When user consent launches in web browser user close it without allow or cancel. In this scenario Google don’t return any value and application gets hang. How can we come to know that user cancel the user consent?
Thank you.
Add a try catch around the GoogleWebAuthorizationBroker section before you create the service. If the user hits cancel it will return
InnerException = {“Error:\”access_denied\”, Description:\”\”, Uri:\”\””}
I am already adding try catch around GoogleWebAuthorizationBroker but not throwing any exception. When user consent tab in web browser is closed (Alt + F4) without clicking on Allow or Cancel application gets stuck.
Could you please suggest any solution on this?
try
{
GogleWebAuthorizationBroker gWebAuthorizationBroker = new GoogleWebAuthorizationBroker();
CientSecrets _ClientSecret = new ClientSecrets();
_ClientSecret.ClientId = ClientId.;
_ClientSecret.ClientSecret = ClientSecret;
FileDataStore objFileDataStore = new FileDataStore(applicationPath, true);
System.Threading.Tasks.Task userCred = GoogleWebAuthorizationBroker.AuthorizeAsync(_ClientSecret,
new[]{ CalendarService.Scope.Calendar},
Username,
System.Threading.CancellationToken.None,
objFileDataStore);
UserCredential _userCredentials = await userCred;
}
catch (Exception)
{ }
OK … That is seriously weird. You are correct I would expect it to timeout or something. I am going to test this a little and if i cant get it to work I am going to submit it as a bug to the client library. Well spotted.
I contacted Google developer on the .net client lib team. we agree its a bug. I have logged an issue for it. https://code.google.com/p/google-api-dotnet-client/issues/detail?id=530
One more thing about the calendar item. Can I get the attachment of the calendar event? Not getting any solution for it as well.
Hi Linda, is there any way to authenticate the user using user name and password without opening the web browser?
I would like to build the application where the user inserts his name and password.
Thanks,
Saar
no unfortunately Google does not allow client login you need to use Open Authentication.
What is the best way to debug?
I keep getting an internal error, when trying to create UserCredential – but the error message is not very informative.
When testing a webservice on localhost, what should the redirect uri be?
BR, Mikkel
When testing a web-service localhost, http://localhost/Oauth2.aspx or create a Client ID for native application but what ever you do don’t release it with the Client ID for native application credentials. I just find it easier to use that then you don’t have to deal with the hole redirect uri nightmare with visual studio adding ports.
Do a try catch what exactly is the error its coming with?
I got it working on my local machine – using http://localhost/authorize/ as redirect uri
But won’t work on hosted server. According to Fiddler I get these exceptions.
{“Message”:” at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)\r\n at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)\r\n at System.Threading.Tasks.Task`1.get_Result()\r\n at DSInettetUserControls.CalendarServicesV3.GetFeed(String start, String end, Int32 numberToRetrieve, String calendarID)”,”StackTrace”:” at DSInettetUserControls.CalendarServicesV3.GetFeed(String start, String end, Int32 numberToRetrieve, String calendarID)”,”ExceptionType”:”System.ArgumentException”}
It really drives me crazy!
Im using your idatastore btw…works great. Thx 🙂
I’ve the ” http://localhost/authorize/” issue on my machine, how avoid it (to do a real deploy to customer)? I can’t fine “native application” option in console…
-_-
will the real customer be running it on localhost or from a web server?
Hi Linda,
“var certificate = new X509Certificate2(keyFilePath, “notasecret”, X509KeyStorageFlags.Exportable);”
What is the KeyFilePath? Is this the path of the location of the certificate file on the developer’s computer? Or is it a path to the Google Developers Console? I’m developing apps on a newer laptop than the one I created the service account info from. Do I need to generate a new P12 key? If I do, will it replace the current P12 key or will I have two keys? I plan to use the Service Account authentication.
That’s the path to the key file on your pc. c:\blah\key.p12 you only need one key file its fine to use that on different pc’s.
what is the “notascrete” ? is it email password ? if not from where i will get it ?
oops !!! got it. gets created when p12 is generated.
Hi Linda,
I need someone (you I hope) to point me in the right direction.
On our company intranet we have a calendar, we use for internal stuff….like booking a meeting room. Behind the calendar there is a google calendar, to which I make some standart api calls like insert, delete, getEntries etc.
Since the Calendar V3 update it doesn’t work anymore of course, so I need to change my api calls – but Im not sure how.
What I want to acomplish is:
I have a google calendar to which I will allow people to insert, delete and change entries via a custom interface that use google api v3 (.Net).
They (the people) might NOT have a google account on their own.
They (the people) DON’T know the password or username to the calendar account.
The calendar stuff is not a secret – I accept low sescurity if necessary.
As I understand, I can only use “Public API access” to show entries, but not add or delete. Is that correct?
What kind of auth. would you recommend for a solution like this?
Best Regards, Mikkel
I would go with a service account if i was you. You wont need a login. Drawback no one will be able to see it on the Web version of Google Calendar but that doesn’t sound like it will be an issue for you.
Hi,
I’ve a similar case, where I’m building solution for meeting rooms.
In my case, I need to show calendar events of multiple google accounts. I want only readonly access to the calendar.
please suggest, how can I do that.
Vinay
I can think of a few ways of doing that.
1. Create a service account give the owners of the accounts the service account email address ask them to grant it access to the calendar in question.
2. Use Oauth2 and request read only access to the users calendars.
Hi Linda,
is it possible to access to any Google Calendar (user enters a public link or username and password)? (readonly)
I am using the .net library.
Thanks Lukas!
No you cant use Client login (Login and password) to access any of the Google APIs useing the .net client library. As of April 20th 2015 you wont be able to access any of the Google APIs like this.
You need to use Open Authentication.
I have 100 google calendar user and I need to create event in their calendar. Event is different from one to another. I have all 100 users gmail id. Please suggest me how to achieve this?
All event related information is available in Database.
1. Should I need to use OAuth2 ?
2. How to achieve this 100 users? Do I need to create 100 OAuth2 Authentication?
Please advice. Thanks.
You will need to have each of your users authenticate your application, then you can save the refresh-token somewhere say the database. Once you have there permissions you will be able to add events to there calendar when ever you like. Yes you will need to use Oauth2.
Hello Linda, I hope you’re there.
I’m attempting to stand on your shoulders and I keep falling off !
I have a main goog calendar, while logged in, i created 2 calendars, made them public and shared them to other gmail accounts. The account for ‘main’ has a project, api’s enabled and various credentials,. the important one being the native app creds. CLIENT_ID + CLIENT_SECRET. In your Clndr-Api-dotnet console app, I put in the databasedatastore code from your api auth project. I set the client_id, client secret, calendarid and the constructed dbdatastore, all good. On 1st run, I get the auth challenge, grant it, the token is captured and subsequent runs utilize the refresh token and all is well. Each calendar id was handled in the same way, 1st run auth, capture the token; insert to db as separate row etc. I am using the same client_id and client_secret for all these “child” calendars since “main” is the creator / owner of them
I’m off in the stix with the following behavior though. For the first child calendarid, the google.apis.calendar.v3.data.events object AccessRole property returns with “owner” ..all good. For the 2nd (and subsequent) calendarid’s the role returns as “reader” ..yikes.. Honest to Pete, these calendars are set up exactly the same way. I’ve been spinning my wheels for more than a few hours, trial and error with no joy. I’m leaning toward the reason being something “dumb” & not fathoming what dumb might be. I’m requesting your opinion. Can you suggest any approach to diagnosis and or fix. Rich in Austin.
How did you create these two calendars? I have seen this before with Access being messed up.
Ok, it’s a “dumb” for sure. In my implementation, the service account is totally adequate for doing crud on various child calendars: the scenario being a “master” calendar where n number of “child” calendars are created and shared to appropriate gmail accounts, Even though each child calendar is shared allowing R/W by the associated gmail user, that is not enough to allow the service account to do anything but read. The appropriate role has to be added. One way to add is to use the “developers.google.com.google-apps/calendar.reference/acl/insert/#example” first. From the top, the steps are 1. create a gmail account. then a calendar (this is your container calendar), 2 Since you are logged in on that gmail account, go on the console.developers.google site, create a project on that account, enable the calendar api, derive the oauth service account creds.. 3. go back over to the calendar, add a child calendar, 4.share that child calendar to a gmail email of your choice, (make sure to accept the invite sent to that email while logged in on that email account) . 4. Go back over and make sure you’re logged into the account that owns the calendar and project, go to the “master” calendar , find the child calendar, got into it’s settings, and copy the calendar id. 5. Go back over to the developers.google.com.google-apps/calendar.reference/acl/insert/#example, turn on oAuth 2.0 (you’ll see the auth window come and go) scroll down to the “try it! ” area and put the calendarid in the calendarid box, put in “writer” in the role box, under “scope” put “user” for the Type and add a value param. In the value param paste in your SERVICE_ACCOUNT_EMAIL. 6. Click Execute. Note the http 200 -or- fix an error. Once this role has been added, the service account will be able to r/w events to the child calendars.
This worked for me and is easier to deploy than using the native app route. Rich
Could you please post an simple example , how to create events in google calender
From win forms or asp.net ,
Have you checked the sample project? DaimtoEventHelper.cs
Thanks for your replay,
Actually my first application on google.apis
please help me
i tried you code from github,
i tried to develop a simple application to create an event in google calender
from win forms applications
by using the service account auth
am receiving the error
“Unexpected character encountered while parsing value: <. Path '', line 0, position 0."
My Code:
CalendarService service;
String SERVICE_ACCOUNT_EMAIL = "XXXXXXXXXXXXXXXXX@developer.gserviceaccount.com";
string SERVICE_ACCOUNT_KEYFILE = @"d:\EVENTREQUEST-a873840e956d.p12";
service = Authentication.AuthenticateServiceAccount(SERVICE_ACCOUNT_EMAIL, SERVICE_ACCOUNT_KEYFILE);
// Authenticate Oauth2
eventdata.Summary = "title";
eventdata.Location = "location";
eventdata.Description = "description";
EventDateTime start = new EventDateTime();
start.DateTime = DateTime.Now;
eventdata.Start = start;
EventDateTime end = new EventDateTime();
end.DateTime = DateTime.Now.AddHours(1);
eventdata.End = end;
eventdata = DaimtoEventHelper.insert(service, "1", eventdata);
Hi Linda,
You example show using the P12 file generated to create the ServiceAccountCredential’s
Do you know how to do the same with the json file option?
I’m guessing that you would not call the “.FromCertificate(certificate)”
And would be setting the key, but not sure what mapping would be or how to convert.
I don’t think that is supoorted by the current version of the client library Add support for Service Account authentication with JSON Key File
hi I’ve been having some difficulty with creating events onto google calendar with .net, I couldn’t fully make use of your sample codes as I’m really just bad at .net
what problem are you having?
I need to use Google Calendar Api from ASP.NET Web Api application. Is there a substitute available for RedirectResult as ApiControllers doesn’t have this and Google’s Mvc4 library uses ResultRedirect to get the authorization.
Hi, I have an app that uses Authentication.AuthenticateOauth and works perfectly on localhost: i can get the events of the calendar’s users and insert new events too but when deply my App to production server with IIS 7.5 my app doesn’t work. I have all dll on the bin, can you help me please?
What do you mean by doesn’t work?
i am getting the same IIS issue?who did u resolve it.
Just wanted to say thanks for all your examples.
They helped me immensely in starting to secure some of our applications using Google instead of LDAP.
Hi Linda,
Is there any support for web-proxy in Google calendar V3 API? I could not find anything.
Google question. Try posting on the client library Eyal will know, he checks issues regularly.
Hi Linda,
Please see https://github.com/google/google-api-dotnet-client/issues/133. Probably somebody filed it earlier.
But they have marked it as fixed ..by giving reference to proxy support in system.net.http.httpclienthandler.
Could you please explain how it will work along with the sample that you have given using GoogleWebAuthorizationBroker.AuthorizeAsync? That will be of a great help.
Thanks,
Amol
add this comment to the issue tracker on that one and i will reopen the issue we can address it there. I would rather keep issues with the client lib addressed on the Issue tracker then spliting them to my website. Someone may have a similar question to yours we should keep them central.
Thanks, Linda.
For the sake of clarity, I filed separate issue https://github.com/google/google-api-dotnet-client/issues/567 . Please take a look at it.
I will look into it. Sounds like something that is missing in the client library itself. I have very little experience with proxy servers so this is going to take some research.
Found a work-around. Added details in the issue-tracker. Thanks.
Hi Linda! Thanks for the tut, it is great!
I’m getting this error: “Key MUST have a value” in the credential line, do you know what that is?
Thx
Javier
which example are you testing Oauth2 or service account?
Hi Linda,
Thank you for your excellent work. I have two problems, here is the first.
I’m trying to use oauth2 to let a user authenticate and then add events, blah blah,
my authentication code is below.
The problem is that this page hangs and never returns, the consent screen never appears.
using System;
using System.Linq;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Calendar.v3;
using Google.Apis.Calendar.v3.Data;
using Google.Apis.Services;
using System.Configuration;
using System.Threading;
namespace Events
{
public partial class Events_newauth2 : System.Web.UI.Page
{
CalendarService service;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (service == null) { service = CreateService(); }
CalendarList result = service.CalendarList.List().Execute();
foreach (CalendarListEntry calendar in result.Items)
{
lblNote.Text += “” + calendar.Id + ” : ” + calendar.Summary;
}
}
}
protected CalendarService CreateService()
{
UserCredential credential;
try
{
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
new ClientSecrets
{
ClientId = ConfigurationManager.AppSettings[“ClientID”],
ClientSecret = ConfigurationManager.AppSettings[“ClientSecret”]
},
new[] { CalendarService.Scope.Calendar },
“tweissert@agnesirwin.org”,
CancellationToken.None,
new DatabaseDataStore(“Websrv”, “aspnet”, “123”, “CalendarEvents”, “GoogleUser”)).Result;
}
catch
(Exception ex)
{
lblNote.Text = ex.Message;
return null;
}
CalendarService theservice = new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = “AIS Calendar Tool”,
});
return theservice;
}
}
}
I would debug it step by step. If the consent screen isn’t appearing there may be an issue in your datastore. there could also be an issue in the redirect uri, or with IIS not having access… There could be a lot of things wrong.
I’m sure it must be the redirect uri; but where is it? It isn’t specified by this method. There are four listed on the project. The previous oauth2 method explicitly contained the redirect uri.
You don’t need to add the redirect URI with the client library it handles that for you. If memory serves it normally ends in something like http://localhost/authorize/
Hi Linda,
I am using Google Calendar API Service Account Authentication for reservation application.
I am having below error: “An error occurred while sending the request. —> System.Net.WebException: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. ”
it works fine on local pc. but when I upload it into the server it gives an error. (below). please help me to resolve this.
2015-08-05 15:57:06,018 – Error when Insert to google cal ‘GoogleCalendarSync’ >>An error occurred while sending the request.
2015-08-05 15:57:06,018 – ex.StackTrace’ >> at Google.Apis.Requests.ClientServiceRequest`1.Execute()
at WebService.GoogleCalendarSync.GoogleCalendarSyncProcess(Int32 RsvId, String GroupId, String Summary, String Desc, String StartTime, String EndTime, String Location, String OrganizerEmail)
2015-08-05 15:57:06,018 – ex.Source’ >>System.Net.Http.HttpRequestException: An error occurred while sending the request. —> System.Net.WebException: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. —> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
at System.Net.TlsStream.EndWrite(IAsyncResult asyncResult)
at System.Net.PooledStream.EndWrite(IAsyncResult asyncResult)
at System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult ar)
— End of inner exception stack trace —
at System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context)
at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar)
— End of inner exception stack trace —
at Google.Apis.Requests.ClientServiceRequest`1.Execute()
at WebService.GoogleCalendarSync.GoogleCalendarSyncProcess(Int32 RsvId, String GroupId, String Summary, String Desc, String StartTime, String EndTime, String Location, String OrganizerEmail)
here are my code segments:
var serviceAccountEmail = “*************nt.com”; // found https://console.developers.google.com
var keyFilePath = @”D:\Production\apps.p12″; // Downloaded from https://console.developers.google.com
service = Authentication.AuthenticateServiceAccount(serviceAccountEmail, keyFilePath);
public static CalendarService AuthenticateServiceAccount(string serviceAccountEmail, string keyFilePath)
{
// check the file exists
if (!File.Exists(keyFilePath))
{
log.Error(“AuthenticateServiceAccount >>An Error occurred – Key file does not exist”);
return null;
}
string[] scopes = new string[] {
CalendarService.Scope.Calendar , // Manage your calendars
CalendarService.Scope.CalendarReadonly // View your Calendars
};
var certificate = new X509Certificate2(keyFilePath, “notasecret”, X509KeyStorageFlags.Exportable);
try
{
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = scopes
}.FromCertificate(certificate));
// Create the service.
CalendarService service = new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = “Calendar API Sample”,
});
return service;
}
catch (Exception ex)
{
log.Error(“AuthenticateServiceAccount >>” + ex.Message);
// Console.WriteLine(ex.InnerException);
return null;
}
}
please help me to solve this issue.
I would check if ssl works on the server.
How can I get clientSecret ?
string clientSecret = “”;//From Google Developer console https://console.developers.google.com
I get clientID
public const string CLIENT_ID = “1xxxxxxxxxxxxxxxx.apps.googleusercontent.com”;
I don’t see clientSecret in Google Developer console https://console.developers.google.co
Client secret is created in the Google Developer console, under APis & Auths -> credentials. You might want to read my Open Authentication post.
Hi Linda,
Diamto.Google.Authentication/DatabaseDataStore.cs saves refresh token only, how about access token?
CREATE TABLE dbo.GoogleUser(username nvarchar(4000), RefreshToken nvarchar(4000), Userid nvarchar(4000))
Based on my experience with Calendar API v2, I suppose access token is useful for
– health check whether the token is still valid
– refresh itself
– revoke a previously permitted access
Any idea?
No real reason to save the access token when it expires after an hour. You can just use the refresh token to get a new access token when ever you need. I am not aware of any limits to the number of times you can request a new access token or how often you can request it.
– I don’t bother with health check normally i just request a new one.
– you use the refresh token to revoke it i think not the access token. (But its been a while since i have done that i may be wrong.)
Hello,
thanks for your great tutorial.
So far i could make it run, but i’m running into an error “GoogleWebAuthorizationBroker.AuthorizeAsync”
“The character set provided in ContentType is invalid. Cannot read content as string using an invalid character set.”
“UTF-8″‘ is not a supported encoding name. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method.\r\nParameter name: name”
I already search an houre on the internet but without success.
Do you have any idea what could be the problem?
Thanks for your help in advance,
greetings,
Caipigott
Hi,
i’m sorry, i just found out that it’s up to the internet connection of my work. I guess it blocks the response, or something.
No i used the connection of my celular and it worked.
Greetings,
Caipigott
Hi Linda,
Thanks for this tutorial. Have you done any tutorials yet on how to create an event on google calendar from a C# application in visual Studio?
///
/// Documentation:https://developers.google.com/google-apps/calendar/v3/reference/calendarList/insert
///
/// Valid Autenticated Calendar service
/// Calendar identifier.
/// an event
/// event resorce: https://developers.google.com/google-apps/calendar/v3/reference/events#resource
public static Event insert(CalendarService service, string id, Event body)
{
try
{
return service.Events.Insert(body,id).Execute();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return null;
}
}
Ok, Thank You. I noticed that piece of the code was there after I posted the comment, Sorry. I’m going to give it a try now.
I am wokring on Google calendar API using C#. I am devloping a web page that will access the my clients(specific user) calendar and display just the calendar’s information,events etc on web page. So, I don’t want the user to enter in their Google account information which is what oAuth wants to do.
i used the following code
string serviceAccountEmail = “serviceAccountEmail “;
string filepath = Application.StartupPath + @”\file.p12”;
var certificate = new X509Certificate2(filepath, “notasecret”,
X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(new
ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes =
new[] { CalendarService.Scope.Calendar }
}.FromCertificate
(certificate));
BaseClientService.Initializer initializer = new
BaseClientService.Initializer();
initializer.HttpClientInitializer = credential;
initializer.ApplicationName = “Google Calendar Sample”;
CalendarService calservice = new CalendarService(initializer);
//Follwoign line did’t get my calendar events
EventsResource.ListRequest request = calservice.Events.List(“primary”);
Events events = request.Execute();
I want to access the calender of specific email and need to show all the events etc .
Kindly help.
Thanks
Regards
Mudasser
Make sure you have taken the Service account email address and added it as a user on the Calendar in the Google Calendar website you can also find the Google Calendar id there, Primary isn’t going to work with a service account.
I added the service account using my Google email,
lets say my email is “abc@gmail.com” and service id generated is “gooleserviceygx@serviceaa-4789.ibm.gstrviceaccount.com”
Then i created the public calendar(Calender Name:My events Calender) on using my Google account(abc@gmail.com),then created the Event in that public calender(My events Calender) lets say event is party.
Then i edit my google calander setting(Shared: Edit settings) and add my service account in Share with specific people section.
Following code i used
string serviceAccountEmail = “gooleserviceygx@serviceaa-4789.ibm.gstrviceaccount.com “;
string filepath = Application.StartupPath + @”\file.p12”;
var certificate = new X509Certificate2(filepath, “notasecret”,
X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(new
ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes =
new[] { CalendarService.Scope.Calendar }
}.FromCertificate
(certificate));
BaseClientService.Initializer initializer = new
BaseClientService.Initializer();
initializer.HttpClientInitializer = credential;
initializer.ApplicationName = “Google Calendar Sample”;
CalendarService calservice = new CalendarService(initializer);
//Follwoing line did’t get my calendar events
EventsResource.ListRequest request = calservice.Events.List(“primary”);
Events events = request.Execute();
Above line suppose to get event(party) which i added in my public calendar(My events Calender) but it is not getting.
My requirement is whatever i added or add on my calender it should shows on my public website.
A service account is not you, even though you created it with your personal gmail its still not you it has its own google calendar.
calservice.Events.List(“primary”);
Primary is the service accounts primary calendar which is not yours.
You need to go back in the settings and find the calendar id for your personal calendar.
How i can get the events by having the calender ID?without being authenticated?
If the calendar is public then you can use a public API key. If its someones personal calendar then you cant, you need to be authenticated to access private data.
Can you kindly share some sample (C#) to get the public calender events using public key without being authenticated.
Thanks in advance for help
Have you checked my Public Google Calendars with C# tutorial?
thanks for your help.Its so nice of you.
Kindly just tell me, if i create a new calender by the following code, is it possible by code to make that calender as public.
Calendar cal = new Calendar();
cal.Summary = “calander created by code”;
Calendar createdCalendar = service.Calendars.Insert(cal).Execute();
And also kindly tell is there any way to get the public calendar only or any way to check either calender is public or not
CalendarList clst = cservice.CalendarList.List().Execute();
calendar list just shows you the list of calendars you have added to calendar list. i would do calendar.get that might show if the calendar is public or not.
Hello Linda,
I published the Daimto.GoogleSample.Analytics to azure and got this message:
2016-04-11T21:06:06 PID[17220] Information System.Net.HttpListenerException (0x80004005): Access is denied
2016-04-11T21:06:06 PID[17220] Information at Microsoft.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
2016-04-11T21:06:06 PID[17220] Information at Microsoft.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccess(Task task)
2016-04-11T21:06:06 PID[17220] Information at Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.d__1.MoveNext()
2016-04-11T21:06:06 PID[17220] Error
2016-04-11T21:06:06 PID[17220] Error Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
2016-04-11T21:06:06 PID[17220] Error at Daimto.Google.Sample.Analytics.DaimtoAnaltyicsManagmentHelper.AccountSummaryList(AnalyticsService service)
2016-04-11T21:06:06 PID[17220] Error at Daimto.Google.Sample.Analytics.
Do you have any clue?
Hello,
I created the sample Asp.net application to get all the calender and add event in a calendar.My Application is working fine when i run it using Visual Studio it successfully load the page,show all calendar info, add event in calendar.But when i deploy the app on IIS, page never load and it gives the “Request timed out” exception.Kindly help
Following is the code
private CalendarService InitGoogleService()
{
UserCredential credential;
string path = Server.MapPath(“~”) + @”\GCSc.json”;
string credPath = Server.MapPath(“~”) + @”\Calendar_Data”;
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets
{
ClientId = “My Client Id”,
ClientSecret = “My Client Secret”
}, Scopes, “user”, CancellationToken.None, new Google.Apis.Util.Store.FileDataStore(credPath)).Result;
CalendarService service = new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
return service;
}
Make sure iis has access to CredPath, what application pool do you have iis running as?
hello:
I am trying to import calendar settings into google calendar and followed your instructions, but I get an access error when I publish my code to staging server. codes works great in my local machine, how do I get around this ? any suggestions?
here is my code:
String gpath = dataPath + “/credentials/siteAPI.json”;
UserCredential credential;
ClientSecrets secrets = new ClientSecrets()
{
ClientId = “aaaaa”,
ClientSecret = “yyyyy”,
};
using (var stream = new FileStream(gpath, FileMode.Open, FileAccess.Read))
{
//string folder = System.Environment.GetFolderPath( System.Environment.SpecialFolder.ApplicationData);
//folder = Path.Combine(Environment.GetFolderPath(System.Web.HttpContext.Current.Server.MapPath(“YourFolderName”), folder));
String g = dataPath + “\\credentials”;
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
//GoogleClientSecrets.Load(stream).Secrets,
secrets,
new[] { CalendarService.Scope.Calendar },
“user”,
CancellationToken.None ,
new FileDataStore(g)
).Result;
}
at this stage I get :
System.ComponentModel.Win32Exception: Access is denied at Microsoft.Runtime.CompilerServices.TaskAwaiter.T …..
error
many thanks
Henry
I would post your question to stackoverflow make sure to tag it google-calendar and google-apis-dotnet-client it will be easier to fix your problem with more eyes on it.
can we get all events of primary calendar by using only email without client id and client secret
You need the client id and client secrete to use the refresh token. You need a client id and client secrete to get an access token. Client id and client secret identify your application to google you will always need that.
Hello Linda,
Recently i have upgraded the .net google calendar API 1.9.0.26011 to Google.Apis… 1.27.1.878
After that the environment path changed from “C:\Users\LOGONUSER\AppData\Roaming\Calendar.Auth.Store”
“C:\Windows\system32\config\systemprofile\AppData\Roaming\Calendar.Auth.Store” and shows access error event if we use admin account as impersonate user in web.config file, any idea about this path change?
One or more errors occurred.Access to the path ‘C:\Windows\system32\config\systemprofile\AppData\Roaming\Calendar.Auth.Store\Google.Apis.Auth.OAuth2.Responses.TokenResponse-user1@gapps.dddd.com’ is denied.
What type of system is this? What type of project are you working with? App data is not normally in windows\system32 the default pat should be something like his C:\Users\HP_User\AppData\Roaming\Calendar.Auth.Store\Google.Apis.Auth.OAuth2.Responses.TokenResponse-user1@gapps.dddd.com
I am not aware of any changes to were things were stored you can change the default storage location of file datastore yourself this may help Google .net – FileDatastore demystified
Thank you very much for your advice. Yes i have noticed this option to provide full path like FileDataStore(@”c:\datastore”,true) and i changed my program to use full path, now it is working fine.
we have integrated google calendar api with one of our asp.net web application and for the past 3 years it was working perfectly with only store name. but after upgrading the library locally it works fine, but on deployment server we noticed that the store path is like “‘C:\Windows\system32\config\systemprofile\AppData\Roaming\Calendar.Auth.Store\”. Older version on same deployment server still using “C:\Users\LOGONUSER\AppData\Roaming\Calendar.Auth.Store” so that means some changes happened with google calendar api .net libraries. But not able to find any documents on this change.
I have contacted one of the main devs on the project he told me the reason for this I have added it as an issue here FileDataStore default location change
It will be great if you could share the reason you heard from from dev.
It looks like this is due to a change in how the default FileStore location is determined from v1.25.0 to v1.26.2.
In v1.25.0 (on Windows Desktop) it uses Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
In v1.26.2+ it uses Environment.GetEnvironmentVariable(“APPDATA”)
On my test system these evaluated to identical directories, but it looks like this isn’t the case on the user that asked the question, or perhaps isn’t true generally on ASP.NET deployments.
The reason for this change is to support FileDataStore on .NET Core (which doesn’t support SpecialFolder), and it was not intended to affect other customers, so this is unfortunate.
The fix would be to use an #if in the code to continue to use Environment.SpecialFolder.ApplicationData only on the .NETFramework4.5 DLL in the package.
I could do a 1.27.2 release with just this change, but I think I’d rather not. It’s probably now better just to leave things as they are, seeing as this new behaviour has been released now for about six weeks.
Hello Linda,
I have been trying to read calendar events using the calendar service Events.List method within a .Net program.
Unfortunately, this method retrieves all events.
Google Calendar supports timeMin and timeMax optional parameters but I do not manage to use then with a .Net client.
I am quite desperate and not looking forward to use the API with HTTP…
Did you do use this filtering option?
Do you have pointers?
Any ideas?
And thank you for your usefull posts.
Eric.
I found the answer: do not focus on the RequestParameters collection. It describes allowed parameters. It doesn’t contain the parameters values. Those values are in the request object itself:
var rq = service.Events.List( “primary” );
rq.TimeMin = aDateTime;
rq.TimeMax = aDateTime.AddDays(1);
rq.SingleEvents = true;
var events = rq.Execute();
So simple…
.Net is strongly typed. I should have looked there first.
String Scopes[]= new String[2]
{
CalendarService.Scope.Calendar,
CalendarService.Scope.CalendarReadonly
};
I am getting a error in this
Error 1 Bad array declarator: To declare a managed array the rank specifier precedes the variable’s identifier. To declare a fixed size buffer field, use the fixed keyword before the field type.
Hey I resolved it .. !
It was because of the scope opr
Hi Linda,
I am facing a strange problem. I’ve created a google app that do the oauth authentication for the user. I’ve created one project that create add/edit and delete events in my application calendar. Once event is created in my application calendar at the same moment it will create an event in the authenticated google calendar.
one of my friend is using this app and when he authenticate using this app, it authenticates successfully.
when he create an event in my application, it should create that event to the authenticated google calendar, but it syncs to the other google calendar. In My google calendar account there are multiple calendar added and the event is created in one of the calendar.
Can you help me out in this.
How exactly are you handling the authentication to your account? Are you using a service account? Sounds like you have your calendar services mixed up.
Thank you mam for your blog,
I am trying access google calendar API from my ASP.NET project.
I am using service account key to access google calendar API.
My code look similar to your have mention in your blog.
My asp.net works fine on my local machine but when I upload it to server it start giving me an error.
I had ask question on Stack Overflow, you can see my question on following link
https://stackoverflow.com/questions/50599764/c-google-apis-auth-oauth2-responses-tokenresponseexception-errorinvalid-cli
Mam please guide me what should I do for solve my error.
I have some newer examples of service accounts that might help serviceaccount.cs
Hi Linda,
I am able to read the Google Calendar using oAuth2 from a window client application. However, when I implemented for web, GoogleWebAuthorizationBroker.AuthorizeAsync() function call hangs, it never opens up pop up browser window to ask user authentication. Please advise.
If I use the credential file created via window client, even web app reads the google calendar. So, only issue seems is opening a brwoser window for authentication permission.
Thanks!
Neeraj Tomar
There is a difference between native application authentication and web authentication. You should be following this [Web applications](https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth#web-applications-aspnet-mvc)
GoogleWebAuthorizationBroker does not work in ASP.NET WebForms. Do you have a article or give some reference on it ?
just this. https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth#web-applications-asp.net-mvc
Hi Linda
how can i get the ClientID and ClientSecret automatically without get them manually or downloading the JSON file ?
no there is no api for google developer console it needs to be done manually.
I using the same process but after creating the events the system is unable to send notification mail to all attendees. Below is the code I am using to enable notification.
String calendarId = “primary”;
EventsResource.InsertRequest request = service.Events.Insert(newEvent, calendarId);
request.SendNotifications = true;
request.SendUpdates = EventsResource.InsertRequest.SendUpdatesEnum.All;
Event createdEvent = request.Execute();
there was a bug in the api it should be fixed now.
Hi, I am using a google service account in c# and I can use CalendarList.List().Execute(), I have a couples of calendar and I can add events fine. But today I tried to add another calendar that I own, I put the service account’s email in the share of the calendar with full access like I did usually, but CalendarList is not giving me the new one, the pageToken is null, it looks like the service account is not accepting the invitation automatically like usualy? Would you know why the share doesn’t work? thanks.
Google made a change a while back service accounts only work with GSuite accounts now. YOu need to set up domain wide delegation to the service account and it can only work with users on the domain.
Dear Linda,
I use Service Account to create a calendar event and I got an error:
‘Google.Apis.Requests.RequestError
Not Found [404]
Errors [
Message[Not Found] Location[ – ] Reason[notFound] Domain[global]
Can you help me fix it? My code:
public class ServiceAccountAuthHelper
{
///
/// Authenticating to Google using a Service account
/// Documentation: https://developers.google.com/accounts/docs/OAuth2#serviceaccount
///
/// From Google Developer console https://console.developers.google.com
/// Location of the .p12 or Json Service account key file downloaded from Google Developer console https://console.developers.google.com
/// AnalyticsService used to make requests against the Analytics API
public static CalendarService AuthenticateServiceAccount(string serviceAccountEmail, string serviceAccountCredentialFilePath)
{
try
{
if (string.IsNullOrEmpty(serviceAccountCredentialFilePath))
throw new Exception(“Path to the .p12 service account credentials file is required.”);
if (!File.Exists(serviceAccountCredentialFilePath))
throw new Exception(“The service account credentials .p12 file does not exist at: ” + serviceAccountCredentialFilePath);
if (string.IsNullOrEmpty(serviceAccountEmail))
throw new Exception(“ServiceAccountEmail is required.”);
// These are the scopes of permissions you need. It is best to request only what you need and not all of them
string[] scopes = new string[] { CalendarService.Scope.Calendar, CalendarService.Scope.CalendarEvents, CalendarService.Scope.CalendarEventsReadonly }; // View your Google Analytics data
// For Json file
if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == “.json”)
{
GoogleCredential credential;
using (var stream = new FileStream(serviceAccountCredentialFilePath, FileMode.Open, FileAccess.Read))
{
credential = GoogleCredential.FromStream(stream)
.CreateScoped(scopes)
.CreateWithUser(“quocdaica158@gmail.com”);
}
// Create the Calendar service.
return new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = “Calendar Authentication Sample”,
});
}
else if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == “.p12”)
{ // If its a P12 file
var certificate = new X509Certificate2(serviceAccountCredentialFilePath, “notasecret”, X509KeyStorageFlags.Exportable);
var credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = scopes,
}.FromCertificate(certificate));
// Create the Calendar service.
return new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = “Calendar Authentication Sample”,
});
}
else
{
throw new Exception(“Unsupported Service accounts credentials.”);
}
}
catch (Exception ex)
{
Console.WriteLine(“Create service account CalendarService failed” + ex.Message);
throw new Exception(“CreateServiceAccountCalendarServiceFailed”, ex);
}
}
public static void CreateEvent(CalendarService _service)
{
Event body = new Event();
EventAttendee a = new EventAttendee();
a.Email = “quocdaica158@gmail.com”;
List attendes = new List();
attendes.Add(a);
body.Attendees = attendes;
EventDateTime start = new EventDateTime();
start.DateTime = DateTime.Now;
EventDateTime end = new EventDateTime();
end.DateTime = DateTime.Now.AddHours(2);
body.Start = start;
body.End = end;
body.Location = “Sigapore”;
body.Summary = “Discussion about new Spidey suit”;
EventsResource.InsertRequest request = new EventsResource.InsertRequest(_service, body, “quocdaica158@gmail.com”);
Event response = request.Execute();
}
}
If you pop your question up on I would be happy to have a look at your code
Hi Linda,
this link in your page give 404 error, how can i Access it?
https://github.com/LindaLawton/Google-Dotnet-Samples/blob/master/Authentication/Diamto.Google.Authentication/Diamto.Google.Authentication/DatabaseDataStore.cs
its probably this [DatabaseDatastore.cs](https://gist.github.com/LindaLawton/a11851d51f13addd70264d01be1928bf)
Pingback: [SOLVED] How do I set return_uri for GoogleWebAuthorizationBroker.AuthorizeAsync? – BugsFixing
Thanks for this tutorial! It helped me (9 years later) to connect my application to Google Calendar and retreive events with just a few lines of code! Great!