Click here to Skip to main content
11,704,315 members (53,537 online)
Click here to Skip to main content

Event Calendar for an ASP.NET MVC Application

, 20 Jan 2011 GPL3 141.6K 10.8K 105
Rate this:
Please Sign up or sign in to vote.
The article explains how to integrate dhtmlxScheduler, an AJAX-based, interactive event calendar, in your ASP.NET MVC application.

Introduction

This tutorial explains the steps required to integrate a Google-like interactive event calendar in an ASP.NET MVC application. We will use dhtmlxScheduler, an Open-Source JavaScript calendar that provides an event scheduling interface with drag-and-drop capabilities and AJAX support. Events can be displayed in Day/Week/Month/Year views and edited by the end-user on the client side.

dhtmlxScheduler interface

Going through this article, you will learn how to put this AJAX-based event calendar on a web page, load events from .NET sever side, and update them in the database when the user makes changes in the browser.

Getting Started

First of all, we need to create a new ASP.NET MVC project. We'll call it, for example, "My Calendar". After that, create a database (or use any valid one) where you will save the calendar events. In the database, create the table "Events" with the following set of fields (all fields are mandatory):

Field Type Description
id identity, primary key event ID
text text event description
start_date datetime start date and time of event
end_date datetime end date and time of event

While the DB tool is open, you can add some test data to the "Events" table. In the attached sample package, you will find the MyCalendar.mdf file which already contains the necessary table and data.

Then we need to download the dhtmlxScheduler package - you can find the download link on the scheduler homepage. When the package is downloaded, unpack it and copy the contents from the folder 'codebase' to the folder 'Scripts' of your project. The result of this step should be similar to this:

Directory

Now everything is ready and all the necessary files are in place, so we can proceed to the next step.

Initialization

At the first set-out, we need to create a default view. Add a new controller "CalendarController" and create the "Index" view for it. Here is the content of the Index.aspx file:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head  runat="server">
<title>Index</title>
<script src="http://www.codeproject.com/Scripts/dhtmlxscheduler.js" 
            type="text/javascript"></script>
<link href="http://www.codeproject.com/Scripts/dhtmlxscheduler.css" 
            rel="stylesheet" type="text/css" />
<style type="text/css">
html, body
{
height:100%;
padding:0px;
margin:0px;
}
</style>
<script type="text/javascript">
function init() {
scheduler.init("scheduler_here",new Date(2010,6,1),"month");
}
</script>
</head>
<body  önload="init()">
<div id="scheduler_here" class="dhx_cal_container" style='width:100%; height:100%;'>
<div class="dhx_cal_navline">
<div class="dhx_cal_prev_button"> </div>
<div class="dhx_cal_next_button"> </div>
<div class="dhx_cal_today_button"></div>
<div class="dhx_cal_date"></div>
<div class="dhx_cal_tab" name="day_tab" style="removed:204px;"></div>
<div class="dhx_cal_tab" name="week_tab" style="removed:140px;"></div>
<div class="dhx_cal_tab" name="month_tab" style="removed:76px;"></div>
</div>
<div class="dhx_cal_header">
</div>
<div class="dhx_cal_data">
</div>
</div>
</body>
</html>

The default view loads the .js and .css files of dhtmlxScheduler and inits a full-screen scheduler. The second and third parameters in the scheduler.init command define the default date and mode, which will be in the calendar just after initialization. Except for the first line, the code doesn't have anything .NET MVC specific. Actually, it's fully taken from the standard dhtmlxScheduler sample.

Now we need to do one more thing - update the default route. Switch the default route of the app to the newly created controller in Global.asax.cs:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}", // URL with parameters
    new { controller = "Calendar", action = "Index", 
          id = UrlParameter.Optional } // Parameter defaults
    );
}

When everything is done and correct, you can run the app and see the following screen:

Calendar preview

If you don't see such a view, most probably you haven't copied the scheduler's files to the folder 'Scripts' correctly, so check it again.

The calendar created with dhtmlxScheduler has a clean and user-friendly interface, and managing the events is quite easy. To create new events, use double click or click-and-drag commands. By clicking on the tabs in the right corner, you can switch views: Day, Week, Month.

Loading Data

The view we have constructed in the previous steps looks fine, but it doesn't contain any data so we need to change this. At first, add 'Model' to your application (just use "Model > Add > Add new item" and select "Data", "Link to SQL Classes"). To complete the process, drag-and-drop the "Events" table to the Model Designer, and then add one more action to CalendarController.cs:

public ActionResult Data()
{
    MyEventsDataContext data = new MyEventsDataContext();
    return View(data.Events);
}

Define the view for that action - Data.aspx:

<%@ Page Language="C#" 
   Inherits="System.Web.Mvc.ViewPage<dynamic>" ContentType="text/xml" %>
<data>
<% foreach (var myevent in Model) { %>
<event id="<%=myevent.id%>">
<start_date>
 <![CDATA[<%= String.Format("{0:MM/dd/yyyy HH:mm}",
                            myevent.start_date) %>]]>
</start_date>
<end_date><![CDATA[<%= String.Format("{0:MM/dd/yyyy HH:mm}",
                       myevent.end_date) %>]]></end_date>
<text><![CDATA[<%= myevent.text%>]]></text>
</event>
<% } %>
</data>

Note that this template outputs not HTML, but XML data. For each event, it will output a block of XML data. The extra bit of the code is used to provide the data in the necessary format. If you need to add extra fields to the model, just add the extra tags to the view.

Then we adjust the initialization code of our scheduler in Index.aspx:

<script type="text/javascript">
function init() {
    scheduler.config.xml_date = "m/d/Y H:m"; // format of dates in XML
    scheduler.init("scheduler_here", new Date(2010, 6, 1), "month");
    scheduler.load("/Calendar/Data");  //path to the newly created action
}
</script>

We have just configured the date format (the same as in Data.aspx) and have defined the path to the action 'Data'. At this step, the running application will look like this:

Scheduler with events

Well, we are in the middle. After the next step, the major part of the job will be done.

Saving to the Database

After all the manipulations described above, we've got the scheduler which loads the events data from the database, but that's not enough. The next goal is to save changes made on the client side to the server. First of all, create one more action - CalendarController.cs:

public ActionResult Save(FormCollection actionValues)
{
    String action_type = actionValues["!nativeeditor_status"];
    Int64 source_id = Int64.Parse(actionValues["id"]);
    Int64 target_id = source_id;

    MyEventsDataContext data = new MyEventsDataContext();
    Event myevent;
    try{
        switch (action_type)
        {
            case "inserted":
                myevent = new Event();
                myevent.start_date = DateTime.Parse(actionValues["start_date"]);
                myevent.end_date = DateTime.Parse(actionValues["end_date"]);
                myevent.text = actionValues["text"];
                data.Events.InsertOnSubmit(myevent);
                break;
            case "deleted":
                myevent = data.Events.SingleOrDefault(ev => ev.id == source_id);
                data.Events.DeleteOnSubmit(myevent);
            break;
            default: // "updated"
                myevent = data.Events.SingleOrDefault(ev => ev.id == source_id);
                myevent.start_date = DateTime.Parse(actionValues["start_date"]);
                myevent.end_date = DateTime.Parse(actionValues["end_date"]);
                myevent.text = actionValues["text"];
                break;
        }
        data.SubmitChanges();
        target_id = myevent.id;
    }
    catch
    {
        action_type = "error";
    }

    return View(new CalendarActionResponseModel(action_type, source_id, target_id));
}

It seems that it's a lot of code but it's quite simple in its logic. In the first lines, we've got the type of the action from the incoming request. Then, according to the type, we insert, delete, or update the data in the database. And after the DB operation has completed, we render a response to the client-side scheduler.

The file Save.aspx will look like this:

<%@ Page Language="C#" 
    Inherits="System.Web.Mvc.ViewPage<scheduler.ActionResponseModel>" 
    ContentType="text/xml"%>
<data>
<action type="<%= Model.Status %>" sid="<%= Model.Source_id %>" 
             tid="<%= Model.Target_id %>"></action>
</data>

The view shown above uses the class CalendarActionResponseModel to transfer the necessary information from the action to the View. In CalendarController.cs, we add:

public class CalendarActionResponseModel
{
    public String Status;
    public Int64 Source_id;
    public Int64 Target_id;
    public CalendarActionResponseModel(String status, 
           Int64 source_id, Int64 target_id)
    {
        Status = status;
        Source_id = source_id;
        Target_id = target_id;
    }
}

Now we update Index.aspx one more time (add a code that will link updates on the client-side scheduler with the action 'Save'):

<script type="text/javascript">
function init() {
    scheduler.config.xml_date = "%m/%d/%Y %H:%i";
    scheduler.init("scheduler_here", new Date(2010, 6, 1), "month");
    scheduler.load("/Calendar/Data");

    var dp = new dataProcessor("/Calendar/Save");
    dp.init(scheduler);
    dp.setTransactionMode("POST", false);
}
</script>

So now, all the changes or new events will be saved to the DB. In addition, the calendar will correctly restore after page reloading. One final step left - improvements.

Improvements

The code we are using in 'SaveController' can be improved by using automatic bindings. In CalendarController.cs:

public ActionResult Save(Event changedEvent, FormCollection actionValues)
{
    String action_type = actionValues["!nativeeditor_status"];
    Int64 source_id = Int64.Parse(actionValues["id"]);
    Int64 target_id = source_id;
    MyEventsDataContext data = new MyEventsDataContext();
    try{
        switch (action_type)
        {
            case "inserted":
                data.Events.InsertOnSubmit(changedEvent);
                break;
            case "deleted":
                changedEvent = data.Events.SingleOrDefault(ev => ev.id == source_id);
                data.Events.DeleteOnSubmit(changedEvent);
                break;
            default: // "updated"
                changedEvent = data.Events.SingleOrDefault(ev => ev.id == source_id);
                UpdateModel(changedEvent);
                break;
        }
        data.SubmitChanges();
        target_id = changedEvent.id;
    }
    catch
    {
        action_type = "error";
    }
    return View(new CalendarActionResponseModel(action_type, source_id, target_id));
}

To give the calendar a more slick and glossy look, or to customize the coloring scheme, use the online SkinBuilder for dhtmlxScheduler. Select one of the "Glossy" skins to get a more modern look for the calendar. When you're done with the customization, download the skin package (CSS files and images) and unpack them in the folder 'Scripts' (it will overwrite some old scheduler files).

The running app after those updates will produce the final look:

Final look of the calendar

So we have implemented a web-based calendar that can be used in ASP.NET MVC and provides all the necessary functions: loading, saving, deleting, and updating calendar events.

If needed, you may define extra fields, add/move calendar views, and redefine scales and templates configuration (please refer to dhtmlxScheduler documentation). All those modifications can be achieved by adding extra JavaScript commands in the "Index" view. There is no need for any further updates in the "CalendarController.cs" code.

Note that the dhtmlxScheduler sources are distributed under GNU GPL v2. For the licensing details, visit the DHTMLX website.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)

Share

About the Author

Stas Wolski
Software Developer (Senior)
Russian Federation Russian Federation
Building web apps since 2001. Rich experience in HTML frontends for different platforms.

You may also be interested in...

Comments and Discussions

 
GeneralThanks a lot for such a detailed tutorial! Pin
vladidrozd16-Aug-15 23:00
membervladidrozd16-Aug-15 23:00 
QuestionWould this work for my application? Pin
Member 996303511-Aug-15 2:55
memberMember 996303511-Aug-15 2:55 
QuestionError following The Steps Pin
Member 115230611-Apr-15 7:48
memberMember 115230611-Apr-15 7:48 
Questionhow to start week on sunday instead of monday Pin
Member 31330863-Mar-15 4:40
memberMember 31330863-Mar-15 4:40 
Questioncan't save event on scheduler when hosting IIS 7 Pin
n3eck4-Dec-14 17:12
membern3eck4-Dec-14 17:12 
QuestionLanguage Pin
Member 1065595115-Jul-14 1:21
memberMember 1065595115-Jul-14 1:21 
QuestionEvent Mgmt required Pin
NandaKishore 235-Jun-14 21:32
memberNandaKishore 235-Jun-14 21:32 
QuestionWhat happens on saving an event? Pin
Member 100665211-Jan-14 19:45
memberMember 100665211-Jan-14 19:45 
QuestionNot able to create Events Pin
Robert Clove24-Aug-13 3:47
memberRobert Clove24-Aug-13 3:47 
GeneralPlease help help.....I need to resolve this urgent Pin
Jayakumar13-Aug-13 22:04
memberJayakumar13-Aug-13 22:04 
GeneralRe: Please help help.....I need to resolve this urgent Pin
Member 824043114-Aug-13 3:15
memberMember 824043114-Aug-13 3:15 
GeneralSmall popup calendar for week selection Pin
Jayakumar13-Aug-13 19:37
memberJayakumar13-Aug-13 19:37 
QuestionEvent Calendar for an ASP.NET MVC Razor view engine Pin
Mohammed Salah8-May-13 5:31
memberMohammed Salah8-May-13 5:31 
QuestionHow do I test out the application? Pin
WENDARIEN10-Feb-13 23:55
memberWENDARIEN10-Feb-13 23:55 
GeneralThanks Pin
Member 805831215-Jan-13 23:45
memberMember 805831215-Jan-13 23:45 
Questionerror: Object doesn't support property or method 'load' Pin
martina loescher20-Oct-12 10:14
membermartina loescher20-Oct-12 10:14 
QuestionJQuery Pin
Pie At The Raven15-May-12 0:27
memberPie At The Raven15-May-12 0:27 
QuestionError Pin
dana_131014-May-12 21:14
memberdana_131014-May-12 21:14 
QuestionDispaly Event Infromation on Mouse hover Pin
prashantvk15-Mar-12 0:10
memberprashantvk15-Mar-12 0:10 
AnswerRe: Dispaly Event Infromation on Mouse hover Pin
Stas Wolski2-Apr-12 7:11
memberStas Wolski2-Apr-12 7:11 
GeneralMy vote of 5 Pin
GastonV7-Mar-12 1:20
memberGastonV7-Mar-12 1:20 
QuestionError Message Pin
Member 203666413-Jul-11 16:33
memberMember 203666413-Jul-11 16:33 
AnswerRe: Error Message Pin
Stas Wolski10-Aug-11 1:02
memberStas Wolski10-Aug-11 1:02 
GeneralRe: Error Message Pin
ertan_ozenli16-Apr-12 11:09
memberertan_ozenli16-Apr-12 11:09 
GeneralOther language Pin
celsocld17-May-11 8:35
membercelsocld17-May-11 8:35 
GeneralRe: Other language Pin
Stas Wolski20-May-11 3:20
memberStas Wolski20-May-11 3:20 
QuestionLast question ... How you pass are parm into the Linq to SQL call Pin
plunkman14-Apr-11 5:50
memberplunkman14-Apr-11 5:50 
AnswerRe: Last question ... How you pass are parm into the Linq to SQL call Pin
Stas Wolski19-Apr-11 3:33
memberStas Wolski19-Apr-11 3:33 
QuestionQuestion: Are the names of table elements mandatory? Pin
xiecsuk29-Mar-11 5:54
memberxiecsuk29-Mar-11 5:54 
AnswerRe: Question: Are the names of table elements mandatory? Pin
Stas Wolski19-Apr-11 3:34
memberStas Wolski19-Apr-11 3:34 
GeneralThanks for that Pin
xiecsuk19-Apr-11 22:17
memberxiecsuk19-Apr-11 22:17 
QuestionRequired field Pin
plunkman29-Mar-11 3:22
memberplunkman29-Mar-11 3:22 
AnswerRe: Required field Pin
Stas Wolski19-Apr-11 3:36
memberStas Wolski19-Apr-11 3:36 
QuestionQuestion: Where does OnLoad="init()" go on Content Page Pin
xiecsuk29-Mar-11 2:44
memberxiecsuk29-Mar-11 2:44 
AnswerRe: Question: Where does OnLoad="init()" go on Content Page Pin
Stas Wolski19-Apr-11 3:39
memberStas Wolski19-Apr-11 3:39 
GeneralRe: Question: Where does OnLoad="init()" go on Content Page Pin
xiecsuk19-Apr-11 22:13
memberxiecsuk19-Apr-11 22:13 
GeneralRe: Question: Where does OnLoad="init()" go on Content Page Pin
Member 278243523-May-11 3:23
memberMember 278243523-May-11 3:23 
GeneralRe: Question: Where does OnLoad="init()" go on Content Page Pin
xiecsuk23-May-11 6:24
memberxiecsuk23-May-11 6:24 
Hi

I have managed to display the calendar on a Content page in one of two columns defined in the Master page. However, I haven't been able to get the data to display yet. I can get the code to create, update and delete an event using the calendar on an index page without a Master page setup, although there appears to be a problem with the way the dates are saved. The same code doesn't appear to work with a Master page / Content page setup. I get an error in the dhtmlxscheduler.js file. I am still working on it.
GeneralRe: Question: Where does OnLoad="init()" go on Content Page Pin
Keith_Wrong17-Jul-11 18:32
memberKeith_Wrong17-Jul-11 18:32 
GeneralNICE Pin
KatareRaju1-Mar-11 18:09
memberKatareRaju1-Mar-11 18:09 
GeneralMy vote of 5 Pin
KatareRaju1-Mar-11 18:08
memberKatareRaju1-Mar-11 18:08 
QuestionQuestion: adding new text field on the new event page Pin
plunkman16-Feb-11 7:26
memberplunkman16-Feb-11 7:26 
AnswerRe: Question: adding new text field on the new event page Pin
Stas Wolski17-Feb-11 23:02
memberStas Wolski17-Feb-11 23:02 
QuestionRe: Question: adding new text field on the new event page Pin
plunkman23-Mar-11 9:58
memberplunkman23-Mar-11 9:58 
AnswerRe: Question: adding new text field on the new event page Pin
plunkman23-Mar-11 10:24
memberplunkman23-Mar-11 10:24 
GeneralRe: Question: adding new text field on the new event page Pin
Stas Wolski24-Mar-11 0:12
memberStas Wolski24-Mar-11 0:12 
GeneralRe: Question: adding new text field on the new event page Pin
plunkman24-Mar-11 1:13
memberplunkman24-Mar-11 1:13 
GeneralRe: Question: adding new text field on the new event page Pin
plunkman24-Mar-11 9:58
memberplunkman24-Mar-11 9:58 
GeneralRe: Question: adding new text field on the new event page Pin
Stas Wolski18-Apr-11 6:15
memberStas Wolski18-Apr-11 6:15 
GeneralRe: Question: adding new text field on the new event page Pin
Jayakumar14-Aug-13 0:00
memberJayakumar14-Aug-13 0:00 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150819.1 | Last Updated 20 Jan 2011
Article Copyright 2011 by Stas Wolski
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid