Bad "Add this Event to your Calendar" link

Topics: Developer Discussion, Help, Request
May 8, 2007 at 9:02 PM
Hi all,

When I am on the view.aspx page and click on the "Add this event to your personal calendar" link and Open the downloaded ICalendar File, "download.ics", I get something the following:

<p>test</p>

Event URL: http://www.host.com/club/events/view.aspx?Eventid

The event URL is highlighted in MS Outlook and when I click on it, it brings up the following page:

http://www.host.com/club/events/view.aspx?Eventid%18

The Event page is then blank because the Eventid has percent between "Eventid" and "18" it should be,
http://www.host.com/club/events/view.aspx?Eventid=18

I have scoured through the Events/download.ashx, Events/view.aspx and Events/edit.aspx code and can't find the problem...

If I change the "%" to and "=" sign in IE7 Address bar, it displays the correct page.

Does anyone else experience this problem? Any help would be appreciated.

Thanks.
May 9, 2007 at 2:18 PM
Edited May 11, 2007 at 3:08 PM
Here is another interesting tidbit. If I download the file instead of opening it with outlook and open it with notepad, the links look like they were built just fine:

BEGIN:VCALENDAR
VERSION:2.0
PRODID:http://www.host.com/club/events/view.aspx?Eventid=17
METHOD:PUBLISH
BEGIN:VEVENT
UID:0fb288e9-4574-40f1-95f9-ca2bee28ded6
DTSTAMP:20070509T131134Z
CATEGORIES:APPOINTMENT;PERSONAL
DESCRIPTION;ENCODING=QUOTED-PRINTABLE:<p>Hi all,</p>=0D=0A<p>This is the title=
of the event.</p>==
0D=0A=0D=0AEvent URL: http://www.host.com/club/events/view.a=
spx?Eventid=17=0D=0A=0D=0AEvent location: Here=0D=0A=0D=0ALoca=
tion description:=0D=0A<p>this is a location.</p>=0D=0A=0D=0ALocati=
on Address:=0D=0ASomewhere=0D=0A
DTEND:20070507T190000Z
LOCATION;ENCODING=QUOTED-PRINTABLE:This is a location
PRIORITY:0
DTSTART:20070507T185000Z
STATUS:NEEDS ACTION
SUMMARY;ENCODING=QUOTED-PRINTABLE:This is the notes
URL:http://www.host.com/club/events/view.aspx?Eventid=17
END:VEVENT
END:VCALENDAR

When Outlook 2003 opens the download.ics file, the link ends up looking like this:

Event URL: http://www.host.com/club/events/view.aspx?Eventid - note the square at the end this is how it looks in the outlook application.

When you click on the link from within outlook it shows this in the address bar of Internet Explorer 7:

http://www.host.com/club/events/view.aspx?Eventid%17

Strange behavior. Any Ideas?

Thanks.
Coordinator
May 11, 2007 at 10:54 PM
I am no ICalendar expert.... when in doubt, consult the docs. Let me do some research.
May 15, 2007 at 9:22 PM
Edited May 15, 2007 at 9:25 PM
Hi z2bass,

I've figured it out with much trial and error. Below is the code that works for me in Outlook 2003. I have no idea what that "DO while offset" code does, but once I removed it and took a look at how MS outlook stores the ical file, I was able to get it to work.

Code module name: Events/Download.ashx

<%@ WebHandler Language="VB" Class="DownloadEvent" %>

Imports System.Web
Imports System.Data.SqlClient

'The idea behind this is to simply fetch the image out of the database and stream it down the network.
Public Class DownloadEvent : Implements IHttpHandler

Const BUFFERSIZE As Integer = 1024

Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return True
End Get
End Property

Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim response As Web.HttpResponse = context.Response
Dim request As Web.HttpRequest = context.Request
response.BufferOutput = True
response.ContentType = "text/calendar"
response.Cache.SetCacheability(HttpCacheability.NoCache)
Dim EventID As Integer = CInt(request.QueryString("EventID"))

Dim viewurl As New Uri(context.Request.Url, "view.aspx?Eventid=" & EventID)
writeCalEntry(EventID, response.Output, viewurl.ToString)

response.End()
End Sub

Public Sub writeCalEntry(ByVal EventID As Integer, ByVal output As IO.TextWriter, ByVal url As String)
Dim connection As New SqlConnection(ConfigurationManager.ConnectionStrings("ClubSiteDB").ConnectionString)
Dim qry As String = "SELECT Events.starttime, Events.endtime, Events.title, Events.description, Events.staticURL, Locations.title AS LocName, Locations.directions, "
qry &= "Locations.description AS locDesc, Locations.address "
qry &= "FROM Locations RIGHT OUTER JOIN "
qry &= "Events ON Locations.id = Events.location "
qry &= "WHERE (Events.id = @id)"

Dim command As New SqlCommand(qry, connection)
Dim param0 As New Data.SqlClient.SqlParameter("@id", Data.SqlDbType.Int)
param0.Value = EventID
command.Parameters.Add(param0)
connection.Open()

Dim dt As New Data.DataTable()
dt.Load(command.ExecuteReader)

If dt.Rows.Count > 0 Then
Dim dr As Data.DataRow = dt.Rows(0)

Dim starttime, endtime As Date
Dim title, description, location As String
Dim sb As New Text.StringBuilder()
Dim o As Object

starttime = CDate(dr("starttime"))
If Not IsDBNull(dr("endtime")) Then endtime = CDate(dr("endtime")) Else endtime = starttime
If Not IsDBNull(dr("title")) Then title = CStr(dr("title")) Else title = "An untitled clubsite event"

o = dr("description")
If Not IsDBNull(o) AndAlso CStr(o) <> "" Then
sb.AppendLine(CStr(dr("description")))

End If

sb.AppendLine()
sb.Append("Event URL: ")

o = dr("staticURL")
If Not IsDBNull(o) AndAlso CStr(o) <> "" Then
sb.AppendLine(CStr(o))
Else
sb.Append(url)
sb.AppendLine()
End If

o = dr("LocName")
If Not IsDBNull(o) AndAlso CStr(o) <> "" Then
location = CStr(o)
sb.AppendLine()
sb.Append("Event location: ")
sb.AppendLine(location)

Else
location = Nothing
End If

o = dr("locDesc")
If Not IsDBNull(o) AndAlso CStr(o) <> "" Then
sb.AppendLine()
sb.AppendLine("Location description:")
sb.AppendLine(CStr(o))

End If

o = dr("Address")
If Not IsDBNull(o) AndAlso CStr(o) <> "" Then
sb.AppendLine()
sb.AppendLine("Location Address:")
sb.AppendLine(CStr(o))

End If

o = dr("directions")
If Not IsDBNull(o) AndAlso CStr(o) <> "" Then
sb.AppendLine()
sb.AppendLine("Location Directions:")
sb.AppendLine(CStr(o))

End If

'Dim uc As New Text.UnicodeEncoding()
'description = System.Convert.ToBase64String(uc.GetBytes(sb.ToString), Base64FormattingOptions.InsertLineBreaks)
description = sb.ToString

output.WriteLine("BEGIN:VCALENDAR")
output.WriteLine("VERSION:2.0")
output.WriteLine("PRODID:" & url)
output.WriteLine("METHOD:PUBLISH")
output.WriteLine("BEGIN:VEVENT")
output.WriteLine("UID:" & Guid.NewGuid().ToString)
output.WriteLine("DTSTAMP:" & Now.ToUniversalTime.ToString("yyyyMMddTHHmmss") & "Z")
output.WriteLine("DTEND:" & endtime.ToUniversalTime.ToString("yyyyMMddTHHmmss") & "Z")
output.WriteLine("CATEGORIES:APPOINTMENT;PERSONAL")
'OLD CODE as of Version RC1
'output.WriteLine(EncodeProperty("DESCRIPTION;ENCODING=QUOTED-PRINTABLE:", description))
output.WriteLine(EncodeProperty("DESCRIPTION:", description))
'output.WriteLine(EncodeProperty64("DESCRIPTION;ENCODING=BASE64:", description))
If Not location Is Nothing Then
output.WriteLine(EncodeProperty("LOCATION;ENCODING=QUOTED-PRINTABLE:", location))
End If
output.WriteLine("PRIORITY:0")
output.WriteLine("DTSTART:" & starttime.ToUniversalTime.ToString("yyyyMMddTHHmmss") & "Z")
output.WriteLine("STATUS:NEEDS ACTION")
output.WriteLine(EncodeProperty("SUMMARY;ENCODING=QUOTED-PRINTABLE:", title))
output.WriteLine("SUMMARY;ENCODING=QUOTED-PRINTABLE:", title)
output.WriteLine("URL:" & url)
output.WriteLine("END:VEVENT")
output.WriteLine("END:VCALENDAR")
End If

connection.Close()
End Sub

Function EncodeProperty(ByVal key As String, ByVal value As String) As String
Dim sb As New Text.StringBuilder()
sb.Append(key)
sb.Append(value)
sb.Replace(";", "\;", key.Length, sb.Length - key.Length)
sb.Replace(vbCrLf, "\n")
sb.Replace("<p>", "")
sb.Replace("</p>", "")

Return sb.ToString
End Function
'OLD CODE as of Version RC1
'Function EncodeProperty(ByVal key As String, ByVal value As String) As String
' Dim sb As New Text.StringBuilder()
' sb.Append(key)
' sb.Append(value)
' sb.Replace(";", "\;", key.Length, sb.Length - key.Length)
' sb.Replace(vbCrLf, "=0D=0A")
' sb.Replace("<p>", "")
' sb.Replace("</p>", "")

' Dim offset As Integer = 76

' Do While offset < sb.Length
' Dim pos As Integer = sb.ToString(offset - 5, 10).IndexOf("=0D=0A")
' If pos = -1 Then
' 'Account for the string at the end of where we want to insert
' sb.Insert(offset - 5 + pos, "=" & vbCrLf)
' offset += 79 - 5 + pos
' Else
' sb.Insert(offset, "=" & vbCrLf)
' offset += 79
' End If
' Loop
' Return sb.ToString
'End Function

'Function EncodeProperty64(ByVal key As String, ByVal value As String) As String
' Dim sb As New Text.StringBuilder()
' sb.Append(key)
' Dim uc As New Text.UnicodeEncoding()
' sb.Append(System.Convert.ToBase64String(uc.GetBytes(value), Base64FormattingOptions.None))

' Dim offset As Integer = 76

' Do While offset < sb.Length
' sb.Insert(offset, vbCrLf)
' offset += 78
' Loop
' Return sb.ToString
'End Function

End Class