API-интерфейсы Google .NET — любое другое хранилище данных, кроме FileDataStore?

Я использую Google .NET API для получения аналитических данных из Google Analytics.

это мой код для запуска аутентификации:

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")
        });

он использует FileDataStore, который хранится в локальном профиле пользователя в виде файла. Я запускаю этот код в приложении ASP.NET, поэтому я не могу использовать этот FileDataStore, поэтому мне понадобится какой-то другой способ получить данные.

Google.Apis.Util.Store содержит только FileDataStore и интерфейс IDataStore. Прежде чем я приступлю к реализации своего собственного DataStore — есть ли какие-либо другие объекты DataStore, доступные для загрузки?

Спасибо


person developer82    schedule 10.12.2013    source источник


Ответы (5)


Исходный код Google FileDataStore доступен здесь.

Я написал простую реализацию IDataStore на Entity Framework (версия 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);
    }
}
person Simon Ness    schedule 26.02.2014
comment
как я могу использовать этот efdatastore? - person Robel Haile; 06.07.2016
comment
Работает на локальном компьютере, но формат строки инициализации не соответствует спецификации, начиная с индекса 0 в Azure. - person Kirill; 31.01.2018
comment
@Kirill Похоже на stackoverflow.com/questions/8243008/ - person Simon Ness; 31.01.2018
comment
Если вы хотите использовать это вместе с сервисом, не основанным на клиенте (выдавать события календаря через несколько часов после того, как клиент покинет ваш сайт), вам нужно повесить токен обновления. Вы получаете токен обновления только с первым токеном. Последующие обновления удалят токен обновления с помощью описанного выше StoreAsync. Вы никогда не заметите этого в веб-приложении, потому что обновление маркера выполняется через сайт перенаправления › accounts.google.com/ signin/oauth › вернуться на сайт. - person bryjohns; 24.02.2018
comment
У меня сработало, но мне пришлось увеличить размер поля Значение - person mrelva; 12.10.2020

Я знаю, что на этот вопрос был дан ответ некоторое время назад, однако я подумал, что это будет хорошее место, чтобы поделиться своими выводами с теми, кто испытывает аналогичные трудности с поиском примеров. Я обнаружил, что сложно найти документацию/образцы по использованию библиотеки .Net API Google для рабочего стола или веб-приложения MVC. Наконец-то я нашел хороший пример в примере с задачами, который вы можете найти в репозитории примеров на сайте Google Project здесь ‹- Это действительно действительно помогло мне.

В итоге я нашел источник для 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);
        }
    }
}

Мне пришлось принудительно настроить приглашение на утверждение, чтобы получить токен автономного доступа.

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;
person Micah    schedule 19.03.2014
comment
Извините за задержку, Крейг, да, на самом деле я выяснил токен offline_access. Пришлось добавить: oAuthUrl.ApprovalPrompt = force; - person Micah; 02.06.2014
comment
Вы могли бы добиться того же с помощью FileDataStore вот так: new FileDataStore(Server.MapPath("~/App_Data"), true) - person jansokoly; 26.02.2015
comment
Обратите внимание, что это не будет работать для веб-сайта Azure, где у вас нет доступа к файловой системе. - person ChiralMichael; 21.09.2016

В основном вам нужно создать собственное ограничение Idatastore, а затем использовать его.

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;
}

Проверьте здесь базовый пример ограничения Idatastore. Google Oauu загружает сохраненный токен обновления

Обновление:

Несколько версий этого можно найти в моем примере проекта аутентификации на GitHub Google-Dotnet-Samples / Authentication / Diamto.Google.Authentication

Обновление 2

person DaImTo    schedule 17.12.2013
comment
Не хотел бы -1 объяснить, почему это старый вопрос, который все еще актуален. - person DaImTo; 04.03.2019
comment
Не я, но, возможно, вы написали слишком много ссылок вместо кода - person Worthy7; 11.04.2019

Здесь доступны реализации для приложений Windows 8 и Windows Phone:

Взгляните на следующий поток При развертывании ASP.NET в облаке Windows Azure приложение выдает ошибку при работе в облаке, прежде чем вы собираетесь внедрить собственное хранилище данных.

В будущем у нас также может быть EF DataStore. Помните, что это проект с открытым исходным кодом, поэтому вы можете внедрить его и отправить на проверку :) Взгляните на нашу страницу вклада (https://code.google.com/p/google-api-dotnet-client/wiki/BecomingACContributor)

person peleyal    schedule 10.12.2013

Наше веб-приложение размещено в Azure, поэтому мне нужно было создать для него IDataStore.

В качестве хранилища данных я использовал Azure Table Storage.

Вот суть моей попытки

Отзывы и предложения приветствуются

person Eilimint    schedule 21.06.2018