我整天都在寻找一个好的解决方案,但 google 发展如此之快,以至于我无法找到有效的解决方案。我想要做的是,我有一个 Web 应用程序,它有一个管理部分,用户需要登录才能查看信息。在本节中,我想展示一些来自 GA 的数据,例如某些特定 url 的综合浏览量。因为它不是我显示的用户信息,而是谷歌分析用户,我想连接传递信息(用户名/密码或 APIKey),但我不知道如何。我发现的所有示例都使用 OAuth2(如果我理解,女巫会要求访问者使用 google 登录)。
到目前为止我发现了什么:
也许我只是累了,明天很容易找到解决办法,但现在我需要帮助!
谢谢
它需要在 google 端进行一些设置,但实际上非常简单。我会一步一步列出来。
首先,您需要在 Google 云控制台中创建一个应用程序并启用 Analytics API。
现在已启用 Analytics API,下一步将是启用服务帐户以访问您所需的分析配置文件/站点。服务帐户将允许您登录,而无需提示用户输入凭据。
现在我们有一个服务帐户,您需要允许该服务帐户访问您在 Google Analytics(分析)中的个人资料/网站。
现在已经完成了服务帐户通过 API 访问 Google Analytics 的设置,我们可以开始编写代码了。
从 NuGet 获取这个包:
Google.Apis.Analytics.v3 客户端库
添加这些用法:
2 3 4 5 6 7 | using Google.Apis.Analytics.v3.Data; using Google.Apis.Services; using System.Security.Cryptography.X509Certificates; using Google.Apis.Auth.OAuth2; using System.Collections.Generic; using System.Linq; |
需要注意的是。
那么做一些基本调用的代码如下。
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | { public AnalyticsService Service { get; set; } public GoogleAnalyticsAPI(string keyPath, string accountEmailAddress) { var certificate = new X509Certificate2(keyPath,"notasecret", X509KeyStorageFlags.Exportable); var credentials = new ServiceAccountCredential( new ServiceAccountCredential.Initializer(accountEmailAddress) { Scopes = new[] { AnalyticsService.Scope.AnalyticsReadonly } }.FromCertificate(certificate)); Service = new AnalyticsService(new BaseClientService.Initializer() { HttpClientInitializer = credentials, ApplicationName ="WorthlessVariable" }); } public AnalyticDataPoint GetAnalyticsData(string profileId, string[] dimensions, string[] metrics, DateTime startDate, DateTime endDate) { AnalyticDataPoint data = new AnalyticDataPoint(); if (!profileId.Contains("ga:")) profileId = string.Format("ga:{0}", profileId); //Make initial call to service. //Then check if a next link exists in the response, //if so parse and call again using start index param. GaData response = null; do { int startIndex = 1; if (response != null && !string.IsNullOrEmpty(response.NextLink)) { Uri uri = new Uri(response.NextLink); var paramerters = uri.Query.Split('&'); string s = paramerters.First(i => i.Contains("start-index")).Split('=')[1]; startIndex = int.Parse(s); } var request = BuildAnalyticRequest(profileId, dimensions, metrics, startDate, endDate, startIndex); response = request.Execute(); data.ColumnHeaders = response.ColumnHeaders; data.Rows.AddRange(response.Rows); } while (!string.IsNullOrEmpty(response.NextLink)); return data; } private DataResource.GaResource.GetRequest BuildAnalyticRequest(string profileId, string[] dimensions, string[] metrics, DateTime startDate, DateTime endDate, int startIndex) { DataResource.GaResource.GetRequest request = Service.Data.Ga.Get(profileId, startDate.ToString("yyyy-MM-dd"), endDate.ToString("yyyy-MM-dd"), string.Join(",", metrics)); request.Dimensions = string.Join(",", dimensions); request.StartIndex = startIndex; return request; } public IList<Profile> GetAvailableProfiles() { var response = Service.Management.Profiles.List("~all","~all").Execute(); return response.Items; } public class AnalyticDataPoint { public AnalyticDataPoint() { Rows = new List<IList<string>>(); } public IList<GaData.ColumnHeadersData> ColumnHeaders { get; set; } public List<IList<string>> Rows { get; set; } } } |
其他有用的链接:
Analytic API Explorer - 从 Web 查询 API
Analytic API Explorer 版本 2 - 从 Web 查询 API
维度和指标参考
希望这对将来尝试这样做的人有所帮助。
我做了很多搜索,最后要么从多个地方查找代码,然后围绕它package我自己的界面,我想出了以下解决方案。不确定人们是否将整个代码粘贴在这里,但我想为什么不节省其他人的时间:)
先决条件,您需要安装 Google.GData.Client 和 google.gdata.analytics 包/dll。
这是完成这项工作的主要类。
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | { public class Analytics { private readonly String ClientUserName; private readonly String ClientPassword; private readonly String TableID; private AnalyticsService analyticsService; public Analytics(string user, string password, string table) { this.ClientUserName = user; this.ClientPassword = password; this.TableID = table; // Configure GA API. analyticsService = new AnalyticsService("gaExportAPI_acctSample_v2.0"); // Client Login Authorization. analyticsService.setUserCredentials(ClientUserName, ClientPassword); } /// <summary> /// Get the page views for a particular page path /// </summary> /// <param name="pagePath"></param> /// <param name="startDate"></param> /// <param name="endDate"></param> /// <param name="isPathAbsolute">make this false if the pagePath is a regular expression</param> /// <returns></returns> public int GetPageViewsForPagePath(string pagePath, DateTime startDate, DateTime endDate, bool isPathAbsolute = true) { int output = 0; // GA Data Feed query uri. String baseUrl ="https://www.google.com/analytics/feeds/data"; DataQuery query = new DataQuery(baseUrl); query.Ids = TableID; //query.Dimensions ="ga:source,ga:medium"; query.Metrics ="ga:pageviews"; //query.Segment ="gaid::-11"; var filterPrefix = isPathAbsolute ?"ga:pagepath==" :"ga:pagepath=~"; query.Filters = filterPrefix + pagePath; //query.Sort ="-ga:visits"; //query.NumberToRetrieve = 5; query.GAStartDate = startDate.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture); query.GAEndDate = endDate.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture); Uri url = query.Uri; DataFeed feed = analyticsService.Query(query); output = Int32.Parse(feed.Aggregates.Metrics[0].Value); return output; } public Dictionary<string, int> PageViewCounts(string pagePathRegEx, DateTime startDate, DateTime endDate) { // GA Data Feed query uri. String baseUrl ="https://www.google.com/analytics/feeds/data"; DataQuery query = new DataQuery(baseUrl); query.Ids = TableID; query.Dimensions ="ga:pagePath"; query.Metrics ="ga:pageviews"; //query.Segment ="gaid::-11"; var filterPrefix ="ga:pagepath=~"; query.Filters = filterPrefix + pagePathRegEx; //query.Sort ="-ga:visits"; //query.NumberToRetrieve = 5; query.GAStartDate = startDate.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture); query.GAEndDate = endDate.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture); Uri url = query.Uri; DataFeed feed = analyticsService.Query(query); var returnDictionary = new Dictionary<string, int>(); foreach (var entry in feed.Entries) returnDictionary.Add(((DataEntry)entry).Dimensions[0].Value, Int32.Parse(((DataEntry)entry).Metrics[0].Value)); return returnDictionary; } } } |
这是我用来package它的接口和实现。
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | { public interface IPageViewCounter { int GetPageViewCount(string relativeUrl, DateTime startDate, DateTime endDate, bool isPathAbsolute = true); Dictionary<string, int> PageViewCounts(string pagePathRegEx, DateTime startDate, DateTime endDate); } public class GooglePageViewCounter : IPageViewCounter { private string GoogleUserName { get { return ConfigurationManager.AppSettings["googleUserName"]; } } private string GooglePassword { get { return ConfigurationManager.AppSettings["googlePassword"]; } } private string GoogleAnalyticsTableName { get { return ConfigurationManager.AppSettings["googleAnalyticsTableName"]; } } private Analytics analytics; public GooglePageViewCounter() { analytics = new Analytics(GoogleUserName, GooglePassword, GoogleAnalyticsTableName); } #region IPageViewCounter Members public int GetPageViewCount(string relativeUrl, DateTime startDate, DateTime endDate, bool isPathAbsolute = true) { int output = 0; try { output = analytics.GetPageViewsForPagePath(relativeUrl, startDate, endDate, isPathAbsolute); } catch (Exception ex) { Logger.Error(ex); } return output; } public Dictionary<string, int> PageViewCounts(string pagePathRegEx, DateTime startDate, DateTime endDate) { var input = analytics.PageViewCounts(pagePathRegEx, startDate, endDate); var output = new Dictionary<string, int>(); foreach (var item in input) { if (item.Key.Contains('&')) { string[] key = item.Key.Split(new char[] { '?', '&' }); string newKey = key[0] +"?" + key.FirstOrDefault(k => k.StartsWith("p=")); if (output.ContainsKey(newKey)) output[newKey] += item.Value; else output[newKey] = item.Value; } else output.Add(item.Key, item.Value); } return output; } #endregion } } |
现在剩下的就是显而易见的事情了——你必须将 web.config 值添加到你的应用程序配置或 webconfig 并调用 IPageViewCounter.GetPageViewCount
此答案适用于希望访问自己的 Google Analytics(分析)帐户并希望使用新的 Analytics Reporting API v4 的人。
我最近写了一篇关于如何使用 C# 获取 Google Analytics 数据的博客文章。阅读那里了解所有详细信息。
您首先需要在连接 OAuth2 或服务帐户之间进行选择。我假设您拥有 Analytics 帐户,因此您需要从 Google API 凭据页面创建一个"服务帐户密钥"。
创建后,下载 JSON 文件并将其放入您的项目中(我将我的放在我的
接下来,安装 Google.Apis.AnalyticsReporting.v4 Nuget 包。同时安装 Newtonsoft 的 Json.NET。
在你的项目中包含这个类:
2 3 4 5 6 7 8 9 10 11 12 13 | { public string type { get; set; } public string project_id { get; set; } public string private_key_id { get; set; } public string private_key { get; set; } public string client_email { get; set; } public string client_id { get; set; } public string auth_uri { get; set; } public string token_uri { get; set; } public string auth_provider_x509_cert_url { get; set; } public string client_x509_cert_url { get; set; } } |
这就是你一直在等待的:一个完整??的例子!
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | string json = System.IO.File.ReadAllText(keyFilePath); var cr = JsonConvert.DeserializeObject(json); var xCred = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(cr.client_email) { Scopes = new[] { AnalyticsReportingService.Scope.Analytics } }.FromPrivateKey(cr.private_key)); using (var svc = new AnalyticsReportingService( new BaseClientService.Initializer { HttpClientInitializer = xCred, ApplicationName ="[Your Application Name]" }) ) { // Create the DateRange object. DateRange dateRange = new DateRange() { StartDate ="2017-05-01", EndDate ="2017-05-31" }; // Create the Metrics object. Metric sessions = new Metric { Expression ="ga:sessions", Alias ="Sessions" }; //Create the Dimensions object. Dimension browser = new Dimension { Name ="ga:browser" }; // Create the ReportRequest object. ReportRequest reportRequest = new ReportRequest { ViewId ="[A ViewId in your account]", DateRanges = new List() { dateRange }, Dimensions = new List() { browser }, Metrics = new List() { sessions } }; List requests = new List(); requests.Add(reportRequest); // Create the GetReportsRequest object. GetReportsRequest getReport = new GetReportsRequest() { ReportRequests = requests }; // Call the batchGet method. GetReportsResponse response = svc.Reports.BatchGet(getReport).Execute(); } |
我们首先反序列化 JSON 文件中的服务帐户密钥信息,并将其转换为
最好在声明
我希望只是为 v3 Beta 的答案添加评论,但代表点阻止了这一点。但是,我认为其他人有这些信息会很好,所以这里是:
2 3 4 | using Google.Apis.Authentication.OAuth2.DotNetOpenAuth; using System.Security.Cryptography.X509Certificates; using Google.Apis.Services; |
这些名称空间在该帖子的整个代码中使用。我一直希望人们能更频繁地发布名称空间,我似乎花了很多时间寻找它们。我希望这可以为一些人节省几分钟的工作时间。
我在 nuGet 包中设置了与上述答案非常相似的东西。它执行以下操作:
- 连接到您在 API 控制台中设置的"服务帐户"
- 提取您想要的任何 Google Analytics(分析)数据
- 使用 Google 的 Charts API 显示该数据
它以一种非常容易修改的方式完成所有这些工作。您可以在此处查看更多信息:https://www.nuget.org/packages/GoogleAnalytics.GoogleCharts.NET/。
希望谷歌有一天会提供适当的文档。在这里,我列出了在 ASP.NET C# 中集成谷歌分析服务器端身份验证的所有步骤。
步骤 1:在 google 控制台中创建一个项目
转到链接 https://console.developers.google.com/iam-admin/projects 并通过单击"创建项目"按钮创建项目并在弹出窗口中提供项目名称并提交。
第 2 步:创建凭据和服务帐户
创建项目后,您将被重定向到"API Manager"页面。
单击凭据并按"创建凭据"按钮。从下拉列表中选择"服务帐户密钥",您将被重定向到下一页。
在服务帐户下拉列表中,选择"新服务帐户"。填写服务帐号名称并下载 p12 密钥。它将具有 p12 扩展名。您将看到一个弹出窗口,其中包含默认密码"notasecret",您的私钥将被下载。
第 3 步:创建 0auth 客户端 ID
单击"创建凭据"下拉菜单并选择"0auth 客户端 ID",您将被重定向到"0auth 同意屏幕"选项卡。在项目名称文本框中提供一个随机名称。选择应用程序类型为"Web 应用程序",然后单击创建按钮。在记事本中复制生成的客户端 ID。
第 4 步:启用 API
在左侧单击"概述"选项卡,然后从水平选项卡中选择"启用的 API"。在搜索栏中搜索"Analytics API",单击下拉菜单并按"启用"按钮。现在再次搜索"Analytics Reporting V4"并启用它。
第 5 步:安装 nuget 包
在 Visual Studio 中,转到工具 > Nuget 包管理器 > 包管理器控制台。
将以下代码复制粘贴到控制台中以安装 nuget 包。
安装包 Google.Apis.Analytics.v3
安装包 DotNetOpenAuth.Core -版本 4.3.4.13329
以上两个包是谷歌分析和DotNetOpenAuth nuget包。
第 6 步:向服务帐户
提供"查看和分析"权限
转到谷歌分析帐户并单击"管理"选项卡并从左侧菜单中选择"用户管理",选择您要访问分析数据的域并在其下插入服务帐户电子邮件 ID,然后从下拉列表中选择"读取和分析"权限。服务帐户电子邮件 ID 类似于 ex:googleanalytics@googleanalytics.iam.gserviceaccount.com。
工作代码
前端代码:
将以下分析嵌入脚本复制并粘贴到您的前端,否则您也可以从谷歌分析文档页面获取此代码。
2 3 4 5 6 | g = w.gapi || (w.gapi = {}); g.analytics = { q: [], ready: function (f) { this.q.push(f); } }; js = d.createElement(s); fs = d.getElementsByTagName(s)[0]; js.src = 'https://apis.google.com/js/platform.js'; fs.parentNode.insertBefore(js, fs); js.onload = function () { g.load('analytics'); }; }(window, document, 'script')); |
将以下代码粘贴到前端页面的正文标记中。
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | gapi.analytics.ready(function () { /** * Authorize the user with an access token obtained server side. */ gapi.analytics.auth.authorize({ 'serverAuth': { 'access_token': access_token } }); /** * Creates a new DataChart instance showing sessions. * It will be rendered inside an element with the id"chart-1-container". */ var dataChart1 = new gapi.analytics.googleCharts.DataChart({ query: { 'ids': 'ga:53861036', // VIEW ID <-- Goto your google analytics account and select the domain whose analytics data you want to display on your webpage. From the URL ex: a507598w53044903p53861036. Copy the digits after"p". It is your view ID 'start-date': '2016-04-01', 'end-date': '2016-04-30', 'metrics': 'ga:sessions', 'dimensions': 'ga:date' }, chart: { 'container': 'chart-1-container', 'type': 'LINE', 'options': { 'width': '100%' } } }); dataChart1.execute(); /** * Creates a new DataChart instance showing top 5 most popular demos/tools * amongst returning users only. * It will be rendered inside an element with the id"chart-3-container". */ }); |
您还可以从 https://ga-dev-tools.appspot.com/account-explorer/
获取您的视图 ID
后端代码:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | using System.Linq; using System.Collections.Generic; using System.Collections.Specialized; using System.Web.Script.Serialization; using System.Net; using System.Text; using Google.Apis.Analytics.v3; using Google.Apis.Analytics.v3.Data; using Google.Apis.Services; using System.Security.Cryptography.X509Certificates; using Google.Apis.Auth.OAuth2; using Google.Apis.Util; using DotNetOpenAuth.OAuth2; using System.Security.Cryptography; namespace googleAnalytics { public partial class api : System.Web.UI.Page { public const string SCOPE_ANALYTICS_READONLY ="https://www.googleapis.com/auth/analytics.readonly"; string ServiceAccountUser ="googleanalytics@googleanalytics.iam.gserviceaccount.com"; //service account email ID string keyFile = @"D:\\key.p12"; //file link to downloaded key with p12 extension protected void Page_Load(object sender, EventArgs e) { string Token = Convert.ToString(GetAccessToken(ServiceAccountUser, keyFile, SCOPE_ANALYTICS_READONLY)); accessToken.Value = Token; var certificate = new X509Certificate2(keyFile,"notasecret", X509KeyStorageFlags.Exportable); var credentials = new ServiceAccountCredential( new ServiceAccountCredential.Initializer(ServiceAccountUser) { Scopes = new[] { AnalyticsService.Scope.AnalyticsReadonly } }.FromCertificate(certificate)); var service = new AnalyticsService(new BaseClientService.Initializer() { HttpClientInitializer = credentials, ApplicationName ="Google Analytics API" }); string profileId ="ga:53861036"; string startDate ="2016-04-01"; string endDate ="2016-04-30"; string metrics ="ga:sessions,ga:users,ga:pageviews,ga:bounceRate,ga:visits"; DataResource.GaResource.GetRequest request = service.Data.Ga.Get(profileId, startDate, endDate, metrics); GaData data = request.Execute(); List<string> ColumnName = new List<string>(); foreach (var h in data.ColumnHeaders) { ColumnName.Add(h.Name); } List<double> values = new List<double>(); foreach (var row in data.Rows) { foreach (var item in row) { values.Add(Convert.ToDouble(item)); } } values[3] = Math.Truncate(100 * values[3]) / 100; txtSession.Text = values[0].ToString(); txtUsers.Text = values[1].ToString(); txtPageViews.Text = values[2].ToString(); txtBounceRate.Text = values[3].ToString(); txtVisits.Text = values[4].ToString(); } public static dynamic GetAccessToken(string clientIdEMail, string keyFilePath, string scope) { // certificate var certificate = new X509Certificate2(keyFilePath,"notasecret"); // header var header = new { typ ="JWT", alg ="RS256" }; // claimset var times = GetExpiryAndIssueDate(); var claimset = new { iss = clientIdEMail, scope = scope, aud ="https://accounts.google.com/o/oauth2/token", iat = times[0], exp = times[1], }; JavaScriptSerializer ser = new JavaScriptSerializer(); // encoded header var headerSerialized = ser.Serialize(header); var headerBytes = Encoding.UTF8.GetBytes(headerSerialized); var headerEncoded = Convert.ToBase64String(headerBytes); // encoded claimset var claimsetSerialized = ser.Serialize(claimset); var claimsetBytes = Encoding.UTF8.GetBytes(claimsetSerialized); var claimsetEncoded = Convert.ToBase64String(claimsetBytes); // input var input = headerEncoded +"." + claimsetEncoded; var inputBytes = Encoding.UTF8.GetBytes(input); // signature var rsa = certificate.PrivateKey as RSACryptoServiceProvider; var cspParam = new CspParameters { KeyContainerName = rsa.CspKeyContainerInfo.KeyContainerName, KeyNumber = rsa.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2 }; var aescsp = new RSACryptoServiceProvider(cspParam) { PersistKeyInCsp = false }; var signatureBytes = aescsp.SignData(inputBytes,"SHA256"); var signatureEncoded = Convert.ToBase64String(signatureBytes); // jwt var jwt = headerEncoded +"." + claimsetEncoded +"." + signatureEncoded; var client = new WebClient(); client.Encoding = Encoding.UTF8; var uri ="https://accounts.google.com/o/oauth2/token"; var content = new NameValueCollection(); content["assertion"] = jwt; content["grant_type"] ="urn:ietf:params:oauth:grant-type:jwt-bearer"; string response = Encoding.UTF8.GetString(client.UploadValues(uri,"POST", content)); var result = ser.Deserialize<dynamic>(response); object pulledObject = null; string token ="access_token"; if (result.ContainsKey(token)) { pulledObject = result[token]; } //return result; return pulledObject; } private static int[] GetExpiryAndIssueDate() { var utc0 = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); var issueTime = DateTime.UtcNow; var iat = (int)issueTime.Subtract(utc0).TotalSeconds; var exp = (int)issueTime.AddMinutes(55).Subtract(utc0).TotalSeconds; return new[] { iat, exp }; } } } |
另一种工作方法
在 ConfigAuth 中添加以下代码
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | { AccessType ="offline", // can use only if require ClientId = ClientId, ClientSecret = ClientSecret, Provider = new GoogleOAuth2AuthenticationProvider() { OnAuthenticated = context => { context.Identity.AddClaim(new Claim("Google_AccessToken", context.AccessToken)); if (context.RefreshToken != null) { context.Identity.AddClaim(new Claim("GoogleRefreshToken", context.RefreshToken)); } context.Identity.AddClaim(new Claim("GoogleUserId", context.Id)); context.Identity.AddClaim(new Claim("GoogleTokenIssuedAt", DateTime.Now.ToBinary().ToString())); var expiresInSec = 10000; context.Identity.AddClaim(new Claim("GoogleTokenExpiresIn", expiresInSec.ToString())); return Task.FromResult(0); } }, SignInAsAuthenticationType = DefaultAuthenticationTypes.ApplicationCookie }; googleApiOptions.Scope.Add("openid"); // Need to add for google+ googleApiOptions.Scope.Add("profile");// Need to add for google+ googleApiOptions.Scope.Add("email");// Need to add for google+ googleApiOptions.Scope.Add("https://www.googleapis.com/auth/analytics.readonly"); app.UseGoogleAuthentication(googleApiOptions); |
在下面添加代码、名称空间和相关引用
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | using Google.Apis.Analytics.v3.Data; using Google.Apis.Auth.OAuth2; using Google.Apis.Auth.OAuth2.Flows; using Google.Apis.Auth.OAuth2.Responses; using Google.Apis.Services; using Microsoft.AspNet.Identity; using Microsoft.Owin.Security; using System; using System.Threading.Tasks; using System.Web; using System.Web.Mvc; public class HomeController : Controller { AnalyticsService service; public IAuthenticationManager AuthenticationManager { get { return HttpContext.GetOwinContext().Authentication; } } public async Task<ActionResult> AccountList() { service = new AnalyticsService(new BaseClientService.Initializer() { HttpClientInitializer = await GetCredentialForApiAsync(), ApplicationName ="Analytics API sample", }); //Account List ManagementResource.AccountsResource.ListRequest AccountListRequest = service.Management.Accounts.List(); //service.QuotaUser ="MyApplicationProductKey"; Accounts AccountList = AccountListRequest.Execute(); return View(); } private async Task<UserCredential> GetCredentialForApiAsync() { var initializer = new GoogleAuthorizationCodeFlow.Initializer { ClientSecrets = new ClientSecrets { ClientId = ClientId, ClientSecret = ClientSecret, }, Scopes = new[] {"https://www.googleapis.com/auth/analytics.readonly" } }; var flow = new GoogleAuthorizationCodeFlow(initializer); var identity = await AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ApplicationCookie); if (identity == null) { Redirect("/Account/Login"); } var userId = identity.FindFirstValue("GoogleUserId"); var token = new TokenResponse() { AccessToken = identity.FindFirstValue("Google_AccessToken"), RefreshToken = identity.FindFirstValue("GoogleRefreshToken"), Issued = DateTime.FromBinary(long.Parse(identity.FindFirstValue("GoogleTokenIssuedAt"))), ExpiresInSeconds = long.Parse(identity.FindFirstValue("GoogleTokenExpiresIn")), }; return new UserCredential(flow, userId, token); } } |
在 Global.asax 的 Application_Start() 中添加这个
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h