Introduction

As you know, in the professional world, we have to do many things such as meetings, business trips, and training sessions. Therefore all that must be organized by using a calendar.

In this article, we will demonstrate how we can use a Full Calendar plugin based on ASP.Net Web API (Back-end) and AngularJS (Front-end). Here what we are doing exactly is to customize the FullCalendar plugin in order to be able to perform CRUD operations. I'd like to remind you that you should have some basic knowledge of Web API and AngularJS. I hope you will like it.

Prerequisites

Make sure you have installed Visual Studio 2017 (.NET Framework 4.6.1) and SQL Server.

In this post, we are going to:

SQL Database part

Here, you will find the script to create database and table.

Create Database

  1. USE [master]
  2. GO
  3. /****** Object: Database [CalendarDB] Script Date: 1/24/2018 9:11:39 PM ******/
  4. CREATE DATABASE [CalendarDB]
  5. CONTAINMENT = NONE
  6. ON PRIMARY
  7. ( NAME = N'CalendarDB', FILENAME = N'c:\Program Files (x86)\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\CalendarDB.mdf' , SIZE = 4096KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
  8. LOG ON
  9. ( NAME = N'CalendarDB_log', FILENAME = N'c:\Program Files (x86)\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\CalendarDB_log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
  10. GO
  11. ALTER DATABASE [CalendarDB] SET COMPATIBILITY_LEVEL = 110
  12. GO
  13. IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled'))
  14. begin
  15. EXEC [CalendarDB].[dbo].[sp_fulltext_database] @action = 'enable'
  16. end
  17. GO
  18. ALTER DATABASE [CalendarDB] SET ANSI_NULL_DEFAULT OFF
  19. GO
  20. ALTER DATABASE [CalendarDB] SET ANSI_NULLS OFF
  21. GO
  22. ALTER DATABASE [CalendarDB] SET ANSI_PADDING OFF
  23. GO
  24. ALTER DATABASE [CalendarDB] SET ANSI_WARNINGS OFF
  25. GO
  26. ALTER DATABASE [CalendarDB] SET ARITHABORT OFF
  27. GO
  28. ALTER DATABASE [CalendarDB] SET AUTO_CLOSE OFF
  29. GO
  30. ALTER DATABASE [CalendarDB] SET AUTO_CREATE_STATISTICS ON
  31. GO
  32. ALTER DATABASE [CalendarDB] SET AUTO_SHRINK OFF
  33. GO
  34. ALTER DATABASE [CalendarDB] SET AUTO_UPDATE_STATISTICS ON
  35. GO
  36. ALTER DATABASE [CalendarDB] SET CURSOR_CLOSE_ON_COMMIT OFF
  37. GO
  38. ALTER DATABASE [CalendarDB] SET CURSOR_DEFAULT GLOBAL
  39. GO
  40. ALTER DATABASE [CalendarDB] SET CONCAT_NULL_YIELDS_NULL OFF
  41. GO
  42. ALTER DATABASE [CalendarDB] SET NUMERIC_ROUNDABORT OFF
  43. GO
  44. ALTER DATABASE [CalendarDB] SET QUOTED_IDENTIFIER OFF
  45. GO
  46. ALTER DATABASE [CalendarDB] SET RECURSIVE_TRIGGERS OFF
  47. GO
  48. ALTER DATABASE [CalendarDB] SET DISABLE_BROKER
  49. GO
  50. ALTER DATABASE [CalendarDB] SET AUTO_UPDATE_STATISTICS_ASYNC OFF
  51. GO
  52. ALTER DATABASE [CalendarDB] SET DATE_CORRELATION_OPTIMIZATION OFF
  53. GO
  54. ALTER DATABASE [CalendarDB] SET TRUSTWORTHY OFF
  55. GO
  56. ALTER DATABASE [CalendarDB] SET ALLOW_SNAPSHOT_ISOLATION OFF
  57. GO
  58. ALTER DATABASE [CalendarDB] SET PARAMETERIZATION SIMPLE
  59. GO
  60. ALTER DATABASE [CalendarDB] SET READ_COMMITTED_SNAPSHOT OFF
  61. GO
  62. ALTER DATABASE [CalendarDB] SET HONOR_BROKER_PRIORITY OFF
  63. GO
  64. ALTER DATABASE [CalendarDB] SET RECOVERY SIMPLE
  65. GO
  66. ALTER DATABASE [CalendarDB] SET MULTI_USER
  67. GO
  68. ALTER DATABASE [CalendarDB] SET PAGE_VERIFY CHECKSUM
  69. GO
  70. ALTER DATABASE [CalendarDB] SET DB_CHAINING OFF
  71. GO
  72. ALTER DATABASE [CalendarDB] SET FILESTREAM( NON_TRANSACTED_ACCESS = OFF )
  73. GO
  74. ALTER DATABASE [CalendarDB] SET TARGET_RECOVERY_TIME = 0 SECONDS
  75. GO
  76. ALTER DATABASE [CalendarDB] SET READ_WRITE
  77. GO

Create Table

After creating database, we will move to create events table.

Events Table

  1. USE [CalendarDB]
  2. GO
  3. /****** Object: Table [dbo].[Events] Script Date: 1/24/2018 9:12:14 PM ******/
  4. SET ANSI_NULLS ON
  5. GO
  6. SET QUOTED_IDENTIFIER ON
  7. GO
  8. SET ANSI_PADDING ON
  9. GO
  10. CREATE TABLE [dbo].[Events](
  11. [EventID] [int] IDENTITY(1,1) NOT NULL,
  12. [EventTitle] [varchar](50) NULL,
  13. [EventDescription] [varchar](50) NULL,
  14. [StartDate] [datetime] NULL,
  15. [EndDate] [datetime] NULL,
  16. CONSTRAINT [PK_Events] PRIMARY KEY CLUSTERED
  17. (
  18. [EventID] ASC
  19. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  20. ) ON [PRIMARY]
  21. GO
  22. SET ANSI_PADDING OFF
  23. GO

Create your MVC application

Open Visual Studio and select File >> New Project.

The "New Project" window will pop up. Select ASP.NET Web Application (.NET Framework), name your project, and click OK.

ASP.NET

Next, a new dialog will pop up for selecting the template. We are going choose Web API template and click Ok.

ASP.NET

Once our project is created, we will add ADO.NET Entity Data Model.

Adding ADO.NET Entity Data Model

From solution explorer, right click on the project name, click Add >> Add New Item.

A dialog box will pop up, inside Visual C#, select Data then ADO.NET Entity Data Model, and enter the name for your DbContext model as CalendarDB, then click Add.

ASP.NET

As you can see, we have 4 model contents, we are selecting the first approach (EF Designer from a database).

ASP.NET

In the next step, we need to select server name, then via drop-down list in connect to a database section. You must choose your database name and finally click OK.

ASP.NET

After that, Entity Data Model Wizard dialog will pop up for choosing objects which will be used in our application. We are selecting the events table then click finish.

Finally, we see that EDMX model generates events table as an object as shown below.

ASP.NET

ASP.NET
Create a controller

Now, we are going to create a controller. Right-click on the controllers folder> > Add >> Controller>> selecting Web API 2 Controller – Empty >> click Add. In the next dialog, name the controller as CalendarController and then click Add.

ASP.NET

ASP.NET

CalendarController.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Net.Http;
  6. using System.Web.Http;
  7. namespace DemoCalendarWebAPI.Controllers
  8. {
  9. [RoutePrefix("api/Calendar")]
  10. public class CalendarController : ApiController
  11. {
  12. /// <summary>
  13. /// Gets all events from Events table
  14. /// </summary>
  15. /// <returns></returns>
  16. ///
  17. //[HttpGet]
  18. [Route("GetEvents")]
  19. public IHttpActionResult GetEvents()
  20. {
  21. using (CalendarDBEntities1 context = new CalendarDBEntities1())
  22. {
  23. var eventsList = context.Events.ToList();
  24. return Ok(eventsList);
  25. }
  26. }
  27. /// <summary>
  28. /// Save or update event.
  29. /// </summary>
  30. /// <param name="eventObject"></param>
  31. /// <returns></returns>
  32. ///
  33. //[HttpPost]
  34. [Route("PostSaveOrUpdate")]
  35. public IHttpActionResult PostSaveOrUpdate(Event NewEvent)
  36. {
  37. using (CalendarDBEntities1 context = new CalendarDBEntities1())
  38. {
  39. if(!ModelState.IsValid)
  40. {
  41. return BadRequest();
  42. }
  43. var eventObj = context.Events.FirstOrDefault(e => e.EventID == NewEvent.EventID);
  44. if(eventObj != null)
  45. {
  46. eventObj.EventTitle = NewEvent.EventTitle;
  47. eventObj.EventDescription = NewEvent.EventDescription;
  48. eventObj.StartDate = NewEvent.StartDate;
  49. eventObj.EndDate = NewEvent.EndDate;
  50. }
  51. else
  52. {
  53. context.Events.Add(NewEvent);
  54. }
  55. context.SaveChanges();
  56. return Ok();
  57. }
  58. }
  59. /// <summary>
  60. /// Delete an event based on the given id.
  61. /// </summary>
  62. /// <param name="eventId"></param>
  63. /// <returns></returns>
  64. ///
  65. //[HttpDelete]
  66. [Route("DeleteEvent/{eventId:int}")]
  67. public IHttpActionResult DeleteEvent(int EventID)
  68. {
  69. using (CalendarDBEntities1 context = new CalendarDBEntities1())
  70. {
  71. Event eventObj = context.Events.FirstOrDefault(e=>e.EventID == EventID);
  72. if(eventObj == null)
  73. {
  74. return NotFound();
  75. }
  76. context.Events.Remove(eventObj);
  77. context.SaveChanges();
  78. return Ok(eventObj);
  79. }
  80. }
  81. }
  82. }

As I mentioned previously, we are using Web API to create all the necessary methods which will be called from the browser.

Now, it's time to define all the methods to perform CRUD operations.

Let's begin with GetEvents() which is responsible to get all the events from the database. This method is decorated as you can see by [Route("GetEvents")] attribute that means if you would call this method, you should proceed as follows: api/Calendar/GetEvents.

Next, we have PostSaveOrUpdate() method which is used to add a new event or update it.

Here, the code snippet implemented is very simple. When we receive event object from HTTP request, we will search it based on EventId. If it already exists in the database that means the operation which will be performed is an update, otherwise we will add it to events table.

One thing that I’d clarify, [Route("PostSaveOrUpdate")] attribute explains we should call the method as follows : /api/Calendar/PostSaveOrUpdate.

Finally, the DeleteEvent method accepts EventId as a parameter and is used to delete an event based on the given EventId parameter. Let’s describe the code snippet of DeleteEvent method,

  1. Search an event based on the EventId parameter. To accomplish that, we used FirstOrDefault() extension method.
  2. If the eventObj object is NULL, we will return NotFound() translated by 404 as status code result, otherwise, we will proceed to delete the returned object by using remove() extension method and finally, we will return OK() which is translated as 200 status code result.

AngularJS Part

Add JavaScript File

In solution explorer, right-click the project name, Add >> JavaScript File.

App.js

  1. var app = angular.module('App', ['ui.calendar', 'ui.bootstrap']);
  2. app.controller('CalendarController', ['$scope', '$http', 'uiCalendarConfig', '$uibModal', function ($scope, $http, uiCalendarConfig, $uibModal) {
  3. $scope.eventsTab = [];
  4. $scope.events = [$scope.eventsTab];
  5. $scope.EventObj = {};
  6. //Clear calendar
  7. function clearCalendar() {
  8. if (uiCalendarConfig.calendars.Calendar != null) {
  9. uiCalendarConfig.calendars.Calendar.fullCalendar('removeEvents');
  10. }
  11. }
  12. //Gets all events from db
  13. function GetEvents() {
  14. clearCalendar();
  15. $http.get('/api/Calendar/GetEvents', {
  16. cache: false,
  17. params: {},
  18. }).then(function (response) {
  19. angular.forEach(response.data, function (value) {
  20. $scope.eventsTab.push({
  21. id: value.EventID,
  22. title: value.EventTitle,
  23. description: value.EventDescription,
  24. start: new Date(parseInt(value.StartDate.substr(6))),
  25. end: new Date(parseInt(value.EndDate.substr(6))),
  26. backgroundColor: "#f9a712",
  27. borderColor: "#8e8574"
  28. });
  29. console.log($scope.eventsTab);
  30. });
  31. });
  32. }
  33. GetEvents();
  34. //Configure Calendar
  35. $scope.uiConfig = {
  36. calendar: {
  37. height: 450,
  38. editable: true,
  39. displayEventTime: true,
  40. header: {
  41. left: 'prev,next today',
  42. center: 'title',
  43. right: 'month,agendaWeek,agendaDay'
  44. },
  45. selectable: true,
  46. select: function (start, end) {
  47. var startDate = moment(start).format('YYYY/MM/DD');
  48. var endDate = moment(end).format('YYYY/MM/DD');
  49. $scope.EventObj = {
  50. EventID: 0,
  51. EventTitle: '',
  52. EventDescription: '',
  53. StartDate: startDate,
  54. EndDate: endDate
  55. };
  56. $scope.ShowModal();
  57. },
  58. eventClick: function (event) {
  59. var startDate = moment(event.start).format('YYYY/MM/DD');
  60. var endDate = moment(event.end).format('YYYY/MM/DD');
  61. $scope.EventObj = {
  62. EventID: event.id,
  63. EventTitle: event.title,
  64. EventDescription: event.description,
  65. StartDate: startDate,
  66. EndDate: endDate
  67. };
  68. $scope.ShowModal();
  69. }
  70. }
  71. };
  72. // Popup modal
  73. $scope.ShowModal = function () {
  74. var modalInstance = $uibModal.open({
  75. templateUrl: 'modalPopUp.html',
  76. controller: 'modalCtrl',
  77. backdrop: 'static',
  78. resolve: {
  79. EventObj: function () {
  80. return $scope.EventObj;
  81. }
  82. }
  83. });
  84. modalInstance.result.then(function (result) {
  85. switch (result.operation) {
  86. case 'AddOrUpdate':
  87. $http({
  88. method: 'POST',
  89. url: '/api/Calendar/PostSaveOrUpdate',
  90. data: $scope.EventObj
  91. }).then(function (response) {
  92. console.log("Added ^_^");
  93. GetEvents();
  94. }, function errorRollBak() {
  95. console.log("Something Wrong !!");
  96. });
  97. break;
  98. case 'Delete':
  99. $http({
  100. method: 'DELETE',
  101. url: '/api/Calendar/DeleteEvent/' + $scope.EventObj.EventID
  102. }).then(function (response) {
  103. GetEvents();
  104. }, function errorRollBack() {
  105. console.log("Something Wrong !!");
  106. });
  107. break;
  108. default:
  109. break;
  110. }
  111. }, function () {
  112. $log.info('modal-component dismissed at: ' + new Date());
  113. })
  114. }
  115. }])
  116. //modalCtrl controller will be used to perform CRUD Operation.
  117. app.controller('modalCtrl', ['$scope', '$uibModalInstance', 'EventObj', function ($scope, $uibModalInstance, EventObj) {
  118. $scope.EventObj = EventObj;
  119. $scope.AddOrUpdateEvent = function () {
  120. $uibModalInstance.close({ event: $scope.EventObj, operation: 'AddOrUpdate' });
  121. }
  122. $scope.DeleteEvent = function () {
  123. $uibModalInstance.close({ event: $scope.EventObj, operation: 'Delete' });
  124. }
  125. $scope.CancelEvent = function () {
  126. $uibModalInstance.dismiss('cancel');
  127. }
  128. }])

Let's explain how to configure our calendar.

As you can see above, to configure calendar, we need to provide so many properties such as:

which will be shown at top of the calendar.

selectable or not.

Finally, Show modal function is used to perform CRUD operations.

Add HTML page

To add html page, right click the project name >> Add >> HTML page

Calendar.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8" />
  5. <title>.: Demo Calendar :.</title>
  6. <!-- CSS -->
  7. <link href="Content/bootstrap.min.css" rel="stylesheet" />
  8. <link href="Content/fullcalendar.css" rel="stylesheet" />
  9. </head>
  10. <body>
  11. <div ng-app="App" ng-controller="CalendarController">
  12. <script type="text/ng-template" id="modalPopUp.html">
  13. <div class="modal-header">
  14. <h3 class="modal-title"> CUD Events </h3>
  15. </div>
  16. <div class="modal-body">
  17. <div class="form-group">
  18. <label>Event Title : </label>
  19. <input type="text" ng-model="EventObj.EventTitle" class="form-control" />
  20. </div>
  21. <div class="form-group">
  22. <label>Description : </label>
  23. <input type="text" ng-model="EventObj.EventDescription" class="form-control" />
  24. </div>
  25. <div class="form-group">
  26. <label>Date (Start - END) : </label>
  27. <span>{{EventObj.StartDate}} - {{EventObj.EndDate}}</span>
  28. </div>
  29. </div>
  30. <div class="modal-footer">
  31. <button class="btn btn-primary" type="button" ng-click="AddOrUpdateEvent()">Add Or Update Event</button>
  32. <button class="btn btn-success" type="button" ng-show="EventObj.EventID > 0" ng-click="DeleteEvent()">Delete Event</button>
  33. <button class="btn btn-info" type="button" ng-click="CancelEvent()">Cancel Event</button>
  34. </div>
  35. </script>
  36. <div class="CalenderClass">
  37. <div class="row">
  38. <div class="col-md-12">
  39. <div ui-calendar="uiConfig.calendar" class="calendar" ng-model="events" calendar="Calendar"></div>
  40. </div>
  41. </div>
  42. </div>
  43. </div>
  44. <!-- JS -->
  45. <script src="Scripts/moment.js"></script>
  46. <script src="Scripts/jquery-1.10.2.min.js"></script>
  47. <script src="Scripts/bootstrap.js"></script>
  48. <script src="Scripts/angular.js"></script>
  49. <script src="Scripts/calendar.js"></script>
  50. <script src="Scripts/fullcalendar.js"></script>
  51. <script src="Scripts/gcal.js"></script>
  52. <script src="Scripts/ui-bootstrap-tpls.min.js"></script>
  53. <script src="Scripts/App.js"></script>
  54. </body>
  55. </html>

Note

Do not forget to add the following libraries within Calendar.html page.

  1. <!-- JS -->
  2. <script src="Scripts/moment.js"></script>
  3. <script src="Scripts/jquery-1.10.2.min.js"></script>
  4. <script src="Scripts/bootstrap.js"></script>
  5. <script src="Scripts/angular.js"></script>
  6. <script src="Scripts/calendar.js"></script>
  7. <script src="Scripts/fullcalendar.js"></script>
  8. <script src="Scripts/gcal.js"></script>
  9. <script src="Scripts/ui-bootstrap-tpls.min.js"></script>
  10. <script src="Scripts/App.js"></script>

You can download them from Here

Demo

Now, our Calendar application is ready. We can run and see the output in the browser.

ASP.NET

ASP.NET

That’s all. Please send your feedback and queries in the comments box.