我正在使用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对象?
由于
答案 0 :(得分:31)
Google FileDataStore的来源可用here。
我已经编写了一个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);
}
}
答案 1 :(得分:5)
我知道这个问题已经回答了一段时间,但我认为这是一个分享我的发现的好地方,因为那些寻找例子有类似困难的人。我发现使用桌面或MVC Web应用程序的Google API .Net库很难找到文档/示例。我终于在您可以在Google项目网站here上的示例存储库中找到的任务示例中找到了一个很好的示例&lt; - 真的真的帮助了我。
我最终抓住FileDataStore的源代码并创建了一个AppDataStore类并将其放在我的App_Code文件夹中。您可以找到源here,虽然这实际上是一个简单的更改 - 将文件夹更改为指向〜/ 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;
答案 2 :(得分:1)
这里有Windows 8应用程序和Windows Phone的实现:
在您要实现自己的DataStore之前,请查看以下线程Deploying ASP.NET to Windows Azure cloud, application gives error when running on cloud。
将来我们可能还有一个EF DataStore。请记住,它是一个开源项目,因此您可以实现它并将其发送给审查:)请查看我们的贡献页面(https://code.google.com/p/google-api-dotnet-client/wiki/BecomingAContributor)
答案 3 :(得分:1)
您基本上需要创建自己对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 Oauth loading stored refresh token
<强>更新强>
可在GitHub Google-Dotnet-Samples / Authentication / Diamto.Google.Authentication
上的身份验证示例项目中找到此版本的多个版本更新2
答案 4 :(得分:0)