Tuesday, June 22, 2010

jQuery FullCalendar and ASP.NET

I needed to display a simple event calendar and looked around for the easiest path to the solution and found fullcalendar v1.4.6. The control is simple and elegant, but not very asp.net and expecially vb.net friendly. This is how you get it to work with a VB.NET webservice that can be used to pull from a database.

Update: v1.4.10 example can be found here.

Updated!  You can now download the example code here.
I am going to assume that you are able to create a basic asp.net website, add your own calendar page and put the fullcalendar control on the page.

First we will create a data class to return the results from the webservice.


Public Class CalendarDTO
Private m_id As Int32    
Public Property id() As Int32
Get
Return m_id
End Get
Set(ByVal value As Int32)
m_id = value
End Set
End Property

Private m_Title As String
Public Property title() As String
Get
Return m_Title
End Get
Set(ByVal value As String)
m_Title = value
End Set
End Property

Private m_Start As Int64
Public Property StartDate() As Int64
Get
Return m_Start
End Get
Set(ByVal value As Int64)
m_Start = value
End Set
End Property

Private m_End As Int64
Public Property EndDate() As Int64
Get
Return m_End
End Get
Set(ByVal value As Int64)
m_End = value
End Set
End Property

Private m_Url As String
Public Property url() As String
Get
Return m_Url
End Get
Set(ByVal value As String)
m_Url = value
End Set
End Property
End Class


The part of this code you need to take special note is EndDate and StartDate properties, we need to convert these to start and end in the fullcalendar.js file.

Next we will add the basic info to the webservice (once again I hope you can find enough examples to add a webservice on the web). Points to take note of are the startDate and endDate strings, these will be passed in as a unixTimespan and will look like a long integer, we will need to convert our dates from this format.


Public Function EventList(ByVal startDate As String, ByVal endDate As String) As String
Dim events As List(Of CalendarDTO) = New List(Of CalendarDTO)()
' Do Some SQL Here
Using con As New SqlConnection(conString)
Dim sqlCmd As SqlCommand = New SqlCommand("GetCalendarEvents", con)
sqlCmd.Parameters.Add(New SqlParameter("@startdate", Data.SqlDbType.DateTime))
sqlCmd.Parameters("@startdate").Value = FromUnixTimespan(startDate)
sqlCmd.Parameters.Add(New SqlParameter("@enddate", Data.SqlDbType.DateTime))
sqlCmd.Parameters("@enddate").Value = FromUnixTimespan(endDate)

con.Open()
Dim sdr As SqlDataReader = sqlCmd.ExecuteReader
While sdr.Read
Dim value As CalendarDTO = New CalendarDTO()
If Not IsDBNull(sdr("EndDate")) Then
value.EndDate = ToUnixTimespan(sdr("EndDate"))
End If
value.StartDate = ToUnixTimespan(sdr("StartDate"))
value.id = sdr("Event_ID")
value.title = sdr("title")
value.url = "http://url/"
events.Add(value)
End While
End Using

Dim js As New JavaScriptSerializer
Return js.Serialize(events)
End Function

Private Function ToUnixTimespan(ByVal d As DateTime) As Int64
Dim time As New TimeSpan()
time = d.ToUniversalTime().Subtract(New DateTime(1970, 1, 1, 0, 0, 0))
Return CType(Math.Truncate(time.TotalSeconds), Int64)
End Function

Private Function FromUnixTimespan(ByVal s As String) As DateTime
Dim time As DateTime = New DateTime(1970, 1, 1, 0, 0, 0)
Return time.AddSeconds(s)
End Function


Now to call the json formatted webservice we need to add "Calendar.asmx/EventList" to the events to be called by the calendar plugin.


<script type="text/javascript" language="javascript">
$(document).ready(function() {       
$('#calendar').fullCalendar({
header: {
left: 'prev,next,today',
center: 'title',
right: 'month,basicWeek,basicDay'
},
events: "Calendar.asmx/EventList"         
//events: [{title:'event1',start:'2010-06-01'},{title:'event2',start:'2010-06-05',end:'2010-06-07'}]                        
});         
});
</script>


Last we need to make the changes to make the fullcalendar.js file VB.NET friendly.
Line 25 (give or take)
Replace the following lines:

startParam: ‘start’,
endParam: ‘end’,

with

startParam:’startDate’,
endParam:’endDate’,

This will change the passed parameters to work with the webservice created above (call using startDate and endDate instead of start and end.
Next we need to change all the returned fields from the webservice calendarDTO class from startDate to start and endDate to end.
At line 442 in the ‘reportEventsAndPop = function(a) function you need to add:

reportEventsAndPop = function(a) {
if (a.d) {
var a = eval('(' + a.d.replace(/StartDate/g, 'start').replace (/EndDate/g, 'end') + ')');
}
reportEvents(a);
popLoading();
};

This will convert the json to an object and replace all the ‘StartDate’ and ‘EndDate’ fields with ‘start’ and ‘end’
For the ajax call to work using a asp.net webservice you need to add the type: ‘Post’ since GET is not allowed, You need to specifiy the content and data type and lastly you need to use the jasn2.js script to convert the params variable to a json string to pass into the webservice.
At line 448 replace the $.ajax call with the following:

$.ajax({
url: src,
type: 'POST',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
data: JSON.stringify(params),
cache: options.cacheParam false, // don't let jquery prevent caching if cacheParam is being used
success: reportEventsAndPop });


Take special note of the JSON.stringify(params), this uses the json2.js script availible from json.org. This is required to convert the passed parameters into a json formated string.

7 comments:

  1. hi Jake

    I tried your code and it seems that the events get freezed/undraggable. Have you observed this too? Is there any fix to that?

    Secondly, I would like to know if you have worked on any other way of fetching event data from database(using c#.net) other than webservices? I would appreciate if you can share with me anything of that sort.

    cheers
    mohit

    ReplyDelete
  2. thanks for the example, really useful. My web service is returning the json ok, but I am not getting any events on the calendar, any ideas why this might be happening, I have followed your example, but it not happening for me? Cheers Chris
    (lordy1981@gmail.com)

    ReplyDelete
  3. Jake have you had any luck with the latest flavor of "FullCalendar"? Was able to make it fly with jquery 1-4.4, but not the fullcalendar 1-4.10.

    Not positive but i think you could get away with not changing the start and end params and instead just throw brackets around the end param. So it would be [end]. Rather than changing the fullcalendar.js file.

    I tried this and was able to return the Json string but couldn't get it to populate the cal. Yet if I take the result and paste it directly into the events: as just the array it creates it works just fine but oddly not during runtime.

    anyway if you have any luck let me know.

    ReplyDelete
  4. I was not able to get [end] and [start] to work but I was able to get version 1-4.10 to work. I also cleaned up a couple parts so you now only need to modify the fullcalendar.js in two places to get it to work in asp.net (VB). I will post the findings and example later this week.

    ReplyDelete
  5. there is no need to change the variable names:
    Allthough End is a reserverd word use [End] and everything is ok!
    So Start en [End] makes the webservices running

    ReplyDelete
  6. Can anyone please provide a working sample of FullCalendar (2.3.1) with VB.NET?

    ReplyDelete
  7. Fantastic tutorial. Well i have one issue i.e. on document.ready, full calender binds all the event details including the start & end date, but not time (hh:mm) i.e the event is rendered in appropriate date slot as expected, but not in appropriate time slot
    Thanks in advance

    ReplyDelete