Additional Fields in the Contact Form

Topics: ASP.NET 2.0, Business Logic Layer, Controls
Sep 17, 2012 at 10:56 PM

I want to add additional fields in the contact form such as an address and phone number. What's the easiest way to accomplish this?

Coordinator
Sep 18, 2012 at 5:28 AM

Its all in contact.aspx - you'll need to add fields to the page and handle them in send email method in code behind. Pretty straight forward but you'll have to remember to update when upgrading.

Sep 18, 2012 at 10:38 PM

Can you give an example to the Visual Studio Challenged such as myself? I'm going batty here trying to figure this out!

Sep 19, 2012 at 2:31 PM

OK, here's what I have:

contact.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="contact.aspx.cs" Inherits="contact" ValidateRequest="false" %>
<%@ Import Namespace="BlogEngine.Core" %>

<asp:Content ID="Content1" ContentPlaceHolderID="cphBody" Runat="Server">
  <div id="contact">
    <div id="divForm" runat="server">
      <h1><%=Resources.labels.contact %></h1>
      
      <div><%=BlogSettings.Instance.ContactFormMessage %></div>
      
      <label for="<%=txtName.ClientID %>"><%=Resources.labels.name %></label>
      <asp:TextBox runat="server" id="txtName" cssclass="field" />
      <asp:requiredfieldvalidator runat="server" controltovalidate="txtName" ErrorMessage="<%$Resources:labels, required %>" validationgroup="contact" /><br />
      
      <label for="<%=txtPhone.ClientID %>">Phone Number</label>
      <asp:TextBox runat="server" id="txtPhone" cssclass="field" />
      <asp:requiredfieldvalidator runat="server" controltovalidate="txtPhone" errorMessage="<%$Resources:labels, required %>" validationgroup="contact" /><br />

      <label for="<%=txtEmail.ClientID %>"><%=Resources.labels.email %></label>
      <asp:TextBox runat="server" id="txtEmail" cssclass="field" />
      <asp:RegularExpressionValidator runat="server" ControlToValidate="txtEmail" display="dynamic" ErrorMessage="<%$Resources:labels, enterValidEmail %>" ValidationExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*" validationgroup="contact" />
      <asp:requiredfieldvalidator runat="server" controltovalidate="txtEmail" ErrorMessage="<%$Resources:labels, required %>" validationgroup="contact" /><br />
      
      <label for="<%=txtSubject.ClientID %>"><%=Resources.labels.subject %></label>
      <asp:TextBox runat="server" id="txtSubject" cssclass="field" />
      <asp:requiredfieldvalidator runat="server" controltovalidate="txtSubject" ErrorMessage="<%$Resources:labels, required %>" validationgroup="contact" /><br />
      
      <label for="<%=txtMessage.ClientID %>"><%=Resources.labels.message %></label>
      <asp:TextBox runat="server" id="txtMessage" textmode="multiline" rows="5" columns="30" />
      <asp:requiredfieldvalidator runat="server" controltovalidate="txtMessage" ErrorMessage="<%$Resources:labels, required %>" display="dynamic" validationgroup="contact" />    
      
      <asp:placeholder runat="server" id="phAttachment">      
        <label for="<%=txtAttachment.ClientID %>"><%=Resources.labels.attachFile %></label>
        <asp:FileUpload runat="server" id="txtAttachment" />
      </asp:placeholder>
      
      <br /><br />
      <blog:RecaptchaControl runat="server" ID="recaptcha" />
      <asp:HiddenField runat="server" ID="hfCaptcha" />
      
      <asp:button runat="server" id="btnSend" Text="<%$Resources:labels, send %>" OnClientClick="return beginSendMessage();" validationgroup="contact" />    
      <asp:label runat="server" id="lblStatus" visible="false">This form does not work at the moment. Sorry for the inconvenience.</asp:label>
    </div>
    
    <div id="thanks">
      <div id="divThank" runat="Server" visible="False">      
        <%=BlogSettings.Instance.ContactThankMessage %>
      </div>
    </div>
  </div>
  
  <script type="text/javascript">
    function beginSendMessage()
    {
    	if (BlogEngine.$('<%=txtAttachment.ClientID %>') && BlogEngine.$('<%=txtAttachment.ClientID %>').value.length > 0)
        return true;
        
      if(!Page_ClientValidate('contact'))
          return false;

      var recaptchaResponseField = document.getElementById('recaptcha_response_field');
      var recaptchaResponse = recaptchaResponseField ? recaptchaResponseField.value : "";

      var recaptchaChallengeField = document.getElementById('recaptcha_challenge_field');
      var recaptchaChallenge = recaptchaChallengeField ? recaptchaChallengeField.value : "";

      var name = BlogEngine.$('<%=txtName.ClientID %>').value;
      var phone = BlogEngine.$('<%=txtPhone.ClientID %>').value;
      var email = BlogEngine.$('<%=txtEmail.ClientID %>').value;
      var subject = BlogEngine.$('<%=txtSubject.ClientID %>').value;
      var message = BlogEngine.$('<%=txtMessage.ClientID %>').value;
      var sep = '-||-';
      var arg = name + sep + email + sep + phone + subject + sep + message + sep + recaptchaResponse + sep + recaptchaChallenge;
      WebForm_DoCallback('__Page', arg, endSendMessage, 'contact', onSendError, false) 
      
      BlogEngine.$('<%=btnSend.ClientID %>').disabled = true;
      
      return false;
    }

    function endSendMessage(arg, context) {

        if (arg == "RecaptchaIncorrect") {
            displayIncorrectCaptchaMessage();
            BlogEngine.$('<%=btnSend.ClientID %>').disabled = false;

            if (document.getElementById('recaptcha_response_field')) {
                Recaptcha.reload();
            }
        }
        else {
            if (document.getElementById("spnCaptchaIncorrect")) document.getElementById("spnCaptchaIncorrect").style.display = "none";

            BlogEngine.$('<%=btnSend.ClientID %>').disabled = false;
            var form = BlogEngine.$('<%=divForm.ClientID %>')
            var thanks = BlogEngine.$('thanks');

            form.style.display = 'none';
            thanks.innerHTML = arg;
        }
    }

    function displayIncorrectCaptchaMessage() {
        if (document.getElementById("spnCaptchaIncorrect")) document.getElementById("spnCaptchaIncorrect").style.display = "";
    }

    function onSendError(err, context) {
        if (document.getElementById('recaptcha_response_field')) {
            Recaptcha.reload();
        }
        BlogEngine.$('<%=btnSend.ClientID %>').disabled = false;
        alert("Sorry, but the following occurred while attemping to send your message: " + err);
    }
  </script>
</asp:Content>

And the contact.aspx.cs:

#region Using

using System;
using System.Collections;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using BlogEngine.Core;
using BlogEngine.Core.Web.Controls;
using System.Net.Mail;
using System.Text.RegularExpressions;

#endregion

public partial class contact : BlogBasePage, ICallbackEventHandler
{

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        ClientScript.GetCallbackEventReference(this, "arg", "callback", "context");
        btnSend.Click += new EventHandler(btnSend_Click);
        if (!Page.IsPostBack)
        {
            txtSubject.Text = Request.QueryString["subject"];
            txtName.Text = Request.QueryString["name"];
            txtEmail.Text = Request.QueryString["email"];
            txtPhone.Text = Request.QueryString["phone"];

            GetCookie();
            phAttachment.Visible = BlogSettings.Instance.EnableContactAttachments;
            SetFocus();
        }

        if (!IsPostBack && !IsCallback)
        {
            recaptcha.Visible = UseCaptcha;
            recaptcha.UserUniqueIdentifier = hfCaptcha.Value = Guid.NewGuid().ToString();
        }

        Page.Title = Server.HtmlEncode(Resources.labels.contact);
        base.AddMetaTag("description", Utils.StripHtml(BlogSettings.Instance.ContactFormMessage));
    }

	/// <summary>
	/// Sets the focus on the first empty textbox.
	/// </summary>
	private void SetFocus()
	{
		if (string.IsNullOrEmpty(Request.QueryString["name"]) && txtName.Text == string.Empty)
		{
			txtName.Focus();
		}
        else if (string.IsNullOrEmpty(Request.QueryString["phone"]) && txtPhone.Text == string.Empty)
        {
            txtPhone.Focus();
        }
        else if (string.IsNullOrEmpty(Request.QueryString["email"]) && txtEmail.Text == string.Empty)
        {
            txtEmail.Focus();
        }
        else if (string.IsNullOrEmpty(Request.QueryString["subject"]))
        {
            txtSubject.Focus();
        }
        else
        {
            txtMessage.Focus();
        }
	}

	/// <summary>
	/// Handles the Click event of the btnSend control.
	/// </summary>
	/// <param name="sender">The source of the event.</param>
	/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
	private void btnSend_Click(object sender, EventArgs e)
	{
		if (Page.IsValid && txtAttachment.HasFile)
		{
            if (!UseCaptcha || IsCaptchaValid)
            {
                bool success = SendEmail(txtEmail.Text, txtPhone.Text, txtName.Text, txtSubject.Text, txtMessage.Text);
                divForm.Visible = !success;
                lblStatus.Visible = !success;
                divThank.Visible = success;
                SetCookie();
            }
            else
            {
                ClientScript.RegisterStartupScript(this.GetType(), "captcha-incorrect", " displayIncorrectCaptchaMessage(); ", true);
            }
		}
	}

    private bool SendEmail(string p, string p_2, string p_3, string p_4, string p_5)
    {
        throw new NotImplementedException();
    }

	private bool SendEmail(string email, string name, string subject, string message)
	{
		try
		{
			using (MailMessage mail = new MailMessage())
			{
				mail.From = new MailAddress(BlogSettings.Instance.Email, name);
				mail.ReplyTo = new MailAddress(email, name);

				mail.To.Add(BlogSettings.Instance.Email);
				mail.Subject = BlogSettings.Instance.EmailSubjectPrefix + " " + Resources.labels.email.ToLower() + " - " + subject;

                mail.Body = "<div style=\"font: 10pt Arial, Helvetica, Sans-Serif\">";
				mail.Body += Server.HtmlEncode(message).Replace("\n", "<br />") + "<br /><br />";
				mail.Body += "<hr /><br />";
                		mail.Body += "<h3>" + Resources.labels.contactAuthorInformation + "</h3>";
				mail.Body += "<div style=\"font-size:9pt;line-height:16px\">";
				mail.Body += "<strong>" + Resources.labels.name + ":</strong> " + Server.HtmlEncode(name) + "<br />";
                		mail.Body += "<strong>" + Resources.labels.email + ":</strong> " + Server.HtmlEncode(email) + "<br />";

				if (ViewState["url"] != null)
                    		mail.Body += string.Format("<strong>" + Resources.labels.website + ":</strong> <a href=\"{0}\">{0}</a><br />", ViewState["url"]);

				if (ViewState["country"] != null)
                    		mail.Body += "<strong>" + Resources.labels.countryCode + ":</strong> " + ((string)ViewState["country"]).ToUpperInvariant() + "<br />";

				if (HttpContext.Current != null)
				{
                    			mail.Body += "<strong>" + Resources.labels.contactIPAddress + ":</strong> " + HttpContext.Current.Request.UserHostAddress + "<br />";
                                mail.Body += "<strong>Phone Number:</strong>" + txtPhone.Text + "<br />";
                    			mail.Body += "<strong>" + Resources.labels.contactUserAgent + ":</strong> " + HttpContext.Current.Request.UserAgent;
				}

				if (txtAttachment.HasFile)
				{
					Attachment attachment = new Attachment(txtAttachment.PostedFile.InputStream, txtAttachment.FileName);
					mail.Attachments.Add(attachment);
				}

				if (Utils.SendMailMessage(mail).Length > 0) {
					return false;
				};
			}

			return true;
		}
		catch (Exception ex)
		{
			if (Security.IsAuthorizedTo(Rights.ViewDetailedErrorMessages))
			{
                if (ex.InnerException != null)
                {
                    lblStatus.Text = ex.InnerException.Message;
                }
                else
                {
                    lblStatus.Text = ex.Message;
                }
			}

			return false;
		}
	}

	// comment test
	
	#region Cookies

	/// <summary>
	/// Gets the cookie with visitor information if any is set.
	/// Then fills the contact information fields in the form.
	/// </summary>
	private void GetCookie()
	{
		HttpCookie cookie = Request.Cookies["comment"];
		if (cookie != null)
		{
			txtName.Text = Server.UrlDecode(cookie.Values["name"]);
			txtEmail.Text = cookie.Values["email"];
			ViewState["url"] = cookie.Values["url"];
			ViewState["country"] = cookie.Values["country"];
		}
	}

	/// <summary>
	/// Sets a cookie with the entered visitor information
	/// so it can be prefilled on next visit.
	/// </summary>
	private void SetCookie()
	{
		HttpCookie cookie = new HttpCookie("comment");
		cookie.Expires = DateTime.Now.AddMonths(24);
		cookie.Values.Add("name", Server.UrlEncode(txtName.Text));
		cookie.Values.Add("email", txtEmail.Text);
		cookie.Values.Add("url", string.Empty);
		cookie.Values.Add("country", string.Empty);
		Response.Cookies.Add(cookie);
	}

	#endregion

	#region CAPTCHA

	/// <summary> 
	/// Gets whether or not the user is human 
	/// </summary> 
    private bool IsCaptchaValid
    {
        get
        {
            recaptcha.Validate();
            return recaptcha.IsValid;
        }
    }

    private bool UseCaptcha
    {
        get
        {
            return
                BlogSettings.Instance.EnableRecaptchaOnContactForm &&
                recaptcha.RecaptchaEnabled &&
                recaptcha.RecaptchaNecessary;
        }
    }

	#endregion


	#region ICallbackEventHandler Members

	private string _Callback;

	public string GetCallbackResult()
	{
		return _Callback;
	}

    public void RaiseCallbackEvent(string eventArgument)
    {
        string[] arg = eventArgument.Split(new string[] { "-||-" }, StringSplitOptions.None);
        if (arg.Length == 7)
        {
            string name = arg[0];
            string email = arg[1];
            string subject = arg[2];
            string message = arg[3];

            string recaptchaResponse = arg[4];
            string recaptchaChallenge = arg[5];

            string phone = arg[6];

            recaptcha.UserUniqueIdentifier = hfCaptcha.Value;
            if (UseCaptcha)
            {
                if (!recaptcha.ValidateAsync(recaptchaResponse, recaptchaChallenge))
                {
                    _Callback = "RecaptchaIncorrect";
                    return;
                }
            }

            if (SendEmail(email, name, subject, message))
            {
                _Callback = BlogSettings.Instance.ContactThankMessage;
            }
            else
            {
                _Callback = "This form does not work at the moment. Sorry for the inconvenience.";
            }
        }
        else
        {
            _Callback = "This form does not work at the moment. Sorry for the inconvenience.";
        }
    }

	#endregion

}

But when I submit the form I get the follwoing:
This form does not work at the moment. Sorry for the inconvenience.

What am I doing wrong?

Coordinator
Sep 19, 2012 at 4:53 PM

Hard to tell from a glance because I'm not sure what changes you made and don't have VS at hand, but don't you missing separator after "phone"?

var arg = name + sep + email + sep + phone + subject + sep...

and should be:

var arg = name + sep + email + sep + phone + sep + subject + sep...

Seams like you changed argument length to 7 in raise callback, but still passing 6 arguments squishing phone and subject together.

Sep 21, 2012 at 3:31 PM

Thanks for the help rtur! You pointed me in the right direction and I was able to add all of the additional fields that I need. One other question, though, is how to get a drop down list to pass the variable? In my contact.aspx file I have the the drop down list populating, and it looks correct on the screen. My variable in beginsendmessage is var state = BlogEngine.$('<%=txtState.SelectedValue %>').value; but when I hit the submit button, it just loops back to the form with all fields filled in. Any idea how to pass that variable on to the .cs file?

 

Sep 21, 2012 at 3:41 PM

OK, figured that out! It needs to be var state = ('<%=txtState.SelectedValue %>'); and it passes the 1st value of the drop down. Now I just have to figure out how to get it to pass what's selected!