! Solution added by me below ! Issue: I am building a windows form using c# / .NET and I want to add a functionality to add a event in my personal google calendar. I've been researching over the internet for a few days already but every solution I find seems overcomlicated.
All I need is:
event title = textbox1.text;
event description = textbox2.text;
event date = datetimepicker.text;
addEvent();
But I don't know how to write it and I couldn't find any solution that is simple as that (most solutions were overcomplicated). I can tell I have some hobby experience coding, enough to build a simple project, but I confess that this is above my level and I need some guidance.
I think I've already set Calendar API and Google SDK. Also installed Google Calendars NuGet package in Visual Studio, but I will appreciate if there is way to make a connection by password and username instead of API & SDK.
Thanks in advance!
! Solution !
With the initial help of @Dalmto, I managed to link his code to a button and actually make it fire a event, because previosuly it didn't.
Here is my final code you can use it simply as copy paste. Just add your credentials.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Calendar.v3;
using Google.Apis.Services;
using Google.Apis.Util.Store;
using System.IO;
using System.Threading;
using Google.Apis.Calendar.v3.Data;
namespace googleCalendarTesting
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string clientSecretJson = ""; //add your json path here
string userName = ""; // add your google account here
string[] scopes = new string[n] {"n1", "n2", "n3" }; // replace n with the number of scopes you need and write them one by one
CalendarService service = GetCalendarService(clientSecretJson, userName, scopes);
Event newEvent = new Event()
{
Summary = "event title",
Description = "event description",
Start = new EventDateTime()
{
DateTime = DateTime.Parse("2022-02-28T09:00:00-07:00"),
TimeZone = "America/Los_Angeles",
},
End = new EventDateTime()
{
DateTime = DateTime.Parse("2022-02-28T09:00:00-08:00"),
TimeZone = "America/Los_Angeles",
},
}; //// more options here https://developers.google.com/calendar/api/v3/reference/events/insert#.net
String calendarId = "primary"; // choose a calendar in your google account - you might have multiple calendars
EventsResource.InsertRequest request = service.Events.Insert(newEvent, calendarId);
Event createdEvent = request.Execute();
}
public static CalendarService GetCalendarService(string clientSecretJson, string userName, string[] scopes)
{
try
{
if (string.IsNullOrEmpty(userName))
throw new ArgumentNullException("userName");
if (string.IsNullOrEmpty(clientSecretJson))
throw new ArgumentNullException("clientSecretJson");
if (!File.Exists(clientSecretJson))
throw new Exception("clientSecretJson file does not exist.");
var cred = GetUserCredential(clientSecretJson, userName, scopes);
return GetService(cred);
}
catch (Exception ex)
{
throw new Exception("Get Calendar service failed.", ex);
}
}
private static UserCredential GetUserCredential(string clientSecretJson, string userName, string[] scopes)
{
try
{
if (string.IsNullOrEmpty(userName))
throw new ArgumentNullException("userName");
if (string.IsNullOrEmpty(clientSecretJson))
throw new ArgumentNullException("clientSecretJson");
if (!File.Exists(clientSecretJson))
throw new Exception("clientSecretJson file does not exist.");
// These are the scopes of permissions you need. It is best to request only what you need and not all of them
using (var stream = new FileStream(clientSecretJson, FileMode.Open, FileAccess.Read))
{
string credPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
credPath = Path.Combine(credPath, ".credentials/", System.Reflection.Assembly.GetExecutingAssembly().GetName().Name);
// Requesting Authentication or loading previously stored authentication for userName
var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets,
scopes,
userName,
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
credential.GetAccessTokenForRequestAsync();
return credential;
}
}
catch (Exception ex)
{
throw new Exception("Get user credentials failed.", ex);
}
}
private static CalendarService GetService(UserCredential credential)
{
try
{
if (credential == null)
throw new ArgumentNullException("credential");
// Create Calendar API service.
return new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Calendar Oauth2 Authentication Sample"
});
}
catch (Exception ex)
{
throw new Exception("Get Calendar service failed.", ex);
}
}
}
}
scopes I used in my project:
https://www.googleapis.com/auth/calendar,
https://www.googleapis.com/auth/calendar.events,
https://www.googleapis.com/auth/calendar.events.readonly
CodePudding user response:
I will appreciate if there is way to make a connection by password and username instead of API & SDK.
No, This is called client login and google shut that option down in 2015.
I want to add a functionality to add a event in my personal google calendar.
I am going to assume by personal google calendar that you mean a standard gmail account google calendar.
In order to do this you will need to use Oauth2 request offline access authorize your application once. After that you should have a refresh token stored.
The code for this is resonably strait forward
using Google.Apis.Auth.OAuth2;
using Google.Apis.Calendar.v3;
using Google.Apis.Services;
using Google.Apis.Util.Store;
using System;
using System.IO;
using System.Threading;
namespace GoogleSamplecSharpSample.Calendarv3.Auth
{
public static class Oauth2Example
{
/// <summary>
/// ** Installed Aplication only **
/// This method requests Authentcation from a user using Oauth2.
/// </summary>
/// <param name="clientSecretJson">Path to the client secret json file from Google Developers console.</param>
/// <param name="userName">Identifying string for the user who is being authentcated.</param>
/// <param name="scopes">Array of Google scopes</param>
/// <returns>CalendarService used to make requests against the Calendar API</returns>
public static CalendarService GetCalendarService(string clientSecretJson, string userName, string[] scopes)
{
try
{
if (string.IsNullOrEmpty(userName))
throw new ArgumentNullException("userName");
if (string.IsNullOrEmpty(clientSecretJson))
throw new ArgumentNullException("clientSecretJson");
if (!File.Exists(clientSecretJson))
throw new Exception("clientSecretJson file does not exist.");
var cred = GetUserCredential(clientSecretJson, userName, scopes);
return GetService(cred);
}
catch (Exception ex)
{
throw new Exception("Get Calendar service failed.", ex);
}
}
/// <summary>
/// ** Installed Aplication only **
/// This method requests Authentcation from a user using Oauth2.
/// Credentials are stored in System.Environment.SpecialFolder.Personal
/// Documentation https://developers.google.com/accounts/docs/OAuth2
/// </summary>
/// <param name="clientSecretJson">Path to the client secret json file from Google Developers console.</param>
/// <param name="userName">Identifying string for the user who is being authentcated.</param>
/// <param name="scopes">Array of Google scopes</param>
/// <returns>authencated UserCredential</returns>
private static UserCredential GetUserCredential(string clientSecretJson, string userName, string[] scopes)
{
try
{
if (string.IsNullOrEmpty(userName))
throw new ArgumentNullException("userName");
if (string.IsNullOrEmpty(clientSecretJson))
throw new ArgumentNullException("clientSecretJson");
if (!File.Exists(clientSecretJson))
throw new Exception("clientSecretJson file does not exist.");
// These are the scopes of permissions you need. It is best to request only what you need and not all of them
using (var stream = new FileStream(clientSecretJson, FileMode.Open, FileAccess.Read))
{
string credPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
credPath = Path.Combine(credPath, ".credentials/", System.Reflection.Assembly.GetExecutingAssembly().GetName().Name);
// Requesting Authentication or loading previously stored authentication for userName
var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets,
scopes,
userName,
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
credential.GetAccessTokenForRequestAsync();
return credential;
}
}
catch (Exception ex)
{
throw new Exception("Get user credentials failed.", ex);
}
}
/// <summary>
/// This method get a valid service
/// </summary>
/// <param name="credential">Authecated user credentail</param>
/// <returns>CalendarService used to make requests against the Calendar API</returns>
private static CalendarService GetService(UserCredential credential)
{
try
{
if (credential == null)
throw new ArgumentNullException("credential");
// Create Calendar API service.
return new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Calendar Oauth2 Authentication Sample"
});
}
catch (Exception ex)
{
throw new Exception("Get Calendar service failed.", ex);
}
}
}
}
This code will store the credentials to your personal google calendar account in a file in credPath directory on your machine. You may need to change this directory if you are storing it up on a server.
When you run it the first time (i recommend doing this locally) it will populate that file with a refresh token. The code will then use the refresh token to request a new access token when ever it needs it.
A few notes on this. You will need to set your project to production in google cloud console or your refresh token will only be valid for seven days. You also must be sure that this refresh token is used once every six months or it will expire. If it fails to load the refresh token this code will fail as it is designed for installed applications. This is probably a good thing as you do not a web hosted application to be requesting the users consent to their personal google calendar accounts.
service account note.
Most google apis support something called service account authentication. it is used to pre authorize account access. Google calendar only supports service account authorization for Google workspace accounts not for standard gmail accounts.
If you want to do this with a service account it would be easer but again you would need to register a workspace account and then you could only use it with that not with standard gmail accounts.
CodePudding user response:
You need an API Key from the Google Developer Dashboard (https://console.developers.google.com/apis/dashboard?pli=1) in order to connect to your Calendar and reading or writing events to your calendar. Plain username and password will not work (as far as I know). The documentation of Google is pretty straight forward and explains every step in order to retrieve events from the API. https://developers.google.com/calendar/api/quickstart/dotnet
After understanding the SDK you can enhance your application to add events to your calendar. If I have got the time, I will link one of my GitHub Repos with an example that you can refer.