Google Calendar API v3-在服务器上部署时请求超时 [英] Google Calendar API v3 - Request time out when deploy on server

查看:58
本文介绍了Google Calendar API v3-在服务器上部署时请求超时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试登录localhost,一切正常.

I tried to logged in localhost and everything works properly.

代码:

    public static bool LoginGoogleCalendar(string clientId, string clientSecret, string idGCalendarUser, string calendarServiceScope, string folder)
    {
        try
        {


            UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                                        new ClientSecrets
                                        {
                                            ClientId = clientId,
                                            ClientSecret = clientSecret,
                                        },
                                        new[] { calendarServiceScope },
                                        idGCalendarUser,
                                        CancellationToken.None, new FileDataStore(folder)).Result;
            return true;
        }
        catch (Exception ex)
        {
            Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
            return false;
        }
    }

(我正确设置了fileDataStore的授权)

(I set properly the authorization for fileDataStore)

在Google Developers Console中:

重定向URI:http://localhost/authorize/ Javascript起源:http://localhost:8081

Redirect URIs: http://localhost/authorize/ Javascript Origins: http://localhost:8081

我使用Visual Studio 2013,IIS 8

I use Visual Studio 2013, IIS 8

当我尝试登录服务器时,将阻塞整个服务器几分钟,之后的答案是:System.Web.HttpException请求超时.

When i try the login to the server, will block the entire server for minutes and the answer after is: System.Web.HttpException Request timed out.

在Google Developers Console中:

重定向URI:http://pippo.pluto.it/authorize/ Javascript起源:http://pippo.pluto.it

Redirect URIs: http://pippo.pluto.it/authorize/ Javascript Origins: http://pippo.pluto.it

在服务器上:IIS 7

On the server: IIS 7

对我的示例的引用: https://developers.google.com/google-apps/calendar/instantiate

The reference to my example: https://developers.google.com/google-apps/calendar/instantiate

推荐答案

我遇到了同样的问题.互联网上有很多示例告诉您使用该类.对于Web应用程序,这不是要使用的类.此类对于离线"应用程序将是完美的工作,但是当您在IIS服务器上使用此类时,它将尝试在服务器上打开弹出窗口,但它不允许这样做.

I walked into to same problem. Alot of examples on the internet tell you to use this class. For web applications this is not the class to use though. This class wil work perfect for "offline" applications, but when you use this class on the IIS server it wil try to open the popup on the server but it wont let it.

我使用的类:GoogleAuthorizationCodeFlow

The class I use: GoogleAuthorizationCodeFlow

using Google.Apis.Analytics.v3;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Auth.OAuth2.Flows;
using Google.Apis.Auth.OAuth2.Requests;
using Google.Apis.Auth.OAuth2.Web;
using Google.Apis.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;

namespace GoogleOauth2DemoWebApp
{
    public class GoogleOauth
    {
        public AnalyticsService Handle(string _userId, string _connectionString, string _googleRedirectUri, string _applicationName, string[] _scopes)
        {
            try
            {
                string UserId = _userId;//The user ID wil be for examlpe the users gmail address.
                AnalyticsService service;
                GoogleAuthorizationCodeFlow flow;
                //use extended class to create google authorization code flow
                flow = new ForceOfflineGoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
                {
                    DataStore = new DbDataStore(_connectionString),//DataStore class to save the token in a SQL database.
                    ClientSecrets = new ClientSecrets { ClientId = "XXX-YOUR CLIENTID-XXX", ClientSecret = "XXX-YOURCLIENTSECRET-XXX" },
                    Scopes = _scopes,
                });


                var uri = HttpContext.Current.Request.Url.ToString();
                string redirecturi = _googleRedirectUri;//This is the redirect URL set in google developer console.
                var code = HttpContext.Current.Request["code"];
                if (code != null)
                {
                    var token = flow.ExchangeCodeForTokenAsync(UserId, code,
                        uri.Substring(0, uri.IndexOf("?")), CancellationToken.None).Result;

                    var test = HttpContext.Current.Request["state"];

                    // Extract the right state.
                    var oauthState = AuthWebUtility.ExtracRedirectFromState(
                         flow.DataStore, UserId, HttpContext.Current.Request["state"]).Result;
                    HttpContext.Current.Response.Redirect(oauthState);
                }
                else
                {

                    var result = new AuthorizationCodeWebApp(flow, redirecturi, uri).AuthorizeAsync(UserId,
                         CancellationToken.None).Result;

                    if (result.RedirectUri != null)
                    {
                        // Redirect the user to the authorization server.
                        HttpContext.Current.Response.Redirect(result.RedirectUri);
                    }
                    else
                    {
                        // The data store contains the user credential, so the user has been already authenticated.
                        service = new AnalyticsService(new BaseClientService.Initializer()
                        {
                            HttpClientInitializer = result.Credential,
                            ApplicationName = _applicationName
                        });
                        return service;
                    }
                }
                return null;
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        internal class ForceOfflineGoogleAuthorizationCodeFlow : GoogleAuthorizationCodeFlow
        {
            public ForceOfflineGoogleAuthorizationCodeFlow(GoogleAuthorizationCodeFlow.Initializer initializer) : base(initializer) { }

            public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(string redirectUri)
            {
                var ss = new Google.Apis.Auth.OAuth2.Requests.GoogleAuthorizationCodeRequestUrl(new Uri(AuthorizationServerUrl));
                ss.AccessType = "offline";
                ss.ApprovalPrompt = "force";
                ss.ClientId = ClientSecrets.ClientId;
                ss.Scope = string.Join(" ", Scopes);
                ss.RedirectUri = redirectUri;
                return ss;
            }
        };
    }
}

我还使用了一个DataStore类.将令牌保存到服务器上的文件不是最佳实践.我使用了SQL数据库.

Also I user a DataStore class. Saving the tokens to a file on you server isnt the best practice. I used a SQL database.

数据存储类的示例.它将为您创建一张表格,这不是最好的方法,但是可以使您的测试工作得足够好.

Example of the datastore class. It will make a table for you, not the best way but for testing perpose good enough.

using Google.Apis.Json;
using Google.Apis.Util.Store;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GoogleOauth2DemoWebApp
{
    public class DbDataStore : IDataStore
    {

        readonly string connectionString;


        public string ConnectionString { get { return connectionString; } }
        private Boolean _ConnectionExists { get; set; }
        public Boolean connectionExists { get { return _ConnectionExists; } }


        /// <summary>
        /// Constructs a new file data store with the specified folder. This folder is created (if it doesn't exist 
        /// yet) under the current directory
        /// </summary>
        /// <param name="folder">Folder name</param>
        public DbDataStore(String _connectionString)
        {
            connectionString = _connectionString;

            SqlConnection myConnection = this.connectdb();   // Opens a connection to the database.

            if (_ConnectionExists)
            {
                // check if the Table Exists;
                try
                {
                    SqlDataReader myReader = null;
                    SqlCommand myCommand = new SqlCommand("select 1 from GoogleUser where 1 = 0",
                                             myConnection);
                    myReader = myCommand.ExecuteReader();
                    while (myReader.Read())
                    {
                        var hold = myReader["Column1"];
                    }
                }
                catch
                {
                    // table doesn't exist we create it
                    SqlCommand myCommand = new SqlCommand("CREATE TABLE [dbo].[GoogleUser]( " +
                                                          " [username] [nvarchar](4000) NOT NULL," +
                                                          " [RefreshToken] [nvarchar](4000) NOT NULL," +
                                                          " [Userid] [nvarchar](4000) NOT NULL" +
                                                           " ) ON [PRIMARY]", myConnection);
                    myCommand.ExecuteNonQuery();
                }
            }

            myConnection.Close();
        }

        /// <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);

            SqlConnection myConnection = this.connectdb();
            if (!_ConnectionExists)
            {
                throw new Exception("Not connected to the database");
            }

            // Try and find the Row in the DB.
            using (SqlCommand command = new SqlCommand("select Userid from GoogleUser where UserName = @username", myConnection))
            {
                command.Parameters.AddWithValue("@username", key);

                string hold = null;
                SqlDataReader myReader = command.ExecuteReader();
                while (myReader.Read())
                {
                    hold = myReader["Userid"].ToString();
                }
                myReader.Close();


                if (hold == null)
                {
                    try
                    {
                        // New User we insert it into the database
                        string insertString = "INSERT INTO [dbo].[GoogleUser]  ([username],[RefreshToken],[Userid]) " +
                                              " VALUES (@key,@value,'1' )";

                        SqlCommand commandins = new SqlCommand(insertString, myConnection);
                        commandins.Parameters.AddWithValue("@key", key);
                        commandins.Parameters.AddWithValue("@value", serialized);
                        commandins.ExecuteNonQuery();
                    }
                    catch (Exception ex)
                    {

                        throw new Exception("Error inserting new row: " + ex.Message);

                    }


                }
                else
                {
                    try
                    {
                        // Existing User We update it                        
                        string insertString = "update [dbo].[GoogleUser] " +
                                              " set  [RefreshToken] = @value  " +
                                              " where username = @key";

                        SqlCommand commandins = new SqlCommand(insertString, myConnection);
                        commandins.Parameters.AddWithValue("@key", key);
                        commandins.Parameters.AddWithValue("@value", serialized);
                        commandins.ExecuteNonQuery();
                    }
                    catch (Exception ex)
                    {

                        throw new Exception("Error updating user: " + ex.Message);

                    }
                }
            }


            myConnection.Close();
            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");
            }
            SqlConnection myConnection = this.connectdb();
            if (!_ConnectionExists)
            {
                throw new Exception("Not connected to the database");
            }

            // Deletes the users data.                        
            string deleteString = "delete from [dbo].[GoogleUser] " +
                                  "where username = @key";
            SqlCommand commandins = new SqlCommand(deleteString, myConnection);
            commandins.Parameters.AddWithValue("@key", key);
            commandins.ExecuteNonQuery();


            myConnection.Close();
            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)
        {
            //Key is the user string sent with AuthorizeAsync
            if (string.IsNullOrEmpty(key))
            {
                throw new ArgumentException("Key MUST have a value");
            }
            TaskCompletionSource<T> tcs = new TaskCompletionSource<T>();


            // Note: create a method for opening the connection.
            SqlConnection myConnection = new SqlConnection(this.ConnectionString);
            myConnection.Open();

            // Try and find the Row in the DB.
            using (SqlCommand command = new SqlCommand("select RefreshToken from GoogleUser where UserName = @username;", myConnection))
            {
                command.Parameters.AddWithValue("@username", key);

                string RefreshToken = null;
                SqlDataReader myReader = command.ExecuteReader();
                while (myReader.Read())
                {
                    RefreshToken = myReader["RefreshToken"].ToString();
                }

                if (RefreshToken == null)
                {
                    // we don't have a record so we request it of the user.
                    tcs.SetResult(default(T));
                }
                else
                {

                    try
                    {
                        // we have it we use that.
                        tcs.SetResult(NewtonsoftJsonSerializer.Instance.Deserialize<T>(RefreshToken));
                    }
                    catch (Exception ex)
                    {
                        tcs.SetException(ex);
                    }

                }
            }

            return tcs.Task;
        }

        /// <summary>
        /// Clears all values in the data store. This method deletes all files in <see cref="FolderPath"/>.
        /// </summary>
        public Task ClearAsync()
        {

            SqlConnection myConnection = this.connectdb();
            if (!_ConnectionExists)
            {
                throw new Exception("Not connected to the database");
            }

            // Removes all data from the Table.
            string truncateString = "truncate table [dbo].[GoogleUser] ";
            SqlCommand commandins = new SqlCommand(truncateString, myConnection);
            commandins.ExecuteNonQuery();

            myConnection.Close();
            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);
        }



        //Handel's creating the connection to the database
        private SqlConnection connectdb()
        {

            SqlConnection myConnection = null;
            try
            {
                myConnection = new SqlConnection(this.ConnectionString);
                try
                {
                    myConnection.Open();
                    // ensuring that we are able to make a connection to the database.
                    if (myConnection.State == System.Data.ConnectionState.Open)
                    {
                        _ConnectionExists = true;
                    }
                    else
                    {
                        throw new ArgumentException("Error unable to open connection to the database.");
                    }
                }
                catch (Exception ex)
                {

                    throw new ArgumentException("Error opening Connection to the database: " + ex.Message);
                }

            }
            catch (Exception ex)
            {

                throw new ArgumentException("Error creating Database Connection: " + ex.Message);
            }

            return myConnection;
        }
    }
}

使用课程:

GoogleOauth g = new GoogleOauth();
                AnalyticsService service = g.Handle(userEmailAddress, 
                    connectionString, redirectUrl,
                    "YOURAPLICATIONNAME",
                    new[] {AnalyticsService.Scope.AnalyticsReadonly});

                DataResource.RealtimeResource.GetRequest request = service.Data.Realtime.Get(String.Format("ga:{0}", profileId), "rt:activeUsers");
                RealtimeData feed = request.Execute();

如果人们感兴趣,我可以将示例项目上传到github.

If people are intrested I can upload a sample project to github.

这篇关于Google Calendar API v3-在服务器上部署时请求超时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