WdCalendar JSON Feed Via ASP.Net WCF Service

wdCalendar is a jQuery based Google calendar clone. It is free, easy to use, and has great features. This article covers a way you can provide a JSON feed using a WCF Service.

wdCalendar is a jQuery based Google calendar clone. It is open source and easy to use.

You can find a wdCalendar demo at http://www.web-delicious.com/jquery-plugins-demo/wdCalendar/sample.php.

If you download and look into the sample application then you can find a datafeed.php file, that is actually responsible for generating the appropriate JSON needed for a calendar to be funtional.

So this article is all about creating a JSON based WCF Service in an ASP.NET Website, that can be used for providing the events data feed.

So Let's get started.

JSON object Structure 

{

     "events": [

         [

             16076,

             "project plan review",

             "07/27/2013 13:34",

             "12/31/1969 19:22",

             1,

             0,

             0,

             10,

             1,

             null,

             ""

         ],

         [

             42906,

             "project plan review",

             "07/22/2013 14:06",

             "12/31/1969 19:49",

             0,

             0,

             0,

             4,

             1,

             null,

             ""

         ]

     ],

     "issort": true,

     "start": "07/22/2013 00:00",

     "end": "07/28/2013 23:59",

     "error": null

 }


 
Create an ASP.NET Web Application

A. Add a AJAX Enabled WCF Service
       
I have named it "CalService.svc". The following is the code behind file "CalService.cs":

[ServiceContract(Namespace = "")]

    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]

    public class CalService

    {

        [OperationContract]

        [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]

        public CalendarData GetCalData()

    {

        WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");....}

        [DataContract]

        public class CalendarData

        {

            [DataMember(Order = 1)]

            public List<ArrayList> events { get; set; }

 

            [DataMember(Order = 2)]

            public bool issort { get; set; }

            [DataMember(Order = 3)]

            public string start { get; set; }

            [DataMember(Order = 4)]

            public string end { get; set; }

            [DataMember(Order = 5)]

 

            public string error { get; set; }

        }

    }

Here you can see we are exposing CalendarData using the GetCalData Method.

  1. CalendarData Class is resembles the required JSON structure.

  2. Notice the WebInvoke Method:

    [WebInvoke(Method = "POST",BodyStyle = WebMessageBodyStyle.Bare,ResponseFormat = WebMessageFormat.Json)]
     
    This is required to enable the calendar's script to fire an ajax post to the the server. So we have granted here a POST method and used the JSON format instead of XML as a response.
     

  3. Header to append (to allow cross-domains requests):

    WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");

    B. Event Class
     

    public class Event

    {

        public int Id { get;set; }

        public string Subject { get; set; }

        public string StartDate { get; set; }

        public string EndDate { get; set; }

        public int IsAllDayEvent { get; set; }

        public int IsMoreThanOneDayEvent {get; set; }

        public int RecurringEvent {get; set; }

        public int Color { get;set; }     public int IsEditable { get; set; }

        public string Location { get; set; }

        public string Attendents { get; set; }


    Here I have just wrapped the calendar events into the Event Class.

    Note: I used the string and not DateTime in StartDate and EndDate because the .NET DataContractSerializer converts a DateTime to Microsoft JavaScript date format that wdCalendar is not able to understand, so I am using a workaround and used the following static class to convert a DateTime into a JSDateTime string.

    C. JSDateTime to convert DateTime into JSDate String:

     

    public static class JSDateTime

    {

        public static string ToStr(DateTime dateTime)

        {

            return dateTime.ToString(@"MM\/dd\/yyyy HH:mm");

        }

    }

     
    D. One more limitation is that we need Events in the form of an array and not as a name/value pair. So I have converted the Event Object into the ArrayList using Reflection to iterate the properties and adding the values to the ArrayList.
     

    public ArrayList ConvertToArrayList<T>(T obj)

    {

        ArrayList ls = new ArrayList();

        PropertyInfo[] p = obj.GetType().GetProperties();

        foreach (var item in p)

        {

            ls.Add(item.GetValue(obj,null));

        }

        return ls;

    }

     
    Now Summing all

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Runtime.Serialization;

    using System.ServiceModel;

    using System.ServiceModel.Activation;

    using System.ServiceModel.Web;

    using System.Text;

    using System.Collections;

    using System.Reflection;

     

    [ServiceContract(Namespace = "")]

    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]

    public class CalService

    {

        [OperationContract]

        // [WebGet(ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]

        [WebInvoke(Method = "POST", BodyStyle =WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]

       public CalendarData GetCalData()

        {

           WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin","*");

     

           List<Event> _events = new List<Event>()

            {

                    new Event(){Id = 1,

                     Subject = "Test",

                     StartDate = JSDateTime.ToStr(DateTime.Now.Date),

                     EndDate =  JSDateTime.ToStr(DateTime.Now.Date.AddHours(11)),

                     IsAllDayEvent = 1,

                     IsEditable = 0,

                     IsMoreThanOneDayEvent =0,

                     Attendents ="",

                     Location="Noida",

                     RecurringEvent = 0,

                     Color = 2},

                     new Event(){Id = 2,

                     Subject = "More Test",

                     StartDate =  JSDateTime.ToStr(DateTime.Now.Date.AddDays(1)),

                     EndDate =  JSDateTime.ToStr(DateTime.Now.Date.AddHours(45)),

                     IsAllDayEvent = 1,

                     IsEditable = 0,

                     IsMoreThanOneDayEvent =0,

                     Attendents ="",

                     Location="Delhi",

                     RecurringEvent = 0,

                     Color = 4}

            };

           CalendarData objCalData =new CalendarData();

            objCalData.events = new List<ArrayList>();

           foreach (var item in _events)

            {

                objCalData.events.Add(ConvertToArrayList<Event>(item));

            }

     

            objCalData.issort = true;

            objCalData.start = JSDateTime.ToStr(new DateTime(2013, 7, 1));

            objCalData.end =JSDateTime.ToStr(new DateTime(2013, 7, 31));

            objCalData.error = null;

           return objCalData;

        }

        [DataContract]

       public class CalendarData

        {

            [DataMember(Order = 1)]

           public List<ArrayList> events { get; set; }

            [DataMember(Order = 2)]

           public bool issort { get; set; }

            [DataMember(Order = 3)]

           public string start { get; set; }

            [DataMember(Order = 4)]

           public string end { get; set; }

            [DataMember(Order = 5)]

           public string error { get; set; }

        }

        // Use a data contract as illustrated in the sample below to add composite types to service operations.

      

       public static class JSDateTime

        {

           public static string ToStr(DateTime dateTime)

            {

               return dateTime.ToString(@"MM\/dd\/yyyy HH:mm");

            }

        }

     

       public class Event

        {

           public int Id { get; set; }

           public string Subject { get; set; }

           public string StartDate { get; set; }

           public string EndDate { get; set; }

           public int IsAllDayEvent { get;set; }

           public int IsMoreThanOneDayEvent { get;set; }

           public int RecurringEvent { get;set; }

           public int Color { get; set; }

           public int IsEditable { get; set; }

           public string Location { get; set; }

           public string Attendents { get; set; }

        }

     

       public ArrayList ConvertToArrayList<T>(T obj)

        {

           ArrayList ls = new ArrayList();

           PropertyInfo[] p = obj.GetType().GetProperties();

           foreach (var item in p)

            {

                ls.Add(item.GetValue(obj, null));

            }

           return ls;

        }

    }

     
    E. Web.Config Configuration

    replace <enableWebScript/> with <webHttp />

    <system.serviceModel>

          <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />

          <services>

              <service name="CalService">

                  <endpoint address="" behaviorConfiguration="CalServiceAspNetAjaxBehavior"

              ="" binding="webHttpBinding" contract="CalService" />           

        </service>        

      </services>

          <behaviors>

              <endpointBehaviors>

                  <behavior name="CalServiceAspNetAjaxBehavior">

                      <webHttp />                

          </behavior>            

        </endpointBehaviors>        

      </behaviors>    

    </system.serviceModel> 

    Client Side: Modification in wdCalendar script
     

    $(document).ready(function () {

    var view = "week";

    var DATA_FEED_URL = "CalService.svc"; // Modified the feed URL

    var op = {

               view: view,

               theme: 3,

               showday:new Date(),

               EditCmdhandler: Edit,

               DeleteCmdhandler: Delete,

               ViewCmdhandler: View,

               onWeekOrMonthToDay: wtd,

               onBeforeRequestData: cal_beforerequest,

               onAfterRequestData: cal_afterrequest,

               onRequestDataError: cal_onerror,

               autoload:true,

               url: DATA_FEED_URL + "/GetCalData"

               // Modfied the method

              // quickAddUrl: DATA_FEED_URL + "?method=add",

             // quickUpdateUrl: DATA_FEED_URL + "?method=update",

            // quickDeleteUrl: DATA_FEED_URL + "?method=remov
        
    };

     

So that is how you can create your own custom service and provide the data source feed and operate all the functions, like view, edit, delete and insert events in wdCalendar with extensins of this method.

You can download and run my working source code (zipped and attached with this article).