Intro | Part 1 | Part 2
As promised in the intro of this three-part series, you and I are going to build an AJAX Contact Us form in ASP.NET, a couple of different ways. Today we’re going to look to Visual Studio’s built in ASP.NET AJAX controls to do dynamic partial-page updates, and we’ll leave client-side network callbacks through a web service for a future post. To keep things moving, I’m going to assume that you are comfortable using Visual Studio. If you need to brush up, there are some great tutorials at ASP.NET.
You can download the source files for this project AJAXEnabledContactForm.zip (46 kb).
To start, I created a new AJAX Enabled Web Application in Visual Studio (you can find the free Visual Studio Express Edition here). I called the project “AjaxEnabledContactForm”, but you can call it whatever you want.
Next, I implement a Specified Pickup Directory method to test our contact form, and allow our web app to save notification emails to our c:\Temp\ folder. You can find the specifics of adding this to your own project in my post on The SMTP Alternative, but to keep this short, the code you need to add to your web.config file is as follows:
<configuration>
....
<system.net>
<mailSettings>
<smtp deliveryMethod="SpecifiedPickupDirectory">
<specifiedPickupDirectory pickupDirectoryLocation="c:\Temp\" />
</smtp>
</mailSettings>
</system.net>
....
</configuration>
Now, we need a page for our Contact Us form. I created a new page, called it "PartialPageUpdate.aspx", and added the following content to the body.
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<div>
<asp:Label ID="lblEmail" runat="server" Text="Email" /><br />
<asp:TextBox ID="txtEmail" runat="server" /><br />
<asp:Label ID="lblComments" runat="server" Text="Comments" /><br />
<asp:TextBox ID="txtComments" runat="server" Columns="20" Rows="4" TextMode="MultiLine" /><br />
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Button ID="btnSubmit" runat="server" Text="Submit" />
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
</body>
This gives us a very basic layout: An email text box, a comment text box, and a submit button.

You can add any other fields you need, but for our purposes, this is addequate. Of course, to use AJAX controls, remember to include the ScriptManager tag.
To give our form that AJAX feel, and to give the user some feedback, I also added an UpdateProgress control below the UpdatePanel:
<asp:UpdateProgress ID="UpdateProgress1" runat="server">
<ProgressTemplate>
<img alt="UpdateProgress" src="Images/SquareCircleLoader.gif" style="width: 31px; height: 31px" />
</ProgressTemplate>
</asp:UpdateProgress>
Moving to the page's codebehind file, we'll have the server email us on each submission, although you could just as easily have the server write our form's contents to a database. To the page load event, I've added a 3 second lag, to imitate network latency, only on postback. The code is as follows:
Public Partial Class PartialPageUpdate
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Page.IsPostBack Then
'Disable this setting in production
System.Threading.Thread.Sleep(3000)
End If
End Sub
End Class
Why only postbacks? Well, we're not trying to demonstrate network latency when the page loads for the first time, hence the "only on postback". Obviously, you'll take out this line in a production environment. But more importantly, the notable thing about using the AJAX UpdatePanel, and arguably one of it's problems, is that when you use this control on a page, you actually get a full page postback. At first, this seems rather odd, as we only had the submit button in the UpdatePanel, but this is how the UpdatePanel works. This is the main reason why you might opt for a straight client-side network callback through a web service. However, as long as you're not expecting thousands of postbacks a day, it's probably not going to have a noticable impact on your bandwidth usage.
Next, we're going to handle the submit button's click event by adding the following code to our PartialPageUpdate class in the codebehind file:
Protected Sub btnSubmit_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnSubmit.Click
SendMail()
End Sub
Finally, we'll add the code that actually sends the email. I'm not going to walk through every line, as this is fairly standard email sending code, but I should point out that I've used a session variable to store any errors that are generated, to add some basic error handling and help us troubleshoot any problems.
Private Sub SendMail()
'Create an error session variable
Session("myError") = Nothing
Dim mailMessage As System.Net.Mail.MailMessage = New System.Net.Mail.MailMessage()
mailMessage.From = New System.Net.Mail.MailAddress("myserver@mysite.com")
mailMessage.To.Add(New System.Net.Mail.MailAddress("me@mysite.com"))
mailMessage.ReplyTo = New System.Net.Mail.MailAddress(txtEmail.Text.Trim())
'Set additional options
mailMessage.Priority = Net.Mail.MailPriority.Normal
'Text/HTML
mailMessage.IsBodyHtml = False
'Set the subjet and body text
mailMessage.Subject = "Contact Us Form from: " & txtEmail.Text.Trim
mailMessage.Body = txtComments.Text
'Create an instance of the SmtpClient class for sending the email
'using web.config settings
Dim smtpClient As System.Net.Mail.SmtpClient = New System.Net.Mail.SmtpClient()
'Use a Try/Catch block to trap sending errors
'Especially useful when looping through multiple sends
Try
smtpClient.Send(mailMessage)
Catch ex As System.Net.Mail.SmtpException
Session("myError") = ex
Response.Redirect("/Failed.aspx")
Catch ex As Exception
Session("myError") = ex
Response.Redirect("/Failed.aspx")
Finally
mailMessage.Dispose()
End Try
Response.Redirect("/Success.aspx")
End Sub
So let's just walk through this. When our user clicks the submit button, the page posts back to the server the contents of the email and comments text boxes asynchronously, and our UpdateProgress control tells them to wait as something is happening. When the asynchronouslypostback is complete, the user's browser is redirected to the Success.aspx page (a good thing) or the Failed.aspx page (which isn't good). So we just need to create two new pages, Failed.aspx and Success.aspx, and we should be good to go.

Go ahead and give it a try running the PartialPageUpdate.aspx page. After you fill in the text boxes and click the submit button, you should get 3 seconds of progress, followed by an email delivered to your hard drive in the c:\Temp\ folder, and a browser redirect to the Success.aspx page.

I hope this gets you started on building that amazing AJAXified Contact Us page you've been thinking about. As I said before, at a minimum, you MUST add some server-side validation/security before you contemplate dropping this code into production, otherwise you're leaving the door wide open to hackers.
Our next stop is building a network callback Contact Us form.
Happy partial-page contacting,
James Fielding
Sciosoft Systems is a Canadian web design & development company based in Muskoka,
which is in central Ontario. We provide ASP.NET website & Windows Server application
development services to small and medium-sized business, as well as local government
and not-for-profit groups. If you have a website project you’d like to discuss,
please visit us at www.sciosoft.com.