Google .NET APIs - any other DataStore other than the FileDataStore? Google .NET APIs - any other DataStore other than the FileDataStore? asp.net asp.net

Google .NET APIs - any other DataStore other than the FileDataStore?


The source for Google's FileDataStore is available here.

I've written a simple Entity Framework (version 6) implementation of IDataStore as shown below.

If you're looking to put this in a separate project, as well as EF you'll need the Google.Apis.Core nuget package installed.

public class Item{    [Key]    [MaxLength(100)]    public string Key { get; set; }    [MaxLength(500)]    public string Value { get; set; }}public class GoogleAuthContext : DbContext{    public DbSet<Item> Items { get; set; }}public class EFDataStore : IDataStore{    public async Task ClearAsync()    {        using (var context = new GoogleAuthContext())        {            var objectContext = ((IObjectContextAdapter)context).ObjectContext;            await objectContext.ExecuteStoreCommandAsync("TRUNCATE TABLE [Items]");        }    }    public async Task DeleteAsync<T>(string key)    {        if (string.IsNullOrEmpty(key))        {            throw new ArgumentException("Key MUST have a value");        }        using (var context = new GoogleAuthContext())        {            var generatedKey = GenerateStoredKey(key, typeof(T));            var item = context.Items.FirstOrDefault(x => x.Key == generatedKey);            if (item != null)            {                context.Items.Remove(item);                await context.SaveChangesAsync();            }        }    }    public Task<T> GetAsync<T>(string key)    {        if (string.IsNullOrEmpty(key))        {            throw new ArgumentException("Key MUST have a value");        }        using (var context = new GoogleAuthContext())        {            var generatedKey = GenerateStoredKey(key, typeof(T));            var item = context.Items.FirstOrDefault(x => x.Key == generatedKey);            T value = item == null ? default(T) : JsonConvert.DeserializeObject<T>(item.Value);            return Task.FromResult<T>(value);        }    }    public async Task StoreAsync<T>(string key, T value)    {        if (string.IsNullOrEmpty(key))        {            throw new ArgumentException("Key MUST have a value");        }        using (var context = new GoogleAuthContext())        {            var generatedKey = GenerateStoredKey(key, typeof (T));            string json = JsonConvert.SerializeObject(value);            var item = await context.Items.SingleOrDefaultAsync(x => x.Key == generatedKey);            if (item == null)            {                context.Items.Add(new Item { Key = generatedKey, Value = json});            }            else            {                item.Value = json;            }            await context.SaveChangesAsync();        }    }    private static string GenerateStoredKey(string key, Type t)    {        return string.Format("{0}-{1}", t.FullName, key);    }}


I know this question was answered some time ago, however I thought this would be a good place to share my findings for those having similar difficulty finding examples. I have found it to be difficult to find documentation/samples on using the Google APIs .Net library for an Desktop or MVC Web application. I finally found a good example in the tasks example you can find in the samples repository on the Google Project site here <- That really really helped me out.

I ended up snagging the source for the FileDataStore and created an AppDataStore class and placed it in my App_Code folder. You can find the source here, though it was a simple change really - changing the folder to point to ~/App_Data instead.

The last piece of the puzzle I'm looking into figuring out is getting the offline_access token.


