无法从谷歌日历同步到我的 .Net Mvc Web App

Posted

技术标签:

【中文标题】无法从谷歌日历同步到我的 .Net Mvc Web App【英文标题】:Cant sync from google calendar to my .Net Mvc Web App 【发布时间】:2021-07-09 11:44:59 【问题描述】:

我正在尝试从谷歌日历同步到我的 .NET MVC Web 应用程序。

我创建了一个回调方法,Googles Calendar API 会将日历中的新事件发送到该方法。但我没有收到新的谷歌日历活动,而是收到了这个error

2021-07-09 12:52:26,982 [37] 调试 DotNetOpenAuth.Messaging - DotNetOpenAuth.OAuth2.Messages.AccessTokenFailedResponse 消息中缺少以下必需参数:error,

2021-07-09 12:52:26,997 [ 37] 警告 DotNetOpenAuth.Messaging 多种消息类型似乎适合传入的数据:AccessTokenSuccessResponse (2.0), UnauthorizedResponse (2.0),

2021-07-09 12:52:27,013 [ 37] 调试 DotNetOpenAuth.Messaging.Channel 收到 AccessTokenSuccessResponse 响应。

2021-07-09 12:52:27,013 [ 37] 信息 DotNetOpenAuth.Messaging.Channel 处理传入的 AccessTokenSuccessResponse (2.0) 消息:access_token: token_type: Bearer expires_in: 3599 范围: https://www.googleapis.com/auth/calendar

2021-07-09 12:52:27,013 [ 37] 调试 DotNetOpenAuth.Messaging.Channel 经过绑定元素处理后,收到的AccessTokenSuccessResponse(2.0)消息为:access_token: token_type: Bearer expires_in: 3599 范围: https://www.googleapis.com/auth/calendar

我该如何处理?

编辑(添加代码)

 public void PushNotificationCallback()
    
        try
                        
            var header = Request.Headers;
         
            NotificationResponse notification = new NotificationResponse(header["X-Goog-Channel-Expiration"], header["X-Goog-Channel-Id"], header["X-Goog-Message-Number"], header["X-Goog-Resource-Id"], header["X-Goog-Resource-State"], header["X-Goog-Channel-Token"], header["X-Goog-Resource-Uri"]);   
       
           therapistCalendarEntryController.PushNotificationCallback (notification);

        
        catch (Exception e)
        
          ...
                    
    

在控制器动作中

public void PushNotificationCallback(NotificationResponse response)
                            
        if (!string.IsNullOrEmpty(response?.HTTP_X_GOOG_CHANNEL_TOKEN))  surrounded with if
        
            var TherpistRepisitoryCallback = TherapistRepository ?? (Global.IoC.TryResolve<IRepository<Therapist>>());
            var therapistId = new Guid(response.HTTP_X_GOOG_CHANNEL_TOKEN);
            var therapistCall = TherpistRepisitoryCallback.Get(therapistId);                

            if (therapistCall != null)
            
                SyncGoogleCalendarEvents(therapistCall, null, true);
             
                 
    


public void SyncGoogleCalendarEvents(Therapist therapist, string pagingToken, bool syncAllEvents)
                
        var TherpistRepisitoryCallback = TherapistRepository ?? (Global.IoC.TryResolve<IRepository<Therapist>>());
        var TherapistCalendarEntryRepositoryCallback = TherapistCalendarEntryRepository ?? (Global.IoC.TryResolve<IRepository<TherapistCalendarEntry>>());

        try
        
            Encoding encoding = Encoding.UTF8;
            string SyncTokenStr = "";
            string PageTokenStr = "";

            if (pagingToken != null)
                PageTokenStr = "&pageToken=" + pagingToken;
            if (therapist.SyncTokenGoogleCalendar != null)
                SyncTokenStr = "&syncToken=" + therapist.SyncTokenGoogleCalendar;                

            var request = (HttpWebRequest)WebRequest.Create(new Uri(@"https://www.googleapis.com/calendar/v3/calendars/primary/events?showDeleted=true" + PageTokenStr + SyncTokenStr, UriKind.Absolute));
            if (therapist.RefreshTokenGoogle != null)
            
                var authenticator = GetAuthenticator(therapist);
                GoogleAuthorizationHelper.apply((GoogleApiUtils.GoogleAuthenticator)authenticator, request);
            
            request.Method = "GET";
            request.ContentType = "application/json";

            try
            
                var response = (HttpWebResponse)request.GetResponse();
                string jsonString = GetResponseJson(response);
                PrintResponseJson(jsonString, "sync from google calendar");

                var data = (JObject)JsonConvert.DeserializeObject(jsonString);

                if (data["nextPageToken"] != null)
                
                    if (syncAllEvents == true)
                    
                        AddGoogleCalendarEventToTipulog(therapist, TherapistCalendarEntryRepositoryCallback, data);
                    

                    SyncGoogleCalendarEvents(therapist, data["nextPageToken"].ToString(), syncAllEvents);
                
                else
                
                    saveTherapistNextToken(therapist, TherpistRepisitoryCallback, data);
                    if (syncAllEvents == true)
                    
                        AddGoogleCalendarEventToTipulog(therapist, TherapistCalendarEntryRepositoryCallback, data);
                    
                             

            
            catch (WebException e)
            
                ...
            

            catch (Exception e)
            
                ...
            
        
        catch (Exception e)
        
           ...
        
    

【问题讨论】:

请编辑您的问题并包括minimal reproducible example @DaImTo 我尝试添加所有相关代码 您没有使用 google .net 客户端库的任何原因?您的问题是您没有添加包含已在适当范围内授权的访问令牌的授权标头。 @DaImTo 谢谢,你能添加一些缺少header的示例代码吗? 不像我使用 Google .net 客户端库,如果您要重新发明***,它会为我处理所有这些。只需查看如何添加授权标头即可。 【参考方案1】:

我有一个教程展示了如何设置一个 MVC 项目以使用 Google people api Asp .net core 3 and Google login进行授权

一旦你设置了 DI,你就可以调用你想要的 API。

 // This configures Google.Apis.Auth.AspNetCore3 for use in this app.
 services
     .AddAuthentication(o =>
     
         // This forces challenge results to be handled by Google OpenID Handler, so there's no
         // need to add an AccountController that emits challenges for Login.
         o.DefaultChallengeScheme = GoogleOpenIdConnectDefaults.AuthenticationScheme;
         // This forces forbid results to be handled by Google OpenID Handler, which checks if
         // extra scopes are required and does automatic incremental auth.
         o.DefaultForbidScheme = GoogleOpenIdConnectDefaults.AuthenticationScheme;
         // Default scheme that will handle everything else.
         // Once a user is authenticated, the OAuth2 token info is stored in cookies.
         o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
       )
       .AddCookie()
       .AddGoogleOpenIdConnect(options =>
       
          options.ClientId = ClientId;
          options.ClientSecret = ClientSecret;
           );

博客帖子 How to get a Google users profile information, with C#. 有一个配套视频,但它使用的是 Google people api。

这是一个如何将其调整为 google calendar api 的示例。

    /// <summary>
    /// List all calendars in a users Calendar List.
    /// </summary>
    /// <param name="auth"></param>
    /// <returns></returns>
    [GoogleScopedAuthorize(CalendarService.ScopeConstants.Calendar)]
    public async Task<IActionResult> Index([FromServices] IGoogleAuthProvider auth)
    
        var cred = await auth.GetCredentialAsync();
        var service = new CalendarService(new BaseClientService.Initializer
        
            HttpClientInitializer = cred
        );

        var response = await service.CalendarList.List().ExecuteAsync();
        return View(response);
    

我正在为 Google 日历编辑视频

【讨论】:

以上是关于无法从谷歌日历同步到我的 .Net Mvc Web App的主要内容,如果未能解决你的问题,请参考以下文章

谷歌日历 API 从谷歌日历设置中获取工作时间数据

使用 python 从谷歌日历事件中提取与会者响应

尝试使用 Google.Apis.Gmail 从 asp.net core web api 应用程序从谷歌工作区发送电子邮件时出错

Maven 不会从谷歌存储库下载 jars

ASP.NET / MVC 1.0 组件和 Ajax 控件 - 网格 - 日历 - 搜索?

日历推送通知到 Java 应用引擎后端 servlet