Click here to Skip to main content
16,019,593 members
Articles / Web Development

How to Build a Room Booking Calendar with dhtmlxScheduler

Rate me:
Please Sign up or sign in to vote.
4.94/5 (29 votes)
5 Feb 2018GPL37 min read 184.9K   12.4K   104   43
This article describes how to implement a meeting room booking system in an ASP.NET MVC project with dhtmlxScheduler.

Introduction

In the previous MVC-related tutorial, I described how to integrate dhtmlxScheduler into an ASP.NET MVC application and create an event calendar to manage and edit events online. This time I decided to continue this series and show you how to extend the calendar functionality to implement a meeting room booking system.

In this tutorial, I will explain how to add multi-user functionality to the scheduling system, allowing different users to make changes in the calendar simultaneously. A meeting room booking system, which we're going to build, will look like this:

room-booking-calendar/1_booking_calendar.png

In the end of the tutorial, we will get a ready-to-use event scheduling application that allows end-users to add, delete, edit, and move events between different rooms. I'm going to continue my previous tutorial, so you can learn how to integrate the calendar into an ASP.NET MVC application here.

Setting Goals

Before I describe how to extend the functionality of the calendar, we need to define the list of features of our room booking app:

  • Events can be created only by authorized users
  • A user can edit only events that he/she created
  • Expired events can't be edited
  • Each event can be assigned only to one room from a list
  • Users can see events by assigned room (room view)
  • Users can see all events within a week (week agenda view)
  • Events created by different users are colored differently

The list is not short, but most of the requirements can be achieved by using dhtmlxScheduler extensions and standard ASP.NET MVC solutions.

Getting Started

In the previous tutorial, I described how to use dhtmlxScheduler 2.6, but recently the new version 3.0 has been released. The update includes some bug fixes and some new features that we will need in our app.

So at first, download the most recent version of dhtmlxScheduler from this page. After you download the package, copy the content from the folder 'codebase' to the folder 'Scripts' of your project (if you were using v.2.6, new files will overwrite the old ones).

The new features that we will use in our booking application:

  • simple event colors (to set different colors for events created by each user)
  • week agenda view (allows end-user to see all events within the current week)

Database Structure and .NET Membership

Our database should store information about available rooms and users that have access to the system. So let's create a table Rooms in our database with the following columns:

  • room_id – ID of the room
  • title – name of the room

In order not to create user infrastructure manually, we will use the built-in ASP.NET Membership utility (read more about it here). All we need to do is:

Run the tool with the following keys:

aspnet_regsql.exe -E -S <servername> -d <databasename> -A m

It will create several tables (and a database, if it doesn't exist yet):

All these tables are used by ASP.NET Membership for providing its functionality. We should only edit the table aspnet_Users by adding a column 'color' into it.

To simplify things, let's rename the mapping table aspnet_User to User and leave just the columns we will use, which are:

We'll use the controllers and views generated by a standard MVC project. So you don't need to create any new files, you just need to alter the existing ones a little:

To link users and rooms with events, we add two more columns to the table Events:

When you finish with this (created all the needed tables and added the missing columns), don't forget to refresh MyEvents.dbml.

If you don't want to edit the DB manually, you can use the database from the package with the sample files. It contains all the needed tables and columns.

  1. Run the ASP.NET SQL Server Registration Tool (Aspnet_regsql.exe) (find the details here). The tool comes with the .NET Framework, and can be found under: C:\WINDOWS\Microsoft.NET\Framework\\aspnet_regsql.exe.
    • aspnet_Applications
    • aspnet_Membership
    • aspnet_SchemaVersions
    • aspnet_Users
    • color – the color of the user's events
    • UserId
    • UserName
    • Color
  2. Customize authorization-related controllers and views.
    • change the redirect path in AccountController.cs
    • remove the default CSS processing
    • room_id – a foreign key for the Rooms table
    • user_id – a foreign key for the aspnet_Users table

room-booking-calendar/2.png

User Authentication

Now all the required conditions for authentication are provided, so we can add this functionality to our calendar. For that, we will need to do three things:

XML
<membership defaultProvider="CustomMembershipProvider">
  <providers>
    <clear/>
    <add name="CustomMembershipProvider" 
         type="System.Web.Security.SqlMembershipProvider"
         connectionStringName="MyCalendarConnectionString"
         enablePasswordRetrieval="false"
         enablePasswordReset="true"
         requiresQuestionAndAnswer="false"
         requiresUniqueEmail="false"
         maxInvalidPasswordAttempts="5"
         minRequiredPasswordLength="1"
         minRequiredNonalphanumericCharacters="0"
         passwordAttemptWindow="10"
         applicationName="/" />
  </providers>
</membership>

Here MyCalendarConnectionString is the name of the connectionString attribute set in the same file. The generated views and controllers are ready to use and don't need any corrections.

In our sample, we use a database that contains two test users. You can use the following username/password pairs to log in:

XML
...
<div class="dhx_cal_navline">
    <div class="" style="removed420px;height:23px;"> 
      <% Html.RenderPartial("LogOnUserControl"); %></div>
...
  1. Add settings into the Web.config file:
  2. It's not necessary that our app will have free registration, so we can remove the registration link from LogOn.aspx and the related 'action' from the controller.
    • test / test
    • user / user
  3. Add a link to LogOn in the Index.aspx file. View/Calendar/Index.aspx:

After all these steps, we’ll get a working calendar system which contains a user login form. In Month View, our calendar will look like this:

room-booking-calendar/3.png

User Access Security

To provide user access control (according to our requirements), we need to add some checks on both client and server side.

Server-side checks are needed to provide security for the application. Client-side checks do not affect application security and we could do without them, but it would make our system slow. So, we will define client-side checks to provide better performance and real-time user experience.

Client-side rules – Views/Calendar/Index.aspx:

JavaScript
<script type="text/javascript">
    //stores the name of the user in js var
    <% if(Request.IsAuthenticated){ %>
        scheduler._user_id = "<%= Model.User.UserId %>";
        scheduler._color = "<%= Model.User.color %>";
    <%} %>
    //blocks all operations for non-authenticated users
    scheduler.config.readonly = 
      <%= Request.IsAuthenticated ? "false" : "true" %>;

    //checks if an event belongs to a certain user and it’s not started yet
    var isEditable = function(event_id){
        var ev = scheduler.getEvent(event_id);
        return (ev && ev.start_date > new Date() && 
                ev.user_id == scheduler._user_id);
    };
    //blocks operations for non-owned events
scheduler.attachEvent("onBeforeLightbox", isEditable);
    scheduler.attachEvent("onBeforeDrag", isEditable);
    scheduler.attachEvent("onClick", isEditable);
    scheduler.attachEvent("onDblClick",isEditable);      
    //each time as a new event is created - it assigns a user, color and room
    scheduler.attachEvent("onEventCreated", function(event_id){
        var ev = scheduler.getEvent(event_id);
        if (ev.start_date < new Date()){
            scheduler.deleteEvent(event_id, true);
        } else {
            ev.user_id = scheduler._user_id;
            ev.textColor = scheduler._color;
            return true;    
       }
    });
</script>

We will add the same rules to the server-side. If a user is not authorized to edit the events, or a user name doesn't match the name of the current user, then changes won't be saved and 'error' will be returned.

Controllers/CalendarController.cs

C#
public ActionResult Save(Event changedEvent, FormCollection actionValues)
{
    ...
    if (Request.IsAuthenticated && changedEvent.user_id == 
       (Guid)Membership.GetUser().ProviderUserKey && 
        changedEvent.start_date > DateTime.Now)
    {
        ...
        //default processing logic
    }
    else
    {
        action_type = "error";
    }

Now we need to include the information about the event holder to our data feed and pass the needed models from the Index.aspx controller to the view.

Views/Calendar/Data.aspx

XML
<data>
    <% foreach (var myevent in Model) { %>
        <event id="<%=myevent.id%>" textColor=
          "<%= (myevent.start_date < DateTime.Now ? 
          "gray" : myevent.User.color) %>">
            <start_date><![CDATA[<%=    String.Format("{0:dd/MM/yyyy HH:mm}",
                  myevent.start_date) %>]]></start_date>
            <end_date><![CDATA[<%=      String.Format("{0:dd/MM/yyyy HH:mm}",
                  myevent.end_date) %>]]></end_date>
            <text><![CDATA[<%=         Html.Encode(myevent.text)%>]]></text>
            <room_id><![CDATA[<%=  myevent.room_id %>]]></room_id>
            <username><![CDATA[<%= myevent.username  %>]]></username>
        </event>
    <% } %>
</data>

Also, we will specify the property 'color' for events. From this moment on, events created by each user will be colored in the appropriate color. Expired events, which can't be edited, will be shown in grey color as disabled.

Views/Calendar/Data.aspx

C#
public ActionResult Index()
{
    MyEventsDataContext context = new MyEventsDataContext();

    User current_user = null;
    if (Request.IsAuthenticated)
        current_user = context.Users.SingleOrDefault(user => 
              user.UserId == (Guid)Membership.GetUser().ProviderUserKey);

    return View(new CalendarModel(current_user, context.Rooms.ToList());
}

CalendarModel is a class that contains information about the current user and the available rooms (creating a list of available rooms is our next step).

This is how our event calendar will look like. In Month view, we can see the events displayed in different colors by the user who created them. The old events are displayed in grey color and can't be edited.

room-booking-calendar/4.png

After these changes, we've achieved our main goal and created a multi-user event calendar. Users can see all the events, but they can only edit events that they created.

Agenda View and Room View

To follow the requirements we've set in the beginning, we will now add the ability to show events by room and view all events within the current week.

To see the list of events taking place within the current week, we can use the Week Agenda view of dhtmlxScheduler. We need to add the appropriate script and button to the Index.aspx file.

Views/Calendar/Index.aspx

HTML
<script 
   src="http://www.codeproject.com/Scripts/ext/dhtmlxscheduler_week_agenda.js" 
   type="text/javascript"></script>
...
<div class="dhx_cal_tab" name="week_agenda_tab" 
           style="removed278px;"></div>

The image below shows how our booking calendar will look in the Week Agenda view. We can see the list of events assigned per day of the week.

room-booking-calendar/5.png

To show events by the assigned room, we will use the Unit view of dhtmlxScheduler. Let's make the necessary modifications in the Index.aspx file:

HTML
<script src="http://www.codeproject.com/Scripts/ext/dhtmlxscheduler_units.js" 
        type="text/javascript"></script>
...
<div class="dhx_cal_tab" name="units_tab" 
        style="removed214px;"></div>

Also, we should add JavaScript code to configure the new view in the calendar. In Views/Calendar/Index.aspx:

JavaScript
scheduler.locale.labels.units_tab = 'Rooms';
scheduler.locale.labels.section_room = "Room:";
//a list of rooms
var rooms = [<% for(var i =0; i < Model.Rooms.Count; i++){ %>
     {key:<%= Model.Rooms[i].room_id %>, label:"<%= Html.Encode(
        Model.Rooms[i].title) %>"}<%= i<Model.Rooms.Count-1 ? "," : "" %>   
<% } %>];
//helper, returns room number by id
function getRoom(id){
    for(var i in rooms){
        if(rooms[i].key == id)
            return rooms[i].label;
    }
}

//units view
scheduler.createUnitsView({ 
    "name": "units",
    "list": rooms,                     
    "property": "room_id" 
});

Now we can see events by room number. This view allows users to check the availability of each room and find the best place and time for each event.

room-booking-calendar/6.png

Providing Better User Experience

To simplify user interactions with the calendar, we will add the ability to select a room number directly from the event lightbox of the calendar. To achieve this, we will define our own configuration for the event details form instead of the default one in the Index.aspx file:

C#
//lightbox configuration
scheduler.config.lightbox.sections = [
    {name:"description",height:200,map_to:"text",type:"textarea",focus:!0},
    {name:"room",map_to:"room_id",type:"select",options:rooms},
    {name:"time",height:72,type:"time",map_to:"auto"}             
];

Our custom event lightbox now has an additional select box with room numbers:

room-booking-calendar/7.png

To give users more information about the event, we can add room number to the event description. Add in Views/Calendar/Index.aspx:

C#
//custom event text
function template(start,end,ev){
    return getRoom(ev.room_id) + " : " + ev.text;
}
scheduler.templates.event_text = template;
scheduler.templates.agenda_text = template;
scheduler.templates.event_bar_text = template;
scheduler.templates.week_agenda_event_text = 
  function(start_date, end_date, event, date) {
    return scheduler.templates.event_date(start_date) + 
           " " + template(start_date, end_date, event);
};

And again, here is the final look of our room booking calendar:

room-booking-calendar/1_booking_calendar.png

If you have followed all the steps of the tutorial, you now have a multi-user calendar that allows end-users to easily book meeting rooms and arrange the events between rooms.

License

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


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

Comments and Discussions

 
Question[My vote of 2] Doesn't work with MVC 5 or even 4 Pin
Basharss6-Jul-15 21:26
Basharss6-Jul-15 21:26 
QuestionTimes Pin
Don Laverdure18-Mar-15 7:41
Don Laverdure18-Mar-15 7:41 
QuestionHow to build in razor view? Pin
Member 96188455-Dec-14 18:18
Member 96188455-Dec-14 18:18 
SuggestionTutorial for MVC4 & above Pin
Member 961884517-Nov-14 3:57
Member 961884517-Nov-14 3:57 
Questioncannot save event to database Pin
rosy8418-Aug-14 4:52
rosy8418-Aug-14 4:52 
QuestionCan't Add Event in IIS Pin
Mike Cheng Bonjour22-Jun-14 21:18
Mike Cheng Bonjour22-Jun-14 21:18 
QuestionHelp Pin
EmersonVaz23-Jan-14 16:12
EmersonVaz23-Jan-14 16:12 
GeneralMy vote of 5 Pin
Humayun Kabir Mamun17-Dec-13 19:57
Humayun Kabir Mamun17-Dec-13 19:57 
QuestionUrgent Help Needed Please Help Pin
Robert Clove24-Aug-13 6:59
Robert Clove24-Aug-13 6:59 
QuestionHow to Build a Room Booking Calendar with dhtmlxScheduler Pin
ly nguyen duy nguyen19-Mar-13 20:51
ly nguyen duy nguyen19-Mar-13 20:51 
QuestionUser registration Pin
jagadishanil14-Feb-13 20:35
jagadishanil14-Feb-13 20:35 
QuestionStart Date/ End Date has null value Pin
kpant12-Jul-12 0:04
kpant12-Jul-12 0:04 
GeneralMy vote of 5 Pin
Gaston Verelst6-Jun-12 3:57
Gaston Verelst6-Jun-12 3:57 
QuestionIs it possible to count the Items as per the date Pin
Sri Soma13-May-12 16:46
Sri Soma13-May-12 16:46 
QuestionData sorting/grouping Pin
compliedmonkey10-May-12 20:02
compliedmonkey10-May-12 20:02 
Questiondata disappear on user log out Pin
compliedmonkey19-Mar-12 1:23
compliedmonkey19-Mar-12 1:23 
AnswerRe: data disappear on user log out Pin
compliedmonkey20-Mar-12 0:01
compliedmonkey20-Mar-12 0:01 
GeneralRe: data disappear on user log out Pin
Stas Wolski22-Mar-12 4:55
Stas Wolski22-Mar-12 4:55 
GeneralRe: data disappear on user log out Pin
compliedmonkey27-Mar-12 23:12
compliedmonkey27-Mar-12 23:12 
GeneralRe: data disappear on user log out Pin
kpant11-Jul-12 20:47
kpant11-Jul-12 20:47 
AnswerRe: data disappear on user log out Pin
kpant12-Jul-12 21:36
kpant12-Jul-12 21:36 
AnswerRe: data disappear on user log out Pin
Robert Clove24-Aug-13 3:44
Robert Clove24-Aug-13 3:44 
GeneralMy vote of 5 Pin
Manoj Kumar Choubey29-Feb-12 18:11
professionalManoj Kumar Choubey29-Feb-12 18:11 
GeneralMy vote of 4 Pin
Abinash Bishoyi28-Feb-12 22:39
Abinash Bishoyi28-Feb-12 22:39 
QuestionSQLExpress 2005 version of Database Pin
compliedmonkey17-Feb-12 18:25
compliedmonkey17-Feb-12 18:25 

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

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