C# Desktop application using Google Calendar API .NET v3 -- Howto? - c#

Probably not the only one asking this, but I found nothing that works...It's like a jungle ;)
I have a C# desktop app (5-10 user) that I want to connect to my Google calendar. I want to add, move, delete, update events in the calendar. I downloaded an installed the last .Net api v.3.
From what I read, the difficult part is the authenticate/connecting procedure. I suppose that we need to use OAuth 2.0 authentication ? I want my user to authenticate once, not each time they want to make a action (add, move, delete, update).In some sample I get we have to cut and paste a token from a web page into a Console...not really user friendly. And how to authenticate only 1 times (or just put the token directly in code to not authenticate ?) ?
Now, were I can have a good working sample code in C# to make that ?
Thanks you very much for helping !!

I used something similar to the example here. What I did initially was create a simple web application using the sample logic to setup the initial auth that Google requires. I stepped through and got the Refresh Token from the state. I then saved this in an app setting that I could use later during future GetAuthorization requests. At least for what I was doing this worked well, the user never needed to authorize as long as app stayed connected.
private IAuthorizationState GetAuthorization(WebServerClient client)
{
IAuthorizationState state = new AuthorizationState(new[] { CalendarService.Scopes.Calendar.GetStringValue() });
string refreshToken = LoadRefreshToken();//this where I wrote code to load it from the app settings
if (!string.IsNullOrEmpty(refreshToken))
{
state.RefreshToken = refreshToken;
try
{
if (client.RefreshToken(state))
return state;
}
catch (ProtocolException)
{
return null;
}
}
return null;
}

I have today the same issue and found now the solution
Prepare Api Access https://console.developers.google.com/apis/dashboard
Press button "Enable Apis and services"
Search "Calendar" and choose "Google Calendar API"
Press button "Create Project"
Create Project
Press "Enable"
Press button "Create credentials"
Choose "Where will you be calling the API from?" -> Other UI
Choose "What data will you be accessing?" -> Application data
Create service account
Choose Role Project -> Editor
Choose Key type JSON
Press button "Continue"
Rename the file to "credential.json" and save it in the visual studio project
Change in Visual Studio the Copy to output Directory -> "Copy if newer"
Change share config of your google calendar (Share this Calendar)
Add the email address from the json file "client_email" in the google calendar config "Share with specific people"
Example Code
using Google.Apis.Auth.OAuth2;
using Google.Apis.Calendar.v3;
using Google.Apis.Calendar.v3.Data;
using Google.Apis.Services;
using System.IO;
namespace Test.GoogleCalendar
{
class Program
{
static void Main(string[] args)
{
GoogleCredential credential;
using (var stream = new FileStream("credential.json", FileMode.Open, FileAccess.Read))
{
credential = GoogleCredential.FromStream(stream).CreateScoped(CalendarService.Scope.Calendar);
}
// Create Google Calendar API service.
var service = new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Test Calendar Reader",
});
var calendars = service.CalendarList.List().Execute().Items;
foreach (CalendarListEntry calendar in calendars)
{
var events = service.Events.List(calendar.Id).Execute();
}
}
}
}

Here is a link to help download Calendar Client API library for .NET. The library makes OAuth and accessing the Calendar easier. See link for OAuth details but I'm pretty sure it's what you want - user logs in only once to authorize.
On same page there are sample applications using the Client API in VB.NET and MVC.

Related

UWP - How to Sync files with OneDrive API in C#