Edit: Here's the code for convenience:

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.IO;using System.Threading;using System.Threading.Tasks;using Google.Apis.Util.Store;using Google.Apis.Json;namespace Google.Apis.Util.Store {    public class AppDataFileStore : IDataStore {        readonly string folderPath;        /// <summary>Gets the full folder path.</summary>        public string FolderPath { get { return folderPath; } }        /// <summary>        /// Constructs a new file data store with the specified folder. This folder is created (if it doesn't exist        /// yet) under <see cref="Environment.SpecialFolder.ApplicationData"/>.        /// </summary>        /// <param name="folder">Folder name.</param>        public AppDataFileStore(string folder) {            folderPath = Path.Combine(HttpContext.Current.Server.MapPath("~/App_Data/"), folder);            if (!Directory.Exists(folderPath)) {                Directory.CreateDirectory(folderPath);            }        }        /// <summary>        /// Stores the given value for the given key. It creates a new file (named <see cref="GenerateStoredKey"/>) in        /// <see cref="FolderPath"/>.        /// </summary>        /// <typeparam name="T">The type to store in the data store.</typeparam>        /// <param name="key">The key.</param>        /// <param name="value">The value to store in the data store.</param>        public Task StoreAsync<T>(string key, T value) {            if (string.IsNullOrEmpty(key)) {                throw new ArgumentException("Key MUST have a value");            }            var serialized = NewtonsoftJsonSerializer.Instance.Serialize(value);            var filePath = Path.Combine(folderPath, GenerateStoredKey(key, typeof(T)));            File.WriteAllText(filePath, serialized);            return TaskEx.Delay(0);        }        /// <summary>        /// Deletes the given key. It deletes the <see cref="GenerateStoredKey"/> named file in        /// <see cref="FolderPath"/>.        /// </summary>        /// <param name="key">The key to delete from the data store.</param>        public Task DeleteAsync<T>(string key) {            if (string.IsNullOrEmpty(key)) {                throw new ArgumentException("Key MUST have a value");            }            var filePath = Path.Combine(folderPath, GenerateStoredKey(key, typeof(T)));            if (File.Exists(filePath)) {                File.Delete(filePath);            }            return TaskEx.Delay(0);        }        /// <summary>        /// Returns the stored value for the given key or <c>null</c> if the matching file (<see cref="GenerateStoredKey"/>        /// in <see cref="FolderPath"/> doesn't exist.        /// </summary>        /// <typeparam name="T">The type to retrieve.</typeparam>        /// <param name="key">The key to retrieve from the data store.</param>        /// <returns>The stored object.</returns>        public Task<T> GetAsync<T>(string key) {            if (string.IsNullOrEmpty(key)) {                throw new ArgumentException("Key MUST have a value");            }            TaskCompletionSource<T> tcs = new TaskCompletionSource<T>();            var filePath = Path.Combine(folderPath, GenerateStoredKey(key, typeof(T)));            if (File.Exists(filePath)) {                try {                    var obj = File.ReadAllText(filePath);                    tcs.SetResult(NewtonsoftJsonSerializer.Instance.Deserialize<T>(obj));                }                catch (Exception ex) {                    tcs.SetException(ex);                }            }            else {                tcs.SetResult(default(T));            }            return tcs.Task;        }        /// <summary>        /// Clears all values in the data store. This method deletes all files in <see cref="FolderPath"/>.        /// </summary>        public Task ClearAsync() {            if (Directory.Exists(folderPath)) {                Directory.Delete(folderPath, true);                Directory.CreateDirectory(folderPath);            }            return TaskEx.Delay(0);        }        /// <summary>Creates a unique stored key based on the key and the class type.</summary>        /// <param name="key">The object key.</param>        /// <param name="t">The type to store or retrieve.</param>        public static string GenerateStoredKey(string key, Type t) {            return string.Format("{0}-{1}", t.FullName, key);        }    }}

I had to set the approval prompt to force in order to get the offline access token.

var req = HttpContext.Current.Request;var oAuthUrl = Flow.CreateAuthorizationCodeRequest(new UriBuilder(req.Url.Scheme, req.Url.Host, req.Url.Port, GoogleCalendarUtil.CallbackUrl).Uri.ToString()) as GoogleAuthorizationCodeRequestUrl;oAuthUrl.Scope = string.Join(" ", new[] { CalendarService.Scope.CalendarReadonly });oAuthUrl.ApprovalPrompt = "force";oAuthUrl.State = AuthState;


You basicly need to create your own implimitation of Idatastore and then use that.

IDataStore StoredRefreshToken = new myDataStore();// Oauth2 Autentication.using (var stream = new System.IO.FileStream("client_secret.json", System.IO.FileMode.Open, System.IO.FileAccess.Read)){ credential = GoogleWebAuthorizationBroker.AuthorizeAsync( GoogleClientSecrets.Load(stream).Secrets, new[] { AnalyticsService.Scope.AnalyticsReadonly }, "user", CancellationToken.None, StoredRefreshToken).Result;}

Check here for a basic example of an implimitation of Idatastore. Google Oauth loading stored refresh token

Update:

Several versions of this can be found in my Authentication sample project on GitHub Google-Dotnet-Samples / Authentication / Diamto.Google.Authentication

Update 2