目前,我正在开发一个网站,它将数据从 Apple 日历同步到我的应用程序,反之亦然。
为了将 Apple 日历中的数据获取到我的应用程序,我已经可以从 iCloud 日历中获取
.ics
文件,而且效果很好。
但是,我在 Apple 日历中创建新事件时遇到问题。不知何故,我发送的每个请求都会有结果
400 Bad Request
。
以下是请求的详细信息:
If-None-Match: *
PUT
https://p46-caldav.icloud.com/[USER_ID]/calendars/work/dfsfsdfsfsfsfsdfsdfsdf.ics
text/calendar
httpWebRequest.Credentials = new NetworkCredential(username, password);
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# 代码演示了如何通过 WebDAV 和 iCal 将新事件添加到 Apple iCalendar 日历。使用的NuGet包是:
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 的初步知识。