iCalendarSharp
A C# NuGet plugin for your web or desktop application.
The iCalendarSharp is an open-source component that simply creates an .ics file for compatible iCalendar applications. You can create your own derived classes to handle complex appointments or tasks, but this application is a good starting point.
After you create your .ics file, you can easily attach it to an email using MvcMailer or the standard System.Net.Mail.MailMessage object.
This initial version just contain one derived class that I included that builds a simple Calendar appointment.
You can easily install the component using Nuget in Visual Studio. It does require .Net 4.5 to work. Using the Visual Studio Package Manager, you can install it like this:
How to use it
​Here is an example of how the code is used:
01.
// Create the Event request object and populate it with your values.
02.
CalendarEventRequest cEvent =
new
CalendarEventRequest();
03.
cEvent.PRODID =
"-//Gizmo Beach//My Demo app 1.0 MIMEDIR//EN"
;
04.
cEvent.DateStart = DateTime.Parse(
"7/26/2014 7:30AM"
).ToString(
"yyyyMMdd\\THHmmss"
);
05.
cEvent.DateEnd = DateTime.Parse(
"7/26/2014 11:30AM"
).ToString(
"yyyyMMdd\\THHmmss"
);
06.
cEvent.Description =
"Important Reminders \n• Please arrive at the course at least 30 minutes prior to Shotgun start time.\n• CASH ONLY for payment of green fees and guest fees!!!\n• Slow play is not permitted. Please be courteous to all golfers and keep on pace.\nIf you have any questions please contact either:\n• communityservices@la-quinta.org - 760-777-7090"
;
07.
cEvent.Location =
"Classic Club Golf Course - Palm Desert"
;
08.
cEvent.Priority = 2;
09.
cEvent.Subject =
"Classic Club Golf Course"
;
10.
cEvent.UID =
"something@mydomain.com"
;
11.
cEvent.Version =
"2.0"
;
12.
cEvent.FileName =
"Classic Club Golf Course"
;
13.
14.
// Create a new instance of your implemented ICalendar class.
15.
ICalendar simple =
new
SimpleCalendar(cEvent);
16.
17.
// Pass your ICalendar instance into the Calendar class.
18.
Calendar calendar =
new
Calendar(simple);
19.
20.
// Save the .ics file. In this case the file name will be: "Classic Club Golf Course.ics"
21.
calendar.Save();
A look at the Code
Here's a look at some of the code used to create this component. First there's the Calendar class. This is the main class that all the ICalendar implemented classes get composed with. It's a very simple class that wraps other functionality such as saving the file to disk in your application, and retrieving the file.
01.
using
System;
02.
using
System.Linq;
03.
using
iCalendarSharp.Helpers;
04.
using
iCalendarSharp.Interfaces;
05.
06.
namespace
iCalendarSharp
07.
{
08.
/// <summary>
09.
/// This is the main message creator class.
10.
/// </summary>
11.
public
class
Calendar
12.
{
13.
#region ctors
14.
15.
private
readonly
ICalendar _calendar;
16.
17.
public
Calendar(ICalendar calendar)
18.
{
19.
this
._calendar = calendar;
20.
}
21.
22.
#endregion
23.
24.
#region Public Methods
25.
26.
/// <summary>
27.
/// Save the message to the file system.
28.
/// </summary>
29.
public
void
Save()
30.
{
31.
FileManager.SaveFile(_calendar.FileName, _calendar.Build());
32.
}
33.
34.
#endregion
35.
}
36.
}
You can see that there's not much here, most of the work is done in the implemented classes.
Here's a look at the SimpleCalendar class.
01.
using
System;
02.
using
System.Linq;
03.
using
System.Text;
04.
using
iCalendarSharp.DomainObjects;
05.
using
iCalendarSharp.Helpers;
06.
using
iCalendarSharp.Infrastructure;
07.
using
iCalendarSharp.Interfaces;
08.
09.
namespace
iCalendarSharp.Calendars
10.
{
11.
public
class
SimpleCalendar : ICalendar
12.
{
13.
#region ctors
14.
15.
private
readonly
CalendarEventRequest _request;
16.
17.
public
SimpleCalendar(CalendarEventRequest request)
18.
{
19.
this
._request = request;
20.
}
21.
22.
#endregion
23.
24.
/// <summary>
25.
/// The full physical path to the .vcs file.
26.
/// </summary>
27.
public
string
FileName
28.
{
29.
get
{
return
_request.FileName; }
30.
}
31.
32.
/// <summary>
33.
/// Build the appointment message.
34.
/// </summary>
35.
/// <returns></returns>
36.
public
string
Build()
37.
{
38.
StringBuilder sb =
new
StringBuilder();
39.
FormatHelper helper =
new
FormatHelper();
40.
PropertyBuilder prop =
new
PropertyBuilder(sb);
41.
42.
// These are the basic message header properties needed for every message.
43.
prop.BeginCalendar();
44.
prop.Version(_request.Version);
45.
prop.BeginEvent();
46.
47.
// These are the message specific properties needed just for my particular purpose.
48.
// In this case, it's just a basic calendar appointment with no bells-and-whistles.
49.
prop.DateStart(_request.DateStart);
50.
prop.DateEnd(_request.DateEnd);
51.
prop.Location(_request.Location);
52.
prop.Description(helper.FixLineBreaksFromHTML(_request.Description));
53.
prop.Subject(_request.Subject);
54.
prop.Priority(_request.Priority);
55.
56.
// These are the basic footer message properties.
57.
prop.EndEvent();
58.
prop.EndCalendar();
59.
60.
string
calendar = sb.ToString();
61.
62.
return
calendar;
63.
}
64.
}
65.
}
Before I describe what's going on here, let's take a look at the ICalendar interface.
01.
using
System;
02.
using
System.Linq;
03.
04.
namespace
iCalendarSharp.Interfaces
05.
{
06.
/// <summary>
07.
/// All concrete calendars should implement this interface.
08.
/// </summary>
09.
public
interface
ICalendar
10.
{
11.
12.
#region Interface Members
13.
14.
/// <summary>
15.
/// Build the overall vCalendar formatted body using StringBuilder
16.
/// and the PropertyBuilder class.
17.
/// </summary>
18.
/// <returns></returns>
19.
string
Build();
20.
21.
/// <summary>
22.
/// Get the full physical path to the .ics file.
23.
/// </summary>
24.
string
FileName {
get
; }
25.
26.
#endregion
27.
28.
}
29.
}
Again, this is very simple, which is the way I like it. The Build() method is where you put your Event specific code, with the event properties that you want in your message.
The FileName property contains the full physical path to the .ics file in your application. This is so you can retrieve it later. There are some applications that create the .ics file to send in an email immediately after creating it, but in my case, I found that the point at which I create the file, is not going to be the same moment that it will be attached in an email. So I made it so the file could be stored on the file system for later retrieval.
So back up in the implement SimpleCalendar class, the Build() method contains all the properties necessary to assemble all the needed message values.
I also created a PropertyBuilder class that wraps the StringBuilder instance for creating the necessary formatted strings and values from the CalendarEventRequest class.
This is a look at the PropertyBuilder class. Additional property methods can easily be included here in the future as needed.
001.
using
System;
002.
using
System.Linq;
003.
using
System.Text;
004.
005.
namespace
iCalendarSharp.Infrastructure
006.
{
007.
/// <summary>
008.
/// This is the class used to write to and access the properties you need
009.
/// for your derived Calendar class instance.
010.
/// </summary>
011.
public
class
PropertyBuilder
012.
{
013.
#region ctors
014.
015.
private
readonly
StringBuilder _sb;
016.
017.
public
PropertyBuilder(StringBuilder sb)
018.
{
019.
this
._sb = sb;
020.
}
021.
022.
#endregion
023.
024.
#region Public Value Methods
025.
026.
public
void
ProdId(
string
value)
027.
{
028.
_sb.AppendFormat(
"PRODID:{0}"
, value);
029.
_sb.AppendLine();
030.
}
031.
032.
public
void
Version(
string
value =
"2.0"
)
033.
{
034.
035.
_sb.AppendFormat(
"VERSION:{0}"
, value);
036.
_sb.AppendLine();
037.
}
038.
039.
public
void
DateStart(
string
value)
040.
{
041.
_sb.AppendFormat(
"DTSTART:{0}"
, value);
042.
_sb.AppendLine();
043.
}
044.
045.
public
void
DateEnd(
string
value)
046.
{
047.
_sb.AppendFormat(
"DTEND:{0}"
, value);
048.
_sb.AppendLine();
049.
}
050.
051.
public
void
Location(
string
value)
052.
{
053.
_sb.AppendFormat(
"LOCATION:{0}"
, value);
054.
_sb.AppendLine();
055.
}
056.
057.
public
void
Description(
string
value)
058.
{
059.
_sb.AppendFormat(
"DESCRIPTION;ENCODING=QUOTED-PRINTABLE:={0}{1}"
, System.Environment.NewLine, value);
060.
_sb.AppendLine();
061.
}
062.
063.
public
void
Subject(
string
value)
064.
{
065.
_sb.AppendFormat(
"SUMMARY:{0}"
, value);
066.
_sb.AppendLine();
067.
}
068.
069.
public
void
Priority(
int
value)
070.
{
071.
_sb.AppendFormat(
"PRIORITY:{0}"
, value);
072.
_sb.AppendLine();
073.
}
074.
075.
076.
077.
#endregion
078.
079.
#region Enumerable Methods
080.
081.
082.
083.
#endregion
084.
085.
#region Begin Methods
086.
087.
public
void
BeginCalendar()
088.
{
089.
_sb.AppendLine(
"BEGIN:VCALENDAR"
);
090.
}
091.
092.
public
void
BeginEvent()
093.
{
094.
_sb.AppendLine(
"BEGIN:VEVENT"
);
095.
}
096.
097.
098.
#endregion
099.
100.
#region End Methods
101.
102.
public
void
EndEvent()
103.
{
104.
_sb.AppendLine(
"END:VEVENT"
);
105.
}
106.
107.
public
void
EndCalendar()
108.
{
109.
_sb.AppendLine(
"END:VCALENDAR"
);
110.
}
111.
112.
#endregion
113.
}
114.
}
It offers an easy way of adding properties to your implemented classes to provide only those values that you want in your message.
Helper Classes
There are some helper classes that provide reusable functionality such as replacing HTML breaks (<br />) with encoded characters so line breaks can work correctly in applications like Outlook.
In the case of displaying the message body in Outlook, all HTML breaks would have to be replaced with: =0D=0A.
iCalendarSharp in Action in an ASP.NET MVC application
In the github source there is an ASP.NET MVC 5 application written in Visual Studio 2013, that implements this.
This is a picture of the home page of the MVC application.
From here you click on the "Messages" link in the top navigation to go to the input form.
Once you fill out the form, it will do three things:
1) Create the .ics file
2) Save it inside the web application
3) Send an email to the recipient with the .ics attachment.
Here's what the email message looks like in your inbox:
You can see the "Demo Message.ics" attachment. When you double-click the file, it opens in a window that allows you to save it to your calendar.
Once you see that everything is ok, you click the "Save and Close" button and it will be saved to your calendar.
That's it! That's the iCalendarSharp component. It's very easy to use for this simple purpose.
Summary
That's about it for this first version of the iCalendarSharp component. Again at the moment, it is primarily to be used for creating calendar appointments. Tasks, ToDo's and other features like recurring events, are not implemented in this version.
Have fun.