Story Details for articles

iCalendarSharp Component

kahanu
Author:
Version:
1.0.0.0
Views:
8359
Date Posted:
7/24/2014 2:34:08 PM
Date Updated:
7/24/2014 2:34:08 PM
Rating:
5/2 votes
Framework:
.Net 4.5
Platform:
Windows
Programming Language:
C#
Technologies:
Tags:
ical, icalendar, icalendarsharp, outlook
Demo site:
Home Page:
https://github.com/kahanu/iCalendarSharp
Share:

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();

In this case I'm creating a simple Calendar appointment (Event) that I was to pass along to my customers.  The way I would use this, is by adding this code into an ASP.NET MVC application, or a WebForms application, then implementing some mail sending code like MvcMailer to attach this .ics file to. You can view all the code which contains a demo MVC project that implements this.

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.

Comments

    No comments yet.

 

User Name:
(Required)
Email:
(Required)