I am creating a UWP application and I want to use the Onedrive API so that users can save a copy of their files in their Onedrive account, but I don't get it, so far I have only managed to login what I want is:
upload files
download files
and synchronize if any of them is modified
Create folders
Delete Files
This code achieves the login, but I can not move beyond this, as would proceed for upload files or download them
private async void btn_Login_Click(object sender, RoutedEventArgs e)
{
if (this.oneDriveClient == null)
{
try
{
// Setting up the client here, passing in our Client Id, Return Url,
// Scopes that we want permission to, and building a Web Broker to
// go do our authentication.
this.oneDriveClient = await OneDriveClient.GetAuthenticatedMicrosoftAccountClient(
clientId,
returnUrl,
scopes,
webAuthenticationUi: new WebAuthenticationBrokerWebAuthenticationUi());
// Show in text box that we are connected.
txtBox_Response.Text = "We are now connected";
// We are either just autheticated and connected or we already connected,
// either way we need the drive button now.
btn_GetDriveId.Visibility = Visibility.Visible;
}
catch (OneDriveException exception)
{
// Eating the authentication cancelled exceptions and resetting our client.
if (!exception.IsMatch(OneDriveErrorCode.AuthenticationCancelled.ToString()))
{
if (exception.IsMatch(OneDriveErrorCode.AuthenticationFailure.ToString()))
{
txtBox_Response.Text = "Authentication failed/cancelled, disposing of the client...";
((OneDriveClient)this.oneDriveClient).Dispose();
this.oneDriveClient = null;
}
else
{
// Or we failed due to someother reason, let get that exception printed out.
txtBox_Response.Text = exception.Error.ToString();
}
}
else
{
((OneDriveClient)this.oneDriveClient).Dispose();
this.oneDriveClient = null;
}
}
}
}
I created a sample repository in github:Onedrive Sync Files Sample
I have already tried using Dropbox, Gdrive, but its implementation for UWP seems to be much more complex, so I chose OneDrive. any answer will be very helpful thanks in advance
How to Sync files with OneDrive API in C#
For using OneDrive, we suggest you implement OneDrive feature with OneDrive Service that is part of Windows Community Toolkit .
Getting Started
To use the OneDrive API, you need to have an access token that authenticates your app to a particular set of permissions for a user. In this section, you'll learn how to:
Register your application to get a client ID and a client secret.
Sign your user in to OneDrive with the specified scopes using the token flow or code flow.
Sign the user out (optional).
And this is official code sample that you could refer.

Xamarin Forms - Tracking what links a user is sharing from my app

I am using the method below in order to share uri's from my app.
ShareTextRequest share = new ShareTextRequest
{
Uri = uri,
Title = "Share Link"
};
await Share.RequestAsync(share);
All is working fine on both Android and iOS, however I am running into an issue as I would like to track and log to what applications the users are sharing the link, for security purposes as per company policy.
An example of the log would be something like;
{
'UserId': '999',
'Link': 'http://example.com',
'SharedTo': 'Facebook',
'SharedOn': '29/08/2019 11:00.000'
}
Would it be possible to use a callback method for example, where I can return the name of the application the link was shared to?
I have already tried accessing any returns of the function but it returns void.
My only other option might be to create a custom share functionality without using the native options.

Analytics Reporting API V4 Client Library for .NET

I'm trying to get some data from our google analytics instance and I'd like to use the Analytics Reporting API V4 Client Library for .NET (https://developers.google.com/api-client-library/dotnet/apis/analyticsreporting/v4) so that I can bake some of this data into an administration site we have built. I'm having trouble finding any examples of using this code and the documentation seems to be incredibly sparse. I would like to use a service account to authorize as we only need to view data associated with the analytics account which we control.
If anyone could provide some sample code or point me in the right direction to get some basic report data using the .net api, it would be greatly appreciated
Calling the Google Analytics Reporting API from C# is not particularly difficult, however all of the necessary steps do not seem to be outlined very clearly in the Google Analytics API documentation. I will try to list them all out here. While YMMV, I believe these steps to be correct as of 7/20/2016.
You can start by creating a new C# project. We'll make a console application to test called GoogleAnalyticsApiConsole. Once the project is created, we'll add a reference to the Google Analytics Reporting API V4 Client Library for .NET using the NuGet Package Manager Console (found under the Tools menu in Visual Studio 2015). Fire up the Console and issue the following command at the PM> prompt:
PM> Install-Package Google.Apis.AnalyticsReporting.v4
Installing that package will download the client libraries needed to call the Google Analytics Reporting web services along with a number of other dependencies.
In order to call the web services, you'll need to set up OAuth 2.0 access for your application. The documentation for this setup can be found here, but I will summarize below:
Login to the Google Cloud Platform Console: https://console.cloud.google.com/. Be sure to login with an account that has access to the Google Analytics accounts you are trying to query with the reporting API.
Click the Google Cloud Platform menu and select API Manager.
On the left hand side, click Credentials and then create a new project called Google Analytics API Console. Give it some time to create the new project.
After the project is created, click Credentials again if it is not already selected, and then click the OAuth Consent Screen link in the right panel. Set the Product name shown to users to Google Analytics API Console and then click Save.
Click Credentials again, and then click Create Credentials, and choose OAuth Client ID. Select Other for Application type and then enter Google Analytics API Console as the Name and click Create.
After the credential is created, you will be presented with a client ID and a client secret. You can close the dialog window.
Now, under Credentials you should see an entry under OAuth 2.0 client ids. Click the download icon to the far right of that entry to download the client_secret.json file (this file will have a much longer name). Add that file to your project at the root level once it has been downloaded and rename it to client_secret.json.
Now that the OAuth 2.0 credential has been created, we need to enable it to call the Reporting API. Select Overview and make sure Google APIs is selected in the right panel. Type in Reporting in the search box and select Analytics Reporting API V4 from the list. On the next screen, click Enable. Once this API has been enabled, you should be able to see it under the Enabled APIs list in the right panel.
Now that we've created our project and created our OAuth 2.0 credential, it is time to call the Reporting API V4. The code listed below will use the Google API and the client_secret.json file to create a Google.Apis.Auth.OAuth2.UserCredential to query the Reporting API for all sessions between the given date range for a View. The code is adapted from the Java example here.
Before executing the code, be sure to set the Build Action on the client_secret.json file to Content and the Copy to Output Directory setting to Copy if newer. There are also two variables that need to be properly set. First, in the GetCredential() method, set the loginEmailAddress value to the email address used to create the OAuth 2.0 credential. Then, in the Main method, be sure to set the ViewId in the reportRequest variable to the view that you want to query using the Reporting API. To find the ViewId, log in to Google Analytics and select the Admin tab. From there, select the view you want to query in the View dropdown on the far right and select View Settings. The View ID will be displayed under Basic Settings.
The first time the code is executed, it will bring up a web page asking if you want to allow the Google Analytics API Console to have access to the API data. Select Allow to proceed. From then on that permission will be stored in the GoogleAnalyticsApiConsole FileDataStore. If that file is deleted, then permission will need to be granted again. That file can be found in the %APPDATA%\GoogleAnalyicsApiConsole directory.
Please note that I believe this scenario will meet the needs of the OP. If this application were to be distributed to clients, then a different OAuth 2.0 scheme would most likely be necessary.
Here is the code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Google.Apis.AnalyticsReporting.v4;
using Google.Apis.AnalyticsReporting.v4.Data;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using Google.Apis.Util.Store;
namespace GoogleAnalyticsApiConsole
{
class Program
{
static void Main(string[] args)
{
try
{
var credential = GetCredential().Result;
using(var svc = new AnalyticsReportingService(
new BaseClientService.Initializer
{
HttpClientInitializer = credential,
ApplicationName = "Google Analytics API Console"
}))
{
var dateRange = new DateRange
{
StartDate = "2016-05-01",
EndDate = "2016-05-31"
};
var sessions = new Metric
{
Expression = "ga:sessions",
Alias = "Sessions"
};
var date = new Dimension { Name = "ga:date" };
var reportRequest = new ReportRequest
{
DateRanges = new List<DateRange> { dateRange },
Dimensions = new List<Dimension> { date },
Metrics = new List<Metric> { sessions },
ViewId = "<<your view id>>"
};
var getReportsRequest = new GetReportsRequest {
ReportRequests = new List<ReportRequest> { reportRequest } };
var batchRequest = svc.Reports.BatchGet(getReportsRequest);
var response = batchRequest.Execute();
foreach (var x in response.Reports.First().Data.Rows)
{
Console.WriteLine(string.Join(", ", x.Dimensions) +
" " + string.Join(", ", x.Metrics.First().Values));
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
static async Task<UserCredential> GetCredential()
{
using (var stream = new FileStream("client_secret.json",
FileMode.Open, FileAccess.Read))
{
const string loginEmailAddress = "<<your account email address>>";
return await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
new[] { AnalyticsReportingService.Scope.Analytics },
loginEmailAddress, CancellationToken.None,
new FileDataStore("GoogleAnalyticsApiConsole"));
}
}
}
}
Here are the steps updated for Sep 2019.
First, understand that there are two choices under OAuth: User credentials and Service Account credentials. User credentials are meant to be used when you do not know which Google Analytics account you will be connected to, hence the user grants your application permission. Service Account credentials are meant to be used, e.g. if you build your own dashboard for your company to display Google Analytics data.
Most of the time, if you need programmatic access to Analytics data, it is the second case.
The steps below should get you started for a simple C# example. Note that the Google web console part may vary slightly, but should be easy to find nevertheless.
Go to the Google API Console. Create a Project if prompted.
Go to Service accounts.
Create a new Service Account. You should have an account with a random-generated email address (mine is ending with xxx#xxx.iam.gserviceaccount.com)
Find the Create Key button. Choose JSON and download the file. This is your private key and your only copy. Do not lose it.
Go to your Google Analytics admin panel. Grant access to the Service Account using its email address, the same way you would grant access to other users.
The Google configuration is done. Now jump into Visual Studio.
Create a new C# Console Project.
Get the Nuget package Google.Apis.AnalyticsReporting.v4. It should also automatically download the core packages as well.
Grab the JSON file downloaded earlier, put it in the project, set its Property to Content and Copy Always.
using Google.Apis.AnalyticsReporting.v4.Data;
using System;
namespace ConsoleApplication {
class Program {
static void Main(string[] args) {
var credential = Google.Apis.Auth.OAuth2.GoogleCredential.FromFile("serviceAccount.json")
.CreateScoped(new[] { Google.Apis.AnalyticsReporting.v4.AnalyticsReportingService.Scope.AnalyticsReadonly });
using (var analytics = new Google.Apis.AnalyticsReporting.v4.AnalyticsReportingService(new Google.Apis.Services.BaseClientService.Initializer {
HttpClientInitializer = credential
})) {
var request = analytics.Reports.BatchGet(new GetReportsRequest {
ReportRequests = new[] {
new ReportRequest{
DateRanges = new[] { new DateRange{ StartDate = "2019-01-01", EndDate = "2019-01-31" }},
Dimensions = new[] { new Dimension{ Name = "ga:date" }},
Metrics = new[] { new Metric{ Expression = "ga:sessions", Alias = "Sessions"}},
ViewId = "99999999"
}
}
});
var response = request.Execute();
foreach (var row in response.Reports[0].Data.Rows) {
Console.Write(string.Join(",", row.Dimensions) + ": ");
foreach (var metric in row.Metrics) Console.WriteLine(string.Join(",", metric.Values));
}
}
Console.WriteLine("Done");
Console.ReadKey(true);
}
}
}
I had the same experience: Google's documentation is pretty in-depth but is pretty terrible at giving clear examples of how to connect with .NET.
One key thing I finally realized is that you can either connect using an OAuth2 credential or a service account credential. If you own your Analytics account, use a service account. If you're needing to connect to other users' Analytics accounts, use OAuth2.
There seem to be quite a few examples online of how to get Analytics API data using an OAuth2 credential, but I own my Analytics account and just wanted to pull data from it. I figured out how to connect to the Analytics Reporting API v4 using a ServiceAccountCredential, and I wrote an answer on a similar Stack Overflow question with all the details.
Here Is the code you actually looking for-
protected void Page_Load(object sender, EventArgs e)
{
IRestRequest request = new RestRequest("", Method.POST, DataFormat.Json);
string url = "https://analyticsreporting.googleapis.com/v4/reports:batchGet";
RestClient restClient = new RestClient();
RestRequest Tokenrequest = new RestRequest();
Tokenrequest.AddQueryParameter("client_id", "<CLIENTID>");
Tokenrequest.AddQueryParameter("client_secret", "<CLIENTSECRET>");
Tokenrequest.AddQueryParameter("grant_type", "refresh_token");
Tokenrequest.AddQueryParameter("refresh_token", "<REFRESH_TOKEN>");
restClient.BaseUrl = new System.Uri("https://oauth2.googleapis.com/token");
restClient.Post(Tokenrequest);
var responseToken = restClient.Execute(Tokenrequest);
//Response.Write(responseToken);
dynamic Tokendata = JObject.Parse(responseToken.Content);
var newToken = Tokendata.access_token.Value;
request.AddHeader("authorization", string.Concat("Bearer "+newToken));
string jsonString = "{" +
"\"reportRequests\": [{" +
"\"dateRanges\" : [{\"" +
"startDate\" :'2021-07-01' ," +
"\"endDate\" : '2021-07-07'" +
"}]," +
"\"metrics\":["+
"{\"expression\":'ga:totalEvents'},"+
"{\"expression\": 'ga:pageviews'}"+
"]," +
"\"dimensions\": ["+
"{\"name\": 'ga:eventCategory'}" +
",{" +
"\"name\": 'ga:eventAction'"+
"},"+
//"{\"name\": 'ga:deviceCategory'}"+
"]," +
"\"dimensionFilterClauses\": [{"+
"\"filters\": [{"+
"\"dimensionName\": 'ga:eventCategory',"+
"\"operator\": 'EXACT',"+
"\"expressions\": ["+
"\"Login_Form"+
"\"]}]}],"+
"\"viewId\":'<VIEWID>'" +
"}]" +
"}";
IRestClient client = new RestClient(url);
request.AddHeader("Content-Type", "application/json; CHARSET=UTF-8");
request.Resource = "";
request.AddParameter("application/json", jsonString, ParameterType.RequestBody);
var response = client.Execute(request);
dynamic jdata = JObject.Parse(response.Content);
var Row_data = jdata.reports[0].data.rows;
Response.Write(Row_data);
}
Read The Document To Get access_token through refresh_token.
https://developers.google.com/identity/protocols/oauth2/web-server#offline

Google Web Authorization Broker create secret uri

I want to create the UserCredentials for my program and the signature of this task seems to be
Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.AuthorizeAsync(
(Uri clientSecretsUri, IEnumerable<string> scopes, string user, CancellationToken taskCancellationToken);
All tutorials I found only just create a ClientSecrets-class and pass that as an argument, sadly this class does not have a .ToUri() method. I also can not find any documentation on how this uri has to be constructed. So given that I obviously have my client id and secret ( and redirect uri's if needed ) how do I create the uri needed for this authorization?
I'm assuming your're developing for the universal windows platform? Then this will work:
as neosapien said, you can download the client_secrets.json from the Developer Console.
Add it to your project with a build action of Content.
then load it according to your location in the project (in this case <ProjectDirectory>/Assets/client_secrets.json) like so:
await GoogleWebAuthorizationBroker.AuthorizeAsync(
new Uri("ms-appx:///Assets/client_secrets.json"),
new[] {CalendarService.Scope.Calendar, DriveService.Scope.Drive},
"user",
CancellationToken.None)
Go to the Google Developers Console and download the .json file from the Credentials item under the APIs & Auth menu in the left sidebar.
If you want to include .json file in your deployment you can just encrypt it to keep your secret key and id safe.
The following usings are needed:
using Google.Apis.Services // for BaseClientService
using Google.Apis.Util.Store // for FileDataStore
using System.Threading // for CancellationToken.None
using System.Reflection // for accessing the embedded resource of the json file
Using Google.Apis.Auth.OAuth2
any other google scope specific resources; e.g., Google.Apis.Calendar for the calendar scope or Google.Apis.Gmail for email access.
Create fields and properties as follows:
UserCredentials credentials;
CalendarService calendarService
and this is the code I use for interacting with the Google API:
try
{
GoogleWebAuthorizationBroker.Folder = "Tasks.Auth.Store";
credentials = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load({file name or stream}).Secrets,
new[] {
GmailService.Scope.GmailCompose,
CalendarService.Scope.Calendar,
Google.Apis.Plus.v1.PlusService.Scope.UserinfoEmail },
"user", CancellationToken.None,
new FileDataStore("AppDataFolderName"));
} ...
Since I am installing the encrypted .json file as a part of my software, the entire try/catch block is inside of a using (var cryptoStream = Encryption.ReadJson()) block followed by GoogleClientSecrets.Load(cryptoStream).Secrets but you could just as easily use any file path and name you like.
In the above sample, I am requesting access to read and write gmail, read and write to the Google calendar, and I'd like to know who they are on G+.
Make sure you have enabled the correct APIs in the Google Developers Console.
The real magic doesn't actually happen until you use the credentials to create a service. In the above example, you would use the following code:
calendarService = new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = credentials,
ApplicationName = "My Application"
});
to access the calendar.
I'm pretty sure this is an extremely hacked together way of doing this, but it works for me without any problems. I pieced it together from a lot of the tutorials found here Google Drive | Daimto

Copy a Google Docs Spreadsheet using Google .NET API

I'm wanting to copy an already existing Google Docs Spreadsheet to a new Google Docs spreadsheet. I dont think the v2.0 .NET API can handle it natively (or if so I can't find the class/method), however It looks like the v3.0 protocol can but I'm not sure how to implement this in the current framework or even if it is possible with the current .net api. eg. ~DocumentsFeed.copy() (pseudo code).
Exporting to a temp excel file then uploading with a new name is not possible either as some of the complex formulas get messed up in the conversion process.
I am a bit of a .NET noob so any info would be greatly appreciated eg. How would I go about doing this in .NET if I could only use the v3 protocol (ajax etc) and not the .NET API.
Thanks
EDIT: (final class thanks to #langsamu for his help!)
using System;
using Google.GData.Documents;
using Google.GData.Client;
using Google.GData.Extensions;
public class GoogleDocument
{
private DocumentsService ds;
private String username;
private String password;
public GoogleDocument(String username, String password)
{
this.ds = new DocumentsService("doc service name");
this.username = username;
this.password = password;
this.ds.setUserCredentials(username, password);
this.ds.QueryClientLoginToken();
}
public void copyDocument(String oldFileName, String newFileName)
{
SpreadsheetQuery query = new Google.GData.Documents.SpreadsheetQuery();
query.Title = oldFileName;
query.TitleExact = true;
DocumentsFeed feed = this.ds.Query(query);
AtomEntry entry = feed.Entries[0];
entry.Title.Text = newFileName;
var feedUri = new Uri(DocumentsListQuery.documentsBaseUri);
this.ds.Insert(feedUri, entry);
}
}
Google.GData.Documents.DocumentsService service = new Google.GData.Documents.DocumentsService("YOUR_APPLICATIONS_NAME");
service.setUserCredentials("YOUR_USERNAME", "YOUR_PASSWORD");
Google.GData.Documents.SpreadsheetQuery query = new Google.GData.Documents.SpreadsheetQuery();
query.Title = "YOUR_SPREADSHEETS_TITLE";
query.TitleExact = true;
Google.GData.Documents.DocumentsFeed feed = service.Query(query);
Google.GData.Client.AtomEntry entry = feed.Entries[0];
var feedUri = new Uri(Google.GData.Documents.DocumentsListQuery.documentsBaseUri);
service.Insert(feedUri, entry);
This solution is basically about retrieving an existing spreadsheet (service.Query) using the Document List API and re-inserting it (service.Insert).
Make sure you replace the ALL CAPS application name, username, password and spreadsheet title.
Add a reference to Google.GData.Documents.
This is using .NET 4 (should work with lower versions as well) and Google Documents List Data API v2.0 (DLL says version is 1.6.0.0: google-gdata), which seems to use version 3.0 of the protocol.
It is a bit unclear if you are developing a web application or a desktop application, so I'll try and cover both (essentially they are very much alike - because...).
If you are developing a web application you won't be able to make a 100% AJAX solution. You will only be able to request URL's on the same domain. To do this you will need to either do the communication server side only, or do it server side and proxy it to your web app through AJAX.
If you are developing a desktop application you'll have to do this stuff aswell. Except the AJAX part.
An example app would be fairly easy - 2-3 hours work to whip up considering the documentation given. With just a little knowledge of HTTP and POST request forming you should be able to make it work.

Categories

Resources