Build Room Booking System with dhtmlxScheduler (for ASP.NET MVC)

| Comments (33)

NOTE: We’re now offering DHTMLX Scheduler .NET, a web control optimized for ASP.NET MVC. You can also find the latest version of Booking Calendar in MVC3 here.

In the previous MVC-related tutorial we described how to integrate dhtmlxScheduler into an ASP.NET MVC application. After publication, we received plenty of feedback, reflecting that the tutorial was helpful to many of ASP.NET MVC developers. Therefore we decided to continue this series and show you how to extend the calendar functionality to implement a room booking system.

In this tutorial we’ll go further and add multi-user functionality to the scheduling system, allowing different users to make changes in the calendar simultaneously without impacting each other. As we already said, we’ll create a meeting room booking system which will look like on the screenshot below.

Download: the final package of the booking calendar for ASP.NET MVC

Room Booking Calendar with dhtmlxScheduler

Room Booking Calendar with dhtmlxScheduler

 
In the end of the tutorial we should get a ready-to-use event scheduling application that allows end-users to add, delete, edit, and move events between rooms. Since we’re going to continue our previous tutorial, it’s assumed that you have already learned how to integrate the calendar into an ASP.NET MVC application. If not, please read it first: “Event Calendar for ASP.NET MVC with dhtmlxScheduler”.

 
Setting Goals

Now I will describe how to extend the functionality of our calendar to make it a complete, real-life web application. Here is the list of the features we’re going to implement:

  • Events can be created only by authorized users
  • A user can edit only events that he 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, and you would spend a lot of time trying to implement such an application from scratch. Fortunately, most of the requirements can be achieved by using dhtmlxScheduler extensions and standard ASP.NET MVC solutions. So I believe we’ll manage to complete this task within half an hour.

 
Step 1 – Getting Started

In the previous tutorial we used dhtmlxScheduler 2.6, but recently the new version 3.0 has been released. The update includes lots of small bug-fixes and offers a number of new useful features that we might need.

So at first you need to update the dhtmlxScheduler package (available under GNU GPL). You can grab the most recent version from the Downloads page. After you download the package, copy the content from the folder ‘codebase’ to the folder ‘Scripts’ of your project, like we made before with the files of dhtmlxScheduler 2.x (new files will overwrite the old ones).

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

  • 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)

 
 
Step 2 – 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 build-in ASP.NET Membership utility (read more about it here).

All we need to do is:

1. Run 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.

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):

  • aspnet_Applications
  • aspnet_Membership
  • aspnet_SchemaVersions
  • aspnet_Users

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

  • color – the color of user’s events

 
To simplify things, let’s rename the mapping table ‘aspnet_User’ to ‘User’ and leave just the columns we will use, such as:

  • UserId
  • UserName
  • color

 
2. Customize authorization-related controllers and views.

We will 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:

  • change the redirect path in the ‘AccountController.cs’
  • remove default css processing

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

  • room_id – a foreign key for the ‘Rooms’ table
  • user_id – a foreign key for the ‘aspnet_Users’ table

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

NOTE: If you don’t want to edit DB manually you can use db from the package with the sample files. It contains all needed tables and columns.

Database Tables

Database Tables

 
 
Step 3 – Authentication

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

1. Add settings into the Web.config file:

<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. Generated views and controllers don’t need any corrections.

 
2. It’s not necessary that our app will have free registration, so we can remove the registration link from LogOn.aspx and related ‘action’ from the controller.

NOTE: In our sample we use a db that contains 2 test users. You can use the following username/password pairs to log in:

  • username – test, password – test
  • username – user, password – user

 
 
3. Add a link to LogOn in the Index.aspx file. View/Calendar/Index.aspx:

...
<div class="dhx_cal_navline">
    <div class="" style="right:420px;height:23px;"> <% Html.RenderPartial("LogOnUserControl"); %></div>
...

 
After all these steps we’ll get a working calendar system which contains a user login form.

Event Calendar - Month View

Event Calendar - Month View

 
 
Step 4 – 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 of the application. Client-side checks do not affect the 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:

<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:

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";
    }

 
We have a few last things left at this step. 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:

<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 a each user will be colored into appropriate color. Expired events, which can’t be edited, will be showed in grey color as disabled.

Views/Calendar/Data.aspx:

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

 
Here ‘CalendarModel’ is a class that contains information about the current user and 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 a user who created them. The old events are displayed in grey color and can’t be edited.

Room Booking Calendar - Colored Events

Room Booking Calendar - Colored Events

 
After these changes, we’ve achieved our main goal and created a multi-user calendar. All users can see all the events, but events can be edited only by a user who created them.

 
 
Step 5 – Agenda View and Unit (Room) View

In compliance with the requirements we’ve set in the beginning, we will 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 Week Agenda View, a new feature available in dhtmlxScheduler 3.0. All we need to do is to add the appropriate script and button to the Index.aspx file.

Views/Calendar/Index.aspx:

<script src="/Scripts/ext/dhtmlxscheduler_week_agenda.js" type="text/javascript"></script>
...
<div class="dhx_cal_tab" name="week_agenda_tab" style="right:278px;"></div>

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

Room Booking Calendar - Week Agenda View

Room Booking Calendar - Week Agenda View

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

<script src="/Scripts/ext/dhtmlxscheduler_units.js" type="text/javascript"></script>
...
<div class="dhx_cal_tab" name="units_tab" style="right:214px;"></div>

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

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 - Unit View

Room Booking Calendar - Unit View

 
 
Step 6 – 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 achive this, we will define our own configuration for the event details form instead of the default one in the Index.aspx file:

//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 - Custom Event Lightbox

Room Booking Calendar - Custom Event Lightbox

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

//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 with dhtmlxScheduler

Room Booking Calendar with dhtmlxScheduler

 
If you have followed these 6 steps of our tutorial, you now have a multi-user calendar that allows end-users to easily book meeting rooms and arrange the events between rooms.
Referring back to the assigned requirements, you can see that each requirement has been fully implemented and it all took us about 30 minutes. The impressive result for such a complex application, huh? :)

The final package with all files and assets may be downloaded here.

scheduler-in-blog-dhtmlx

Comments

  1. Jens August 28, 2011 at 6:49 pm

    It seems to me that you skip over the infrastructure a bit.
    “In order not to create user infrastructure manually, we will use the ASP.NET Membership utility which comes in the standard package (you can find it in Windows.NET2.0.50727_regsql.exe). This utility will create a table and all necessary controllers and views in the DB. All we need is to add column ‘color’ to the table:”

    However Windows.NET2.0.50727_regsql.exe doesn’t seem to be readily available. Google’s only link is to this page.
    This page gives some hints, but after running aspnet_regsql.exe from the .NET 4 framework a get quite a bit more in my database, than the user table in your example. Furthermore the table aspnet_Users (not just User, as in your final code) has quite a few columns.
    Can you maybe update with a step by step guide to make the infrastructure and a link to the needed tools?

    Thanks
    Jens

    • ivan August 29, 2011 at 8:53 pm

      Jens, we’ve updated step 2, so hopefully this part will be more clear now.

  2. mark alphonso September 3, 2011 at 10:41 am

    this is a really good documentation here, very very helpful.
    but when room#1 is booked by one user can this be visible to other users….there also should have been how to stop recurring events

    • Stanislav September 5, 2011 at 3:36 pm

      Do you mean some kind of live update ?
      Currently it necessary to refresh page to see the updates. It possible to implement live update system over the existing solution – but it will increase complexity of the code a lot

  3. mark alphonso September 3, 2011 at 10:56 am

    i am very new to MVC so not able to cover up most of it
    suppose if i wanted to also integrate the day view for all the rooms then how should it be done

    • Stanislav September 5, 2011 at 3:37 pm

      Do you mean separate tabs for each room?

      It possible to use filtering api of scheduler and hide show events related to the different rooms based on some select-like control on the page.

  4. shantha September 27, 2011 at 9:45 am

    Hi
    I downloaded tis project working fine but need to fetch active directory users no need of asp.net membership tool how to fetch and how to validate those users and implement logic into this project can any one help me.

  5. Bao form VietNam October 23, 2011 at 12:57 pm

    Hi all
    Please Help Me.
    Now I can project for event calendar use vesion FrameWork 35. or slow
    If who have , can share for me email chibao2704@gmail.com
    I very thank you!!!
    Best Regards

  6. Dewayne Dodd October 28, 2011 at 8:41 pm

    I was wondering if the authentication that comes with a MVC3 project in Visual Studio could be used for this authentication? When you create a new MVC3 project in Visual Studio there is already a login screen and a registration screen already build in for you. This would be great is this could be used. Maybe a tutorial on how to use this would be in order

  7. Dewayne Dodd October 28, 2011 at 8:51 pm

    Also it looks like the example that you are using is using Webform Views. Could you use the new Razor engine that comes with MVC3?

  8. anil November 9, 2011 at 10:25 am

    nice code

  9. Yash November 16, 2011 at 4:06 am

    +1 for Razor. Please do at your earliest.

  10. hadi toraby December 14, 2011 at 4:16 pm

    hi
    i am php developer and unfortunately user of zkoss
    I discover your application recently for using instead of jquery UI and ZKoss
    but trying to translate Calenders to shamsi calender (persian) disappoint me
    even your arabic localization have serius bug in first day of year and week (your calendar is Cristian type)

    I have persian localization translate of dhtmlxScheduler & dhtmlxCalender but unused for this bug
    for solving this problem i need to membership or this bug resolve in next version

    • Stanislav December 15, 2011 at 1:01 pm

      If you have any correction to locale files – we will be glad to accept it.

  11. Eniyan December 15, 2011 at 9:46 am

    Hi,

    Your tutorial really useful and trying to achieve auto update, but not able to complete. Could you tell me how to enable auto update using the setAutoUpdate method.

    • Stanislav December 15, 2011 at 1:02 pm

      Stay tuned, we are working on separate article about scheduler in live-update mode.

  12. Booking Calendar User February 19, 2012 at 11:02 am

    Great post out there. Helpful information. Booking calendar really helps me and it really suits my needs.

  13. kpant July 13, 2012 at 11:53 am

    Hi, Thanks for the nice article.

    I downloaded this code and tried to run it.
    But I never manage to get the Event list after logging off the application.
    I logged in the application, created event and saved it. I was able to see the event appearing in all the different views like Month, week, room and agenda. But as soon as I logged off the event got disappeared.

    I tried yoto add following line in index.aspx

    scheduler.config.prevent_cache = true;

    But it did not solve my problem.. I tried in all browsers Mozila, chrome, IE8, IE9 but as soon as I logged off, event got disappeared. When I checked in the Event table in the database, the entries were not there for the events that I created.
    I debug the application and I came to know that when click on Save button in the Lightbox, the start_date and end_date value that we try to retreive in MyEvent.designer.cs are null, whereas all other fields from lightbox like text, roomid, userid has their respective values. SO I am not sure why start_date and end_date value are not being passed in the MyEvent.designer.cs.
    Due to this, the changedEvent’s start_date and end_date remains as null and “inserted” action result is not getting executed inthe Save View. So the events entry never getting saved in the database.

    Please help me in to resolve the issue.
    Regards,
    kpant

  14. moon October 23, 2012 at 12:28 pm

    I run this command aspnet_regsql.exe -E -S -d -A m but the tables are not added in the database.
    Will they be added automatically? please specify the step by step procedure . It is urgent.

  15. moon October 27, 2012 at 11:55 am

    it does display that membership feature is added and finish successfully but when i check the database in visual studio, it only has the events table ant not the tables you mentioned above.
    what should i do now?

    • Alexander October 29, 2012 at 12:07 pm

      Please note that tool works with the databases at the specified Sql Server. If you want to update database file(.mdf) you need to attach it to the server manually. Also, if you enter wrong database name tool won’t show any error or warning message – it will just create new database at the specified server instance. You may use Sql Server Management studio to see all existing databases

  16. moon November 2, 2012 at 4:59 pm

    i downloaded the package and logged on using “user” as username and password. when i created the event , it is not saved in the database.
    why is that so?

  17. Zhe Zhang April 9, 2013 at 6:23 am

    How can I make it both multi-resource weekly view? In each day of the week, there will be 5 columns for 5 rooms. For example,

    • Ivan April 9, 2013 at 2:27 pm

      Unfortunately, there is no a simple way to do it. You may check the sources of Unit View extension, and maybe try to modify the code for your needs, but this would be a complex customization.

  18. hasanein December 17, 2013 at 3:14 pm

    hello its smart project,but it’s not save any event,when i refresh the peg or logout and back it’s remove
    whole event

  19. Ryan A. May 14, 2014 at 12:47 pm

    Hello..nice project but the events did’nt save after refresh or log off. please help and fix.. thank you..

  20. Andy November 18, 2014 at 3:55 am

    Hi! Do you have MVC4 & above sample for this booking system? Thanks

  21. Ron Zaido March 17, 2016 at 6:02 am

    Is this open source?

  22. Maria (DHTMLX team) March 17, 2016 at 1:39 pm

    Hi Ron, Scheduler.Net isn’t Open source product. License details can be found here: http://scheduler-net.com/license.aspx If you want to use dhtmlxScheduler (JavaScript), then it’s availbale under GNU GPL v2: http://dhtmlx.com/docs/products/dhtmlxScheduler/#licenses

Leave a Reply