在 iCloud Apple 日历中创建新事件总是会导致 400 错误请求

问题描述 投票:0回答:1

目前,我正在开发一个网站,它将数据从 Apple 日历同步到我的应用程序,反之亦然。

为了将 Apple 日历中的数据获取到我的应用程序,我已经可以从 iCloud 日历中获取

.ics
文件,而且效果很好。

但是,我在 Apple 日历中创建新事件时遇到问题。不知何故,我发送的每个请求都会有结果

400 Bad Request

以下是请求的详细信息:

  1. 标题:
    If-None-Match: *
  2. 方法:
    PUT
  3. Uri目的地:
    https://p46-caldav.icloud.com/[USER_ID]/calendars/work/dfsfsdfsfsfsfsdfsdfsdf.ics
  4. 内容类型:
    text/calendar
  5. Apple ID 和应用程序特定密码使用 NetworkCredential 设置。这对于从苹果日历获取数据来说效果很好,所以我不认为这是问题的根源。这是它的片段代码:
    httpWebRequest.Credentials = new NetworkCredential(username, password);
  6. 对于请求内容,其实我已经尝试了很多东西。这里我只设置 RFC 4791
  7. 中的一个

BEGIN:VCALENDAR VERSION:2.0 PRODID:-//Example Corp.//CalDAV Client//EN BEGIN:VEVENT UID:[email protected] DTSTAMP:20060712T182145Z DTSTART:20060714T170000Z DTEND:20060715T040000Z SUMMARY:Bastille Day Party END:VEVENT END:VCALENDAR

有人知道可能出什么问题吗?

c# icloud webdav caldav
1个回答
0
投票

这里的工作 C# 代码演示了如何通过 WebDAV 和 iCal 将新事件添加到 Apple iCalendar 日历。使用的NuGet包是:

  • Ical.Net 4.2.0,作者:Rian Stockbower、Douglas Day 和贡献者 - 为 ical 实现了 .NET 接口;下面的代码使用它来编写和序列化一个新的日历事件,为 WebDAV 做好准备。
  • WebDav.Clien 2.8.0 by skazantsev - 为 WebDAV 实现 .NET 接口;下面的代码使用它来通过
    caldav.icloud.com
    进行身份验证,并将新事件放在 Apple 服务器上。

可以从代码和代码注释中提取更多重要细节。

using System.Net;
using Ical.Net.CalendarComponents;
using Ical.Net.DataTypes;
using Ical.Net.Serialization;
using Ical.Net;
using WebDav;

namespace Falael.Auto.Mon.Acq
{
    class Program
    {
        static async Task Main(string[] args)
        {
            //////////////////////////////////////////////////////////////////////////////
            //  webdav client
            var webDavClientParams = new WebDavClientParams
            {
                //  pXXX can be acquired from the public URL when the calendar is marked 
                //      as Public Calendar from the icloud.com web calendar
                BaseAddress = new Uri("https://pXXX-caldav.icloud.com"),
                //  an apple-app-specific-password can be acquired via icloud.com,
                //      "Manage Apple ID", App-Specific Passwords
                Credentials = new NetworkCredential("apple-id", "apple-app-specific-password")
            };

            //  can be acquired from network activity in chrome dev tools in icloud.com web 
            //      calendar by inspecting the first POST request when creating a new event
            var dsid = "1234567890";

            var client = new WebDavClient(webDavClientParams);
            try
            {
                var response = await client.Propfind($"/{dsid}/calendars");
                foreach (var res in response.Resources)
                {
                    Console.WriteLine($"Resource URI: {res.Uri}, {res.Properties.Count}");
                    var response2 = await client.Propfind(res.Uri);
                    foreach (var resource in response2.Resources)
                    {
                        Console.WriteLine($"-- Resource URI: {resource.Uri}, {resource.Properties.Count}");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
            }

            //  can be acquired by identifying the correct id from the calendar ids listed by the 
            //      above code; i used the number of events in each calendar to diversify
            var calendarId = "04690ac0-9911-4466-b30e-4c9d0f38dcde";

            //////////////////////////////////////////////////////////////////////////////
            //  ical
            var calendar = new Ical.Net.Calendar();
            var now = DateTime.Now;

            var calendarEvent = new CalendarEvent
            {
                Start = new CalDateTime(now.AddMinutes(5)),
                End = new CalDateTime(now.AddMinutes(5).AddHours(1)),
                Summary = "Test Event",
                Description = "This is a test event"            
            };
            calendarEvent.Alarms.Add(new Alarm 
            {
                Trigger = new Trigger(TimeSpan.FromMinutes(-1)),
                Action = AlarmAction.Display
            });
            calendarEvent.Alarms.Add(new Alarm
            {
                Trigger = new Trigger(TimeSpan.FromMinutes(-1)),
                Action = AlarmAction.Audio
            });

            calendar.Events.Add(calendarEvent);

            var serializer = new CalendarSerializer(new SerializationContext());
            var serializedCalendar = serializer.SerializeToString(calendar);
            var bytes = System.Text.Encoding.UTF8.GetBytes(serializedCalendar);
            var httpContent = new System.Net.Http.ByteArrayContent(bytes);

            //////////////////////////////////////////////////////////////////////////////
            //  create new event
            var eventUri = $"/{dsid}/calendars/{calendarId}/" + Guid.NewGuid().ToString() + ".ics";
            var putFileParameters = new PutFileParameters
            {
                ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("text/calendar"),
                Headers = new Dictionary<string, string>() 
                {
                    { "If-None-Match", "*" }, 
                    { "User-Agent", "Mozilla/5.0 (compatible; GoogleCalendarClient/1.0)" } 
                }
            };
            var content = new StringContent(serializedCalendar, System.Text.Encoding.UTF8, "text/calendar");
            var result = await client.PutFile(eventUri, content, putFileParameters);

            //  on success will show 201
            Console.WriteLine(result.StatusCode);
        }
    }
}

另请参阅:https://sabre.io/dav/building-a-caldav-client/#discovery - 包含有关如何使用 WebDAV 的宝贵信息(所有示例都是纯 XML),也可以应用于WebDAV 与 ical 的案例。不过,需要一些有关 WebDAV 的初步知识。

© www.soinside.com 2019 - 2024. All rights reserved.