Features

  • Using DayPilot Pro for JavaScript in ASP.NET WebForms
  • Creating a JSON endpoint by overriding a standard Web Form page
  • Visual Studio 2017 solution (C#) available for download
  • Sample Microsoft SQL Server database (LocalDB)
  • Includes a trial version of DayPilot Pro for JavaScript (see also License below)

DayPilot Pro has a special edition for ASP.NET WebForms. The ASP.NET WebForms edition makes the event calendar available as a traditional ASP.NET control which handles the client-server communication transparently.

However, if you want more control over the client-side behavior you can use the pure client-side solution - DayPilot Pro for JavaScript. The JavaScript version doesn't include any server-side part and it communicates with the server using custom JSON endpoints that you need to create.

There are many ways to implement JSON endpoints in ASP.NET (WebMethods, WebAPI, WCF...). This tutorial uses a fallback solution that overrides a Web Forms page response and serializes the data manually using Json.NET library.

See also:

License

Licensed for testing and evaluation purposes. Please see the license agreement included in the sample project. You can use the source code of the tutorial if you are a licensed user of DayPilot Pro for JavaScript. Buy a license.

Json.NET Library

We will use Json.NET library for JSON serialization and deserialization. Add Newtonsoft.Json package to the Visual Studio project dependencies using NuGet console:

PM> Install-Package Newtonsoft.Json

package.json

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.7" targetFramework="net461" />
  <package id="Microsoft.Net.Compilers" version="2.1.0" targetFramework="net461" developmentDependency="true" />
  <package id="Newtonsoft.Json" version="11.0.2" targetFramework="net461" />
</packages>

JavaScript Calendar Configuration

In order to display the DayPilot JavaScript calendar in Default.aspx page we need to follow three steps:

  • Include daypilot-all.min.js JavaScript file
  • Add a placeholder <div>
  • Add the calendar initialization code (JavaScript)

This initialization code can look like this:

<script src="js/daypilot/daypilot-all.min.js"></script>

<div id="dp"></div>
    
<script>
    var dp = new DayPilot.Calendar("dp", {
      viewType: "Week"
    });
    dp.init();
</script>

This configuration will display an empty weekly calendar.

You can also use the online Calendar UI Builder to configure the JavaScript calendar component and download a ready-to-run HTML5/JavaScript project. 

This is the full source code the Default.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TutorialAspnetCalendarJson.Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Creating Calendar JSON Backend in ASP.NET (C#)</title>
</head>
<body>

<script src="js/daypilot/daypilot-all.min.js"></script>

<div id="dp"></div>
    
<script>
    var dp = new DayPilot.Calendar("dp", {
      viewType: "Week"
    });
    dp.init();
</script>

</body>
</html>

Simple JSON Endpoint for Loading Calendar Events

As the next step, we will add a code that loads calendar data from the server using an AJAX call. This can by done by simply adding events.load() call to the Default.aspx page:

<script>
    var dp = new DayPilot.Calendar("dp", {
      viewType: "Week"
    });
    dp.init();

    dp.events.load("JsonGetEvents.aspx");
</script>

This built-in method invokes an AJAX to the specified URL which should return the event data in JSON format.

Our first implementation of the JsonGetEvents.aspx JSON endpoint looks like this:

JsonGetEvents.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="GetEvents.aspx.cs" Inherits="TutorialAspnetCalendarJson.GetEvents" %>

The remaining content of JsonGetEvents.aspx can be deleted because we will override the response in the code behind.

JsonGetEvents.aspx.cs

using System;
using System.Collections.Generic;
using Newtonsoft.Json;

namespace TutorialAspnetCalendarJson
{
    public partial class GetEvents : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            List<Event> events = new List<Event>();

            events.Add(new Event
            {
                Start = DateTime.Parse("2018-04-03T12:00:00"),
                End = DateTime.Parse("2018-04-03T14:00:00"),
                Id = "1",
                Text = "Event 1"
            });

            string json = JsonConvert.SerializeObject(events);

            Response.Clear();
            Response.ContentType = "application/json";
            Response.Write(json);
            Response.End();

        }
    }


    public class Event
    {
        [JsonProperty("start")]
        public DateTime Start { get; set; }

        [JsonProperty("end")]
        public DateTime End { get; set; }

        [JsonProperty("id")]
        public string Id { get; set; }

        [JsonProperty("text")]
        public string Text { get; set; }
    }

}

This implementation returns the following JSON response:

[{"start":"2018-04-03T12:00:00","end":"2018-04-03T14:00:00","id":"1","text":"Event 1"}]

Loading Calendar Events from SQL Server Database

Now we will modify this endpoint to load the Calendar data from a SQL Server database.

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using Newtonsoft.Json;

namespace TutorialAspnetCalendarJson
{
    public partial class JsonGetEvents : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

            DateTime start = Convert.ToDateTime(Request.QueryString["start"]);
            DateTime end = Convert.ToDateTime(Request.QueryString["end"]);

            DataTable dt = GetData(start, end);

            List<Event> events = new List<Event>();

            foreach (DataRow dr in dt.Rows)
            {
                events.Add(new Event
                {
                    Start = (DateTime) dr["EventStart"],
                    End = (DateTime) dr["EventEnd"],
                    Id = (int) dr["Id"],
                    Text = (string) dr["Text"]
                });
            }

            string json = JsonConvert.SerializeObject(events);

            Response.Clear();
            Response.ContentType = "application/json";
            Response.Write(json);
            Response.End();

        }

        private DataTable GetData(DateTime start, DateTime end)
        {
            SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM [Event] WHERE NOT (([EventEnd] <= @start) OR ([EventStart] >= @end))", ConfigurationManager.ConnectionStrings["daypilot"].ConnectionString);
            da.SelectCommand.Parameters.AddWithValue("start", start);
            da.SelectCommand.Parameters.AddWithValue("end", end);

            DataTable dt = new DataTable();
            da.Fill(dt);

            return dt;
        }
    }


    public class Event
    {
        [JsonProperty("start")]
        public DateTime Start { get; set; }

        [JsonProperty("end")]
        public DateTime End { get; set; }

        [JsonProperty("id")]
        public int Id { get; set; }

        [JsonProperty("text")]
        public string Text { get; set; }
    }

}

We have moved the JSON serialization logic to a special helper class (JsonHelper):

using System.IO;
using System.Web;
using Newtonsoft.Json;

namespace TutorialAspnetCalendarJson
{
    public class JsonHelper
    {
        public static void WriteResponse(HttpResponse response, object target)
        {
            string json = JsonConvert.SerializeObject(target);

            response.Clear();
            response.ContentType = "application/json";
            response.Write(json);
            response.End();
        }
    }
}

POST Endpoint for Creating New Calendar Events

We can use this approach for all other JSON endpoints as well. As the next step, we will add a handler for onTimeRangeSelected event handler which is fired when the user selects a time range. The event handler opens a modal dialog and ask the user to enter new event details. When the event details are confirmed it calls JsonCreateEvent.aspx endpoint using DayPilot.Http.ajax() method to save the new event in the database.

Default.aspx

<script>
    var dp = new DayPilot.Calendar("dp", {
        viewType: "Week",
        timeRangeSelectedHandling: "Enabled",
        onTimeRangeSelected: function (args) {
            DayPilot.Modal.prompt("Create a new event:", "Event 1").then(function (modal) {

                dp.clearSelection();

                if (!modal.result) {
                    return;
                }

                var params = {
                    start: args.start,
                    end: args.end,
                    text: modal.result
                };

                DayPilot.Http.ajax({
                    url: "JsonCreateEvent.aspx",
                    method: "POST",
                    data: params,
                    success: function (ajaxArgs) {
                        dp.events.add(new DayPilot.Event({
                            start: args.start,
                            end: args.end,
                            text: modal.result,
                            id: ajaxArgs.data.id
                        }));
                        dp.message(ajaxArgs.data.message);
                    }
                });

            });
        },

        // ...
    });
    dp.init();

    dp.events.load("JsonGetEvents.aspx");

</script>

This time the HTTP request contains data (the new event details) in the request body. On the server side, we need to read it and update the database.

First, we will extend our JsonHelper with ReadRequest<T>(HttpRequest request) method for reading JSON from request body:

using System.IO;
using System.Web;
using Newtonsoft.Json;

namespace TutorialAspnetCalendarJson
{
    public class JsonHelper
    {

        // ...

        public static T ReadRequest<T>(HttpRequest request)
        {
            string body;
            request.InputStream.Seek(0, SeekOrigin.Begin);
            using (StreamReader reader = new StreamReader(request.InputStream))
            {
                body = reader.ReadToEnd();
            }
            T obj = JsonConvert.DeserializeObject<T>(body);

            return obj;
        }

    }
}

Now we can use this method in Page_Load to read the new event parameters.

JsonCreateEvent.aspx.cs

using System;
using System.Configuration;
using System.Data.SqlClient;
using Newtonsoft.Json;

namespace TutorialAspnetCalendarJson
{
    public partial class JsonCreateEvent : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {            
            CreateEventParams createparams = JsonHelper.ReadRequest<CreateEventParams>(Request);

            int id = DbCreateEvent(createparams.Start, createparams.End, createparams.Text);

            CreateEventResponse response = new CreateEventResponse
            {
                Id = id,
                Message = "Event created"
            };

            JsonHelper.WriteResponse(Response, response);
        }


        private int DbCreateEvent(DateTime start, DateTime end, string text)
        {
            using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["daypilot"].ConnectionString))
            {
                con.Open();
                SqlCommand cmd = new SqlCommand("INSERT INTO [Event] (EventStart, EventEnd, Text) VALUES(@start, @end, @text)", con);
                cmd.Parameters.AddWithValue("start", start);
                cmd.Parameters.AddWithValue("end", end);
                cmd.Parameters.AddWithValue("text", text);
                cmd.ExecuteNonQuery();

                cmd = new SqlCommand("select @@identity;", con);
                int id = Convert.ToInt32(cmd.ExecuteScalar());
                return id;
            }
        }


        public class CreateEventParams
        {
            [JsonProperty("text")]
            public string Text { get; set; }

            [JsonProperty("start")]
            public DateTime Start { get; set; }

            [JsonProperty("end")]
            public DateTime End { get; set; }
        }


        public class CreateEventResponse
        {
            [JsonProperty("id")]
            public int Id { get; set; }

            [JsonProperty("message")]
            public string Message { get; set; }

        }

    }

}

SQL Server Database Schema

This example includes a sample SQL Server database (App_Data/DayPilot.mdf) with the following schema:

CREATE TABLE [dbo].Event
(
    [Id] INT NOT NULL PRIMARY KEY IDENTITY, 
    [EventStart] DATETIME NULL, 
    [EventEnd] DATETIME NULL, 
    [Text] NCHAR(10) NULL
)