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!
Blog Archive
Thursday, January 24, 2008
Announcing my run for Rockwood School Board
Posted by Chuck Spohr at 8:42 AM 0 comments
Labels: Board of Education, BOE, Chuck Spohr for Rockwood School Board
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
Posted by Chuck Spohr at 1:38 PM 31 comments
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>
Posted by Chuck Spohr at 11:06 AM 0 comments
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.
Posted by Chuck Spohr at 10:19 AM 0 comments
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!
Posted by Chuck Spohr at 11:37 AM 1 comments
Labels: checkboxlist checkbox listitem databound selected value property .net 2.0
About Me
- Chuck Spohr
- Principal Partner at NetPositive, Inc., St. Louis, MO.