Google Calendar V3 freezes when used outside of local environment

I am working on a wrapper for the .net version of the Google Calendar API. Authentication is pretty simple and works fine locally (localhost: port).

UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
               new ClientSecrets
               {
                   ClientId = "The id of my public website",
                   ClientSecret = "The secret of my public website",
               },
               new[] { CalendarService.Scope.Calendar },
               "user",
               CancellationToken.None).Result;

            // Create the service.
            var service = new CalendarService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential
            });

return service.Events.List("primary").Execute().Items;

      

The problem is that when the same code is deployed to production (secrets, of course) the application just hangs whenever I try to access the data. There is no exception, no error code, it just keeps loading forever.

Has anyone experienced this?

0


source to share


3 answers


I'm with you. For some reason, this also happened to me. It was Golgotha. The code below works for me. This is my own version of the simple ASP.NET API of the simple task.

Add this data ...

using System.IO;
using System.Threading;

using Google.Apis.Calendar.v3;
using Google.Apis.Calendar.v3.Data;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Auth.OAuth2.Flows;
using Google.Apis.Auth.OAuth2.Web;
using Google.Apis.Services;
using Google.Apis.Util.Store;

      



And these...

CalendarService service;
static string gFolder = System.Web.HttpContext.Current.Server.MapPath("/App_Data/MyGoogleStorage");

protected void Page_Load(object sender, EventArgs e)
{
    IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(
        new GoogleAuthorizationCodeFlow.Initializer
        {
            ClientSecrets = GetClientConfiguration().Secrets,
            DataStore = new FileDataStore(gFolder),
            Scopes = new[] { CalendarService.Scope.Calendar }
        });

    var uri = Request.Url.ToString();
    var code = Request["code"];
    if (code != null)
    {
        var token = flow.ExchangeCodeForTokenAsync(UserId, code,
            uri.Substring(0, uri.IndexOf("?")), CancellationToken.None).Result;

        // Extract the right state.
        var oauthState = AuthWebUtility.ExtracRedirectFromState(
            flow.DataStore, UserId, Request["state"]).Result;
        Response.Redirect(oauthState);
    }
    else
    {
        var result = new AuthorizationCodeWebApp(flow, uri, uri).AuthorizeAsync(UserId,
            CancellationToken.None).Result;
        if (result.RedirectUri != null)
        {
            // Redirect the user to the authorization server.
            Response.Redirect(result.RedirectUri);
        }
        else
        {
            // The data store contains the user credential, so the user has been already authenticated.
            service = new CalendarService(new BaseClientService.Initializer
            {
                ApplicationName = "Calendar API Sample",
                HttpClientInitializer = result.Credential
            });
        }
    }

}

public static GoogleClientSecrets GetClientConfiguration()
{
    using (var stream = new FileStream(gFolder + @"\client_secrets.json", FileMode.Open, FileAccess.Read))
    {
        return GoogleClientSecrets.Load(stream);
    }
}

      

Hope it helps.

+4


source


I suspect the problem is with what you are using AuthorizeAsync(...).Result

. Using the property will Result

block the current thread ... and I suspect ASP.NET is trying to schedule a continuation (when authentication completes) on the same thread, resulting in a deadlock.

Given that you are blocking anyway, is there any specific reason why you want to use the call AuthorizeAsync

? You usually use this in the context of an async method where you have:

var credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(...);

      



(Looking at GoogleWebAuthorizationBroker

, I don't see a synchronous alternative at the moment, but what you should probably be looking for I am guessing is GoogleWebAuthorizationBroker

not intended to be used in this situation.)

Admittedly, I don't know nearly as much as I probably should know about the ASP.NET sync context or the Google API, but hopefully explains why the problem might be a good starting point ... you probably want read Stephen Cleary's article on Synchronization Context .

0


source


First of all: See Google MVC tutorial

Step by step

1) Create a method in your controller:

 public async Task<ActionResult> Test()
    {
         //your code
    }

      

2) Create a controller:

public class AuthCallbackController : Google.Apis.Auth.OAuth2.Mvc.Controllers.AuthCallbackController
    {
        protected override Google.Apis.Auth.OAuth2.Mvc.FlowMetadata FlowData
        {
            get { return new AppFlowMetadata(); }
        }
    }

      

3) Configure Google Console

0


source







All Articles