Google .NET API - 除FileDataStore之外的任何其他DataStore?

dev*_*r82 24 c# asp.net asp.net-mvc google-api google-api-dotnet-client

我正在使用Google .NET API从谷歌分析中获取分析数据.

这是我开始身份验证的代码:

IAuthorizationCodeFlow flow =
    new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
        {
            ClientSecrets = new ClientSecrets
            {
                ClientId = googleApiClientId,
                ClientSecret = googleApiClientSecret
            },
            Scopes = new[] { 
                Google.Apis.Analytics.v3.AnalyticsService.Scope.AnalyticsReadonly
            },
            DataStore = new Google.Apis.Util.Store.FileDataStore("Test_GoogleApi")
        });
Run Code Online (Sandbox Code Playgroud)

它使用FileDataStore作为文件存储在本地用户配置文件中.我在ASP.NET应用程序中运行此代码,因此我无法真正使用该FileDataStore,因此我需要的是获取数据的其他方法.

Google.Apis.Util.Store仅包含FileDataStore和IDataStore的接口.在我开始实现自己的DataStore之前 - 是否还有其他可供下载的DataStore对象?

谢谢

Sim*_*ess 31

Google的FileDataStore源代码可在此处获取.

我已经编写了一个IDataStore的简单实体框架(版本6)实现,如下所示.

如果您希望将其放在单独的项目中,以及EF,则需要安装Google.Apis.Core nuget软件包.

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 如果您想将它与基于非客户端的服务一起使用(在客户端离开您的站点后数小时发布日历事件),您需要挂在刷新令牌上。您只能使用第一个令牌获得刷新令牌。后续刷新将使用上述 StoreAsync 清除刷新令牌。您永远不会在网络应用程序上注意到它,因为令牌刷新是通过重定向站点 &gt; https://accounts.google.com/signin/oauth &gt; 返回站点来处理的。 (2认同)

Mic*_*cah 5

我知道这个问题已经回答了一段时间,但我认为这是一个分享我的发现的好地方,因为那些在查找示例时遇到类似困难的人.我发现使用桌面或MVC Web应用程序的Google API .Net库很难找到文档/示例.我终于发现在任务比如你可以在谷歌的项目工地样本库找到一个很好的例子,在这里 < -那真的真的帮了我.

我最终窃取了FileDataStore的源代码并创建了一个AppDataStore类并将其放在我的App_Code文件夹中.你可以在这里找到源码,虽然它确实是一个简单的改变 - 改变文件夹指向〜/ App_Data.

我正在研究的最后一块拼图是获取offline_access令牌.


编辑:这是为方便起见的代码:

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我必须设置强制批准提示才能获得脱机访问令牌.

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;
Run Code Online (Sandbox Code Playgroud)

  • 您可以使用这样的`FileDataStore`实现相同的目的:`new FileDataStore(Server.MapPath("〜/ App_Data"),true)` (4认同)
  • 请注意,这对于没有文件系统访问权限的Azure网站不起作用. (2认同)

pel*_*yal 1

此处提供了针对 Windows 8 应用程序和 Windows Phone 的实现:

在您要实现自己的数据存储之前,请查看以下主题“将 ASP.NET 部署到 Windows Azure 云,应用程序在云上运行时出现错误” 。

将来我们可能还会有一个 EF DataStore。请记住,这是一个开源项目,因此您可以实现它并将其发送以供审核:) 请查看我们的贡献页面 ( https://code.google.com/p/google-api-dotnet-client/wiki/BecomingAContributor