在C#中创建iCal文件


76

我正在寻找一种在C#(asp.net)中生成iCalendar文件(* .ics)的好方法。我找到了一些资源,但是缺少的一件事是它们对带引号的可打印字段(具有回车符和换行符的字段)的支持。

例如,如果描述字段的编码不正确,则仅显示第一行,并可能破坏* .ics文件中的其余信息。

我正在寻找可以生成* .ics文件的现有类和/或可以生成带引号的可打印字段的类。


8
即使这个问题很久以前发生了,我还是想指出,带引号的可打印字段不是iCalendar标准(vCalendar 2.0)的一部分。它们是vCalendar标准(vCalendar 1.0)的一部分,而该标准如今已很少使用(如果有的话)。iCalendar拥有自己的转义数据方法,比带引号的可打印数据更干净,更易于解释。
道格

Answers:



12

我发现这样做的最简单方法是使用微格式标记HTML 。

如果您要生成iCalendar文件,则可以使用hCalendar微格式,然后添加诸如“添加到日历”之类的链接,该链接指向:

http://feeds.technorati.com/events/ [您网页的完整URL,包括http://]

然后,Technorati页面解析您的页面,提取hCalendar信息并将iCalendar文件发送给客户端。


3
NerdDinner.com使用此方法,并且效果很好。就是说,我必须给DDay.iCal +1(尽管我偏见):)
Doug 2010年

我不喜欢这种方法,因为technorati可以更改其规格甚至关闭服务。不过,这是个好主意。
加布里埃尔·埃斯皮诺萨

3

我编写了一个匀场函数来处理此问题。它基本上是合规的-唯一的麻烦是第一行是74个字符而不是75个字符(74个字符用于处理后续行的空格)...

 Private Function RFC2445TextField(ByVal LongText As String) As String

     LongText = LongText.Replace("\", "\\")
     LongText = LongText.Replace(";", "\;")
     LongText = LongText.Replace(",", "\,")

     Dim sBuilder As New StringBuilder
     Dim charArray() As Char = LongText.ToCharArray

     For i = 1 To charArray.Length
         sBuilder.Append(charArray(i - 1))
         If i Mod 74 = 0 Then sBuilder.Append(vbCrLf & " ")
     Next

     Return sBuilder.ToString

 End Function

我将其用作ICS feed的摘要和描述。只需在行之前添加字段即可(例如LongText =“ SUMMARY:Event Title”)。只要将缓存设置得足够长,操作就不会太昂贵。


受您的代码启发,我重写了它(尽管使用C#),其中解析是按块而不是按字符进行的。可以通过以下相关问题进行检查:stackoverflow.com/a/27164955/914512
reexmonkey

2

iCal(ical 2.0)和quoted-printable不能同时使用。

vCal(vCal 1.0)中经常使用带引号的可打印字符来表示不可打印的字符,例如换行符(= 0D = 0A)。默认的vCal编码是7位,因此有时您需要使用quoted-printable来表示非ASCII字符(您可以覆盖默认的编码,但是不需要其他与​​vCal兼容的通信方也可以理解它。)

iCal中,特殊字符使用转义符表示,例如'\ n'。默认编码为UTF-8,所有符合iCal的各方都必须支持它,这使得在iCal 2.0(和vCard 3.0)中完全不需要带引号的可打印内容。

您可能需要支持您的客户/利益相关者以阐明要求。vCal和iCal之间似乎有些混乱。


感谢您强调UTF-8是默认编码。
Andrea Antonangeli 2015年


1

根据RFC-2445,注释和描述字段为TEXT。测试字段的规则为:[1] TEXT字段中的一行不得超过75个八位位组。[2]包装是通过在后面插入一个CRLF和空白来实现的。[3]必须编码几个字符,包括\(反斜杠);(分号),(逗号)和换行符。使用\(反斜杠)作为定界符得到\ \;。\,\ n

示例:以下是该属性的示例,该属性在属性值中带有换行符:

 DESCRIPTION:Meeting to provide technical review for "Phoenix"
   design.\n Happy Face Conference Room. Phoenix design team
   MUST attend this meeting.\n RSVP to team leader.

1

我缺少自定义时区的示例。因此,这里有一个片段,显示了如何在ics中设置时区(并将其发送到asp.net中的浏览器)。

//set a couple of variables for demo purposes
DateTime IcsDateStart = DateTime.Now.AddDays(2);
DateTime IcsDateEnd = IcsDateStart.AddMinutes(90);
string IcsSummary = "ASP.Net demo snippet";
string IcsLocation = "Amsterdam (Netherlands)";
string IcsDescription = @"This snippes show you how to create a calendar item file (.ics) in ASP.NET.\nMay it be useful for you.";
string IcsFileName = "MyCalendarFile";

//create a new stringbuilder instance
StringBuilder sb = new StringBuilder();

//begin the calendar item
sb.AppendLine("BEGIN:VCALENDAR");
sb.AppendLine("VERSION:2.0");
sb.AppendLine("PRODID:stackoverflow.com");
sb.AppendLine("CALSCALE:GREGORIAN");
sb.AppendLine("METHOD:PUBLISH");

//create a custom time zone if needed, TZID to be used in the event itself
sb.AppendLine("BEGIN:VTIMEZONE");
sb.AppendLine("TZID:Europe/Amsterdam");
sb.AppendLine("BEGIN:STANDARD");
sb.AppendLine("TZOFFSETTO:+0100");
sb.AppendLine("TZOFFSETFROM:+0100");
sb.AppendLine("END:STANDARD");
sb.AppendLine("END:VTIMEZONE");

//add the event
sb.AppendLine("BEGIN:VEVENT");

//with a time zone specified
sb.AppendLine("DTSTART;TZID=Europe/Amsterdam:" + IcsDateStart.ToString("yyyyMMddTHHmm00"));
sb.AppendLine("DTEND;TZID=Europe/Amsterdam:" + IcsDateEnd.ToString("yyyyMMddTHHmm00"));

//or without a time zone
//sb.AppendLine("DTSTART:" + IcsDateStart.ToString("yyyyMMddTHHmm00"));
//sb.AppendLine("DTEND:" + IcsDateEnd.ToString("yyyyMMddTHHmm00"));

//contents of the calendar item
sb.AppendLine("SUMMARY:" + IcsSummary + "");
sb.AppendLine("LOCATION:" + IcsLocation + "");
sb.AppendLine("DESCRIPTION:" + IcsDescription + "");
sb.AppendLine("PRIORITY:3");
sb.AppendLine("END:VEVENT");

//close calendar item
sb.AppendLine("END:VCALENDAR");

//create a string from the stringbuilder
string CalendarItemAsString = sb.ToString();

//send the ics file to the browser
Response.ClearHeaders();
Response.Clear();
Response.Buffer = true;
Response.ContentType = "text/calendar";
Response.AddHeader("content-length", CalendarItemAsString.Length.ToString());
Response.AddHeader("content-disposition", "attachment; filename=\"" + IcsFileName + ".ics\"");
Response.Write(CalendarItemAsString);
Response.Flush();
HttpContext.Current.ApplicationInstance.CompleteRequest();

0

iCal可能很复杂,因此我建议使用一个库。DDay是一个很好的免费解决方案。最后,我检查了它对重复发生的事件没有完全支持,但是除此之外,它看起来确实不错。绝对要与几个客户一起测试日历。


0

我知道为时已晚,但可能会帮助他人。就我而言,我写了以下扩展名为.ics的文本文件

BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Calendly//EN
CALSCALE:GREGORIAN
METHOD:PUBLISH
BEGIN:VEVENT
DTSTAMP:20170509T164109Z
UID:your id-11273661
DTSTART:20170509T190000Z
DTEND:20170509T191500Z
CLASS:PRIVATE
DESCRIPTION:Event Name: 15 Minute Meeting\nDate & Time: 03:00pm - 03:15pm (
 Eastern Time - US & Canada) on Tuesday\, May 9\, 2017\n\nBest Phone Number
  To Reach You :: xxxxxxxxx\n\nany "link": https://wwww.yahoo.com\n\n
SUMMARY:15 Minute Meeting
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR

它为我工作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.