Author: Craig Stuntz
I’m going to demonstrate how to use the open-source DayPilot Lite calendar control in an ASP.NET MVC application. I will discuss the capabilities of the control and consider the general problem of how to use controls designed for “plain” ASP.NET in MVC applications. I’m including a demo solution which you can download and run yourself.
Download the demo solution: DayPilot ASP.NET MVC demo
We needed a calendar control for an ASP.NET MVC application. In particular, we needed a control which would show a number of events and when they occur within a particular day, “Outlook-style.” I’ll include a screenshot of the demo application here, since it’s the best way to explain the type of control we were looking for:
Possible Alternatives to DayPilot
In my experience, the type of control which works best with ASP.NET MVC is a control which is completely ignorant of ASP.NET, and all the lies such as ViewState and postbacks which accompany it. In particular, I’ve had a good deal of success with controls designed for the jQuery JavaScript framework, which is included, by default, with ASP.NET MVC applications. Unfortunately, I was unable to find a jQuery control which data what we needed. The closest I found was jMonthCalendar which cannot display a single day in the manner illustrated above. I would still prefer a jQuery-based solution if one ever turns up.
I did, however, find a couple of controls designed for “plain” ASP.NET which, from an end-user point of view, it exactly what we needed. One was the DayPilot control illustrated above, the other was the scheduler component included with Telerik’s control suite. Telerik’s control claims some support for MVC, but this is really limited to loading calendar data asynchronously, which was not actually what we wanted to do. Also, Telerik’s control can only be purchased as part of their suite, which is rather expensive if you only need the calendar/scheduler control. Paying for the entire suite would not be a problem for us if it was filled with controls we needed, designed for the environment (MVC) we use. While Telerik seems serious about supporting MVC, they are in the early stages right now, so it is difficult to justify paying for a large suite in order to get a single control, which I would have to use in a mostly-unsupported way. The Telerik control has many more features than the DayPilot control, and, in my opinion, looks a little nicer.
The DayPilot calendar is available in two different editions. There is an open source edition, which is free, and a non-open-source edition, which adds features. The principal difference is that the date version includes editing (via postbacks) and UpdatePanel support, which are not really useful in an ASP.NET MVC application anyway. As with Telerik’s control, I have to adapt the control for use within ASP.NET MVC. So we selected the open source version, even though the paid version is priced reasonably.
Adapting DayPilot to ASP.NET MVC
In order to use the DayPilot control in ASP.NET MVC, I wanted to use markup which would look familiar to ASP.NET MVC developers:
1234 <%= Html.DayPilot(Model, <strong>new</strong> DayPilotViewOptions<br>{<br>HourHeight = 30<br>}) %>
This means that I needed to write an Html helper which will render the control based on the data passed in Model and return the literal HTML markup. In order to make that easier, I created two new types, DayPilotData and DayPilotViewOptions, in order to encapsulate access to the properties of the control. The reason I created two different types was to separate the concerns of data for the events (which will be set up in the controller) and display of the control (which is the concern of the view). The types are trivial, so I’m not going to show them in this post, but you can examine them in the demo solution. There is an overload to this Html helper which does not include the options argument in case you are happy with the defaults.
1234567891011121314151617181920212223242526 <strong> public static string</strong> DayPilot(<br><strong>this</strong> HtmlHelper helper,<br>DayPilotData model,<br>DayPilotViewOptions options)<br>{<br><strong>var</strong> calendar = <strong>new</strong> DayPilotCalendar();<br><strong>if</strong> (model != null)<br>{<br>model.CopyTo(calendar);<br>}<br><strong>if</strong> (options != null)<br>{<br>options.CopyTo(calendar);<br>}<br><strong>var</strong> sb = <strong>new</strong> System.Text.StringBuilder();<br>sb.Append("<div class="dayPilot">"); // allows working around td cellpadding bug in css<br><strong>using</strong> (<strong>var</strong> sw = <strong>new</strong> System.IO.StringWriter(sb))<br>{<br><strong>using</strong> (<strong>var</strong> tw = <strong>new</strong> HtmlTextWriter(sw))<br>{<br>calendar.RenderControl(tw);<br>}<br>}<br>sb.Append("</div>");<br><strong>return</strong> sb.ToString();<br>}
Note the div. The current version of DayPilot astonishingly, as of this writing, does not put a class anywhere in its rendered markup. Since the stylesheet for the default ASP.NET MVC site conflicts with DayPilot, to some degree, I wrapped the whole control in a div so that I could fix the layout in CSS.
Another way which I could have used the control in ASP.NET MVC would be to register a tag prefix and use code behind/code generation, as with standard ASP.NET. I’ve registered a tag prefix in the demo solution in case you want to try that yourself. Be aware, however, that setting up codebehind and code generation files in an MVC application is somewhat less than simple; doing it right requires, among other things, manual editing of the csproj file. So I do recommend using the control in the way I’ve illustrated.
Finally, here’s the source code for the action which supplies data for the control. Since this is a demo solution, I’m generating random events:
1234567891011121314151617181920 <strong> public</strong> ActionResult Index()<br>{<br><strong>var</strong> r = <strong>new</strong> Random();<br><strong>var</strong> q = <strong>from</strong> i <strong>in</strong> Enumerable.Range(1, 4)<br><strong>let</strong> start = DateTime.Today.AddHours(r.Next(47))<br><strong>select new</strong> DayPilotDataItem<br>{<br>Id = i,<br>Start = start,<br>End = start.AddHours(1),<br>Text = string.Format("Event {0}", i)<br>};<br><strong>var</strong> model = <strong>new</strong> DayPilotData<br>{<br>StartDate = DateTime.Today,<br>Days = 2,<br>Data = q<br>};<br><strong>return</strong> View(model);<br>}
Of course, it’s just as easy to select data from a database.
The current version of DayPilot has a kind of a weird limitation: You cannot make it smaller, in the vertical dimension, than 30 pixels per hour. Based on some inspection of the source code, I think this is fixable if you are comfortable altering the source. But be aware of the limitation.
There are more DayPilot features which I have not covered, but that should be enough to get you on your way. If you have any questions, post them in comments, and I’ll see whdat I can do to help out.
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition