Thursday, January 24, 2008

Announcing my run for Rockwood School Board

I know this has nothing to do with .NET development, but I want to get the word out where I can... I'm running for the Rockwood School Board in St. Louis County, MO. Visit my campaign website at SpohrForRockwood.org. Thanks!

Tuesday, October 23, 2007

Send Outlook Meeting Requests with System.Net.Mail

Here's a class I developed to send Outlook Meeting Requests via SMTP Email using the System.Net.Mail library. Just instantiate the AppointmentBLL object, passing in the desired parameters for the meeting, then call EmailAppointment to actually send it.

This ended up being more difficult than I anticipated. You have to create a "multipart/alternative" message, and the calendar item is in VCALENDAR format. After some fiddling with the header parameters and VCALENDAR file, I finally got it to work, and that was after wasting a bunch of time with CDOSYS and MAPI. Enjoy...



Imports Microsoft.VisualBasic
Imports System.Net.Mail

Public Class AppointmentBLL
' This class formats and sends a meeting request via SMTP email

Public StartDate As DateTime
Public EndDate As DateTime
Public Subject As String
Public Summary As String
Public Location As String
Public AttendeeName As String
Public AttendeeEmail As String
Public OrganizerName As String
Public OrganizerEmail As String

Public Sub New(ByVal pdtStartDate As DateTime, _
ByVal pdtEndDate As DateTime, _
ByVal psSubject As String, _
ByVal psSummary As String, _
ByVal psLocation As String, _
ByVal psAttendeeName As String, _
ByVal psAttendeeEmail As String, _
ByVal psOrganizerName As String, _
ByVal psOrganizerEmail As String)

' Copy constructor parameters to public propeties

StartDate = pdtStartDate
EndDate = pdtEndDate
Subject = psSubject
Summary = psSummary
Location = psLocation
AttendeeName = psAttendeeName
AttendeeEmail = psAttendeeEmail
OrganizerName = psOrganizerName
OrganizerEmail = psOrganizerEmail
End Sub


Public Sub EmailAppointment()

' Send the calendar message to the attendee

Dim loMsg As New MailMessage
Dim loTextView As AlternateView = Nothing
Dim loHTMLView As AlternateView = Nothing
Dim loCalendarView As AlternateView = Nothing
Dim loSMTPServer As New SmtpClient

' SMTP settings set up in web.config such as:
' <system.net>
' <mailSettings>
' <smtp>
' <network
' host = "exchange.mycompany.com"
' port = "25"
' userName = "username"
' password="password" />
' </smtp>
' </mailSettings>
' </system.net>

' Set up the different mime types contained in the message
Dim loTextType As System.Net.Mime.ContentType = New System.Net.Mime.ContentType("text/plain")
Dim loHTMLType As System.Net.Mime.ContentType = New System.Net.Mime.ContentType("text/html")
Dim loCalendarType As System.Net.Mime.ContentType = New System.Net.Mime.ContentType("text/calendar")

' Add parameters to the calendar header
loCalendarType.Parameters.Add("method", "REQUEST")
loCalendarType.Parameters.Add("name", "meeting.ics")

' Create message body parts
loTextView = AlternateView.CreateAlternateViewFromString(BodyText(), loTextType)
loMsg.AlternateViews.Add(loTextView)

loHTMLView = AlternateView.CreateAlternateViewFromString(BodyHTML(), loHTMLType)
loMsg.AlternateViews.Add(loHTMLView)

loCalendarView = AlternateView.CreateAlternateViewFromString(VCalendar(), loCalendarType)
loCalendarView.TransferEncoding = Net.Mime.TransferEncoding.SevenBit
loMsg.AlternateViews.Add(loCalendarView)

' Adress the message

loMsg.From = New MailAddress(OrganizerEmail)
loMsg.To.Add(New MailAddress(AttendeeEmail))
loMsg.Subject = Subject

' Send the message
loSMTPServer.DeliveryMethod = SmtpDeliveryMethod.Network
loSMTPServer.Send(loMsg)
End Sub

Public Function BodyText() As String

' Return the Body in text format

Const BODY_TEXT = _
"Type:Single Meeting" & vbCrLf & _
"Organizer: {0}" & vbCrLf & _
"Start Time:{1}" & vbCrLf & _
"End Time:{2}" & vbCrLf & _
"Time Zone:{3}" & vbCrLf & _
"Location: {4}" & vbCrLf & _
vbCrLf & _
"*~*~*~*~*~*~*~*~*~*" & vbCrLf & _
vbCrLf & _
"{5}"

Return String.Format(BODY_TEXT, _
OrganizerName, _
StartDate.ToLongDateString & " " & StartDate.ToLongTimeString, _
EndDate.ToLongDateString & " " & EndDate.ToLongTimeString, _
System.TimeZone.CurrentTimeZone.StandardName, _
Location, _
Summary)

End Function

Public Function BodyHTML() As String

' Return the Body in HTML format

Const BODY_HTML = _
"<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 3.2//EN"">" & vbCrLf & _
"<HTML>" & vbCrLf & _
"<HEAD>" & vbCrLf & _
"<META HTTP-EQUIV=""Content-Type"" CONTENT=""text/html; charset=utf-8"">" & vbCrLf & _
"<META NAME=""Generator"" CONTENT=""MS Exchange Server version 6.5.7652.24"">" & vbCrLf & _
"<TITLE>{0}</TITLE>" & vbCrLf & _
"</HEAD>" & vbCrLf & _
"<BODY>" & vbCrLf & _
"<!-- Converted from text/plain format -->" & vbCrLf & _
"<P><FONT SIZE=2>Type:Single Meeting<BR>" & vbCrLf & _
"Organizer:{1}<BR>" & vbCrLf & _
"Start Time:{2}<BR>" & vbCrLf & _
"End Time:{3}<BR>" & vbCrLf & _
"Time Zone:{4}<BR>" & vbCrLf & _
"Location:{5}<BR>" & vbCrLf & _
"<BR>" & vbCrLf & _
"*~*~*~*~*~*~*~*~*~*<BR>" & vbCrLf & _
"<BR>" & vbCrLf & _
"{6}<BR>" & vbCrLf & _
"</FONT>" & vbCrLf & _
"</P>" & vbCrLf & _
vbCrLf & _
"</BODY>" & vbCrLf & _
"</HTML>"

Return String.Format(BODY_HTML, _
Summary, _
OrganizerName, _
StartDate.ToLongDateString & " " & StartDate.ToLongTimeString, _
EndDate.ToLongDateString & " " & EndDate.ToLongTimeString, _
System.TimeZone.CurrentTimeZone.StandardName, _
Location, _
Summary)

End Function

Public Function VCalendar() As String

' Return the Calendar text in vCalendar format, compatible with most calendar programs

Const lcDateFormat = "yyyyMMddTHHmmssZ"
Dim loGUID As Guid = Guid.NewGuid ' Or use the guid of an exiting meeting?

Const VCAL_FILE = "BEGIN:VCALENDAR" & vbCrLf & _
"METHOD:REQUEST" & vbCrLf & _
"PRODID:Microsoft CDO for Microsoft Exchange" & vbCrLf & _
"VERSION:2.0" & vbCrLf & _
"BEGIN:VTIMEZONE" & vbCrLf & _
"TZID:(GMT-06.00) Central Time (US & Canada)" & vbCrLf & _
"X-MICROSOFT-CDO-TZID:11" & vbCrLf & _
"BEGIN:STANDARD" & vbCrLf & _
"DTSTART:16010101T020000" & vbCrLf & _
"TZOFFSETFROM:-0500" & vbCrLf & _
"TZOFFSETTO:-0600" & vbCrLf & _
"RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=11;BYDAY=1SU" & vbCrLf & _
"END:STANDARD" & vbCrLf & _
"BEGIN:DAYLIGHT" & vbCrLf & _
"DTSTART:16010101T020000" & vbCrLf & _
"TZOFFSETFROM:-0600" & vbCrLf & _
"TZOFFSETTO:-0500" & vbCrLf & _
"RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=3;BYDAY=2SU" & vbCrLf & _
"END:DAYLIGHT" & vbCrLf & _
"END:VTIMEZONE" & vbCrLf & _
"BEGIN:VEVENT" & vbCrLf & _
"DTSTAMP:{8}" & vbCrLf & _
"DTSTART:{0}" & vbCrLf & _
"SUMMARY:{7}" & vbCrLf & _
"UID:{5}" & vbCrLf & _
"ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=""{9}"":MAILTO:{9}" & vbCrLf & _
"ACTION;RSVP=TRUE;CN=""{4}"":MAILTO:{4}" & vbCrLf & _
"ORGANIZER;CN=""{3}"":mailto:{4}" & vbCrLf & _
"LOCATION:{2}" & vbCrLf & _
"DTEND:{1}" & vbCrLf & _
"DESCRIPTION:{7}\N" & vbCrLf & _
"SEQUENCE:1" & vbCrLf & _
"PRIORITY:5" & vbCrLf & _
"CLASS:" & vbCrLf & _
"CREATED:{8}" & vbCrLf & _
"LAST-MODIFIED:{8}" & vbCrLf & _
"STATUS:CONFIRMED" & vbCrLf & _
"TRANSP:OPAQUE" & vbCrLf & _
"X-MICROSOFT-CDO-BUSYSTATUS:BUSY" & vbCrLf & _
"X-MICROSOFT-CDO-INSTTYPE:0" & vbCrLf & _
"X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY" & vbCrLf & _
"X-MICROSOFT-CDO-ALLDAYEVENT:FALSE" & vbCrLf & _
"X-MICROSOFT-CDO-IMPORTANCE:1" & vbCrLf & _
"X-MICROSOFT-CDO-OWNERAPPTID:-1" & vbCrLf & _
"X-MICROSOFT-CDO-ATTENDEE-CRITICAL-CHANGE:{8}" & vbCrLf & _
"X-MICROSOFT-CDO-OWNER-CRITICAL-CHANGE:{8}" & vbCrLf & _
"BEGIN:VALARM" & vbCrLf & _
"ACTION:DISPLAY" & vbCrLf & _
"DESCRIPTION:REMINDER" & vbCrLf & _
"TRIGGER;RELATED=START:-PT00H15M00S" & vbCrLf & _
"END:VALARM" & vbCrLf & _
"END:VEVENT" & vbCrLf & _
"END:VCALENDAR" & vbCrLf

Return String.Format(VCAL_FILE, _
StartDate.ToUniversalTime().ToString(lcDateFormat), _
EndDate.ToUniversalTime().ToString(lcDateFormat), _
Location, _
OrganizerName, _
OrganizerEmail, _
"{" & loGUID.ToString() & "}", _
Summary, _
Subject, _
Now.ToUniversalTime().ToString(lcDateFormat), _
AttendeeEmail)
End Function

End Class

Tuesday, October 2, 2007

Drop-in ASP.NET code for US State List

I often need a dropdownlist of US States. It's a pain to create it from scratch, so here's one I put together. I hope you find this useful...


<asp:DropDownList ID="ddlState" runat="server">
<asp:ListItem Value="">Choose State</asp:ListItem>
<asp:ListItem Value="AL">Alabama</asp:ListItem>
<asp:ListItem Value="AK">Alaska</asp:ListItem>
<asp:ListItem Value="AZ">Arizona</asp:ListItem>
<asp:ListItem Value="AR">Arkansas</asp:ListItem>
<asp:ListItem Value="CA">Califonia</asp:ListItem>
<asp:ListItem Value="CO">Colorado</asp:ListItem>
<asp:ListItem Value="CT">Connecticut</asp:ListItem>
<asp:ListItem Value="DE">Delaware</asp:ListItem>
<asp:ListItem Value="DC">Washington DC</asp:ListItem>
<asp:ListItem Value="FL">Florida</asp:ListItem>
<asp:ListItem Value="GA">Georgia</asp:ListItem>
<asp:ListItem Value="HI">Hawaii</asp:ListItem>
<asp:ListItem Value="ID">Idaho</asp:ListItem>
<asp:ListItem Value="IL">Illinois</asp:ListItem>
<asp:ListItem Value="IN">Indiana</asp:ListItem>
<asp:ListItem Value="IA">Iowa</asp:ListItem>
<asp:ListItem Value="KS">Kansas</asp:ListItem>
<asp:ListItem Value="KY">Kentucky</asp:ListItem>
<asp:ListItem Value="LA">Louisiana</asp:ListItem>
<asp:ListItem Value="ME">Maine</asp:ListItem>
<asp:ListItem Value="MD">Maryland</asp:ListItem>
<asp:ListItem Value="MA">Massachusetts</asp:ListItem>
<asp:ListItem Value="MI">Michigan</asp:ListItem>
<asp:ListItem Value="MN">Minnesota</asp:ListItem>
<asp:ListItem Value="MS">Mississippi</asp:ListItem>
<asp:ListItem Value="MO">Missouri</asp:ListItem>
<asp:ListItem Value="MT">Montana</asp:ListItem>
<asp:ListItem Value="NE">Nebraska</asp:ListItem>
<asp:ListItem Value="NV">Nevada</asp:ListItem>
<asp:ListItem Value="NH">New Hampshire</asp:ListItem>
<asp:ListItem Value="NJ">New Jersey</asp:ListItem>
<asp:ListItem Value="NM">New Mexico</asp:ListItem>
<asp:ListItem Value="NY">New York</asp:ListItem>
<asp:ListItem Value="NC">North Carolina</asp:ListItem>
<asp:ListItem Value="ND">North Dakota</asp:ListItem>
<asp:ListItem Value="OH">Ohio</asp:ListItem>
<asp:ListItem Value="OK">Oklahoma</asp:ListItem>
<asp:ListItem Value="OR">Oregon</asp:ListItem>
<asp:ListItem Value="PA">Pennsylvania</asp:ListItem>
<asp:ListItem Value="RI">Rhode Island</asp:ListItem>
<asp:ListItem Value="SC">South Carolina</asp:ListItem>
<asp:ListItem Value="SD">South Dakota</asp:ListItem>
<asp:ListItem Value="TN">Tennessee</asp:ListItem>
<asp:ListItem Value="TX">Texas</asp:ListItem>
<asp:ListItem Value="UT">Utah</asp:ListItem>
<asp:ListItem Value="VT">Vermont</asp:ListItem>
<asp:ListItem Value="VA">Virginia</asp:ListItem>
<asp:ListItem Value="WA">Washington</asp:ListItem>
<asp:ListItem Value="WV">West Virginia</asp:ListItem>
<asp:ListItem Value="WI">Wisconsin</asp:ListItem>
<asp:ListItem Value="WY">Wyoming</asp:ListItem>
</asp:DropDownList>

Monday, March 5, 2007

Get the return value from a stored procedure

I just burt more hours than I care to admit figuring out this one. I was using an ObjectDataSource to call a stored proc which inserts records into a couple of tables, then returns the identity of the second table. No matter what I did, I could not retrieve the return_value. Instead, I got "Nothing" in the RETURN_VALUE output parameter.

After reading numerous posts out there, I finally figured out that a Strongly Typed Dataset will populate the RETURN_VALUE with the first column of the first row of the resulting result set. Since my stored proc wan't returning a result set, I was getting nothing. By simply ending the proc with the following, I got my RETURN_VALUE:

   -- Do inserts and stuff...

   SELECT Scope_Identity()
   RETURN Scope_Identity()
END

By leaving the RETURN in there, I'm covered if the default behavior changes in the future.

Wednesday, February 28, 2007

Databound checkboxlist aggravation

Discovered today that the databound checkboxlist items' SELECTED property doesn't reflect what's in the VALUE property. The following code on the checkboxlist databound event hanlder cleared things up for me:

Protected Sub cblRoles_DataBound(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles cblRoles.DataBound

    Dim loItem As ListItem = Nothing
    For Each loItem In cblRoles.Items
        loItem.Selected = loItem.Value
    Next
End Sub


Now, when the form loads, the items with Value=True now display with the checkbox selected. Whew!

About Me

Principal Partner at NetPositive, Inc., St. Louis, MO.