A contact form is an essential facet of many websites and a feature that Umbraco 7 does not provide, at least not for free. In this tutorial I’ll show you how to create a contact form with email notification. We’ll use the SendGrid email service to send messages.
To get started, follow the instructions for creating a SendGrid account. Once you have an account, open your Umbraco project in Visual Studio.
Tools
> Nuget Package Manager
> Package Manager Console
.Install-Package Sendgrid
.We now need to set up a data model to represent messages from our users. Add a folder to your project named Models
. Within this folder, add a class named ContactViewModel
. Inside this class, replace the existing code with the code below, being sure to change the namespace to that of your project.
using System.ComponentModel.DataAnnotations;
namespace YourProjectName.Models
{
public class ContactViewModel
{
[Required][stringlength(200, minimumlength = 2)]
public string Name { get; set; }
[Required]
[EmailAddress]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email address")]
public string EmailAddress { get; set; }
[Required]
[StringLength(2500, MinimumLength = 10)]
[DataType(DataType.MultilineText)]
public string Message { get; set; }
}
}
With the data model established, you’re ready to create a surface controller to handle POST requests from a contact form. Create a folder in your project named Controllers
. Within this folder, add a class named ContactSurfaceController.cs
. In this controller we’ll validates requests against our data model and generate email via the SendGrid library. As confirmation, we return successful messages for display to the user via the ViewBag
.
In the example below, I use AppSettings
configuration values from my Web.Config
file to avoid magic strings. If you’d rather, you can simply enter these values directly as strings.
using System.Web.Mvc;
using YourProjectName.Models;
using SendGrid;
using System.Web.Configuration;
namespace YourProjectName.Controllers
{
public class ContactSurfaceController : Umbraco.Web.Mvc.SurfaceController
{
[HttpPost]
public ActionResult CreateContactMessage(ContactViewModel contactMessage)
{
if (!ModelState.IsValid)
{
return CurrentUmbracoPage();
}
ViewBag.Contact = contactMessage;
var appName = WebConfigurationManager.AppSettings["appName"];
var contactEmailAddress = WebConfigurationManager.AppSettings["contactEmailAddress"];
var sendgridUsername = WebConfigurationManager.AppSettings["sendgridUsername"];
var sendgridPassword = WebConfigurationManager.AppSettings["sendgridPassword"];
if (appName != null &&
contactEmailAddress != null &&
sendgridUsername != null &&
sendgridPassword != null)
{
var emailMessage = new SendGridMessage();
emailMessage.From = new System.Net.Mail.MailAddress(contactMessage.EmailAddress);
emailMessage.AddTo(contactEmailAddress);
emailMessage.Subject = appName + " | Message from " + contactMessage.Name;
emailMessage.Text = contactMessage.Message;
var credentials = new System.Net.NetworkCredential(sendgridUsername, sendgridPassword);
var transportWeb = new Web(credentials);
transportWeb.Deliver(emailMessage);
}
return CurrentUmbracoPage();
}
}
}
Next, we need a PartialView
with our contact form markup.
Settings
menu item.Settings
, create a partial view named ContactForm
.@model YourProjectName.Models.ContactViewModel
@using (Html.BeginUmbracoForm<YourProjectName.Controllers.ContactSurfaceController>(
"CreateContactMessage"))
{
<h2>
Contact details
</h2>
if (!ViewData.ModelState.IsValid)
{
<div class="row">
<div class="large-12 columns">
@Html.ValidationSummary(true, "Houston, we have a problem. Check things over and try again.")
</div>
</div>
}
<fieldset>
<div class="row">
<div class="large-12 columns">
</div>
</div>
<div class="row">
<div class="large-6 medium-8 small-10 columns">
@Html.LabelFor(x => x.Name)<span class="required">*</span>
@Html.TextBoxFor(x => x.Name, new Dictionary<string, Object> { { "required", "" } })
<small class="error">Your name is required.</small>
@Html.ValidationMessageFor(x => x.Name)
</div>
</div>
<div class="row">
<div class="large-6 medium-8 small-10 columns">
@Html.LabelFor(x => x.EmailAddress)<span class="required">*</span>
@Html.TextBoxFor(x => x.EmailAddress, new Dictionary<string, Object> { { "required", "" }, { "pattern", "email" } })
<small class="error">A valid email address is required.</small>
@Html.ValidationMessageFor(x => x.EmailAddress)
</div>
</div>
<div class="row">
<div class="large-10 medium-12 small-12 columns">
@Html.LabelFor(x => x.Message)<span class="required">*</span>
@Html.TextAreaFor(x => x.Message, new Dictionary<string, Object> { { "required", "" }, { "rows", "5" } })
<small class="error">Don't forget to enter a message.</small>
@Html.ValidationMessageFor(x => x.Message)
</div>
</div>
</fieldset>
<div class="row">
<div class="large-12 columns">
<input type="submit" class="button" value="Submit" />
</div>
</div>
}
Finally, we’ll add a template on which we’ll display our partial view.
Settings
in Umbraco back office, create a template named Contact
.@inherits Umbraco.Web.Mvc.UmbracoTemplatePage
@{
Layout = "\_Layout.cshtml";
}
<header>
<div class="row">
<div class="large-12 columns">
<h1>
@Umbraco.Field("headline")
</h1>
<h3>@Umbraco.Field("tagline")</h3>
</div>
</div>
</header>
<div class="row">
<div class="large-12 columns">
<section class="page-container">
@{
if (ViewBag.Contact != null)
{
var viewModel = (YourProjectName.Models.ContactViewModel)ViewBag.Contact;
<div class="row">
<div class="large-8 medium-7 small-12 columns">
<h2>
Thanks for the message
</h2>
<div class="contact-confirmation">
<p>
@Html.Raw(Umbraco.ReplaceLineBreaksForHtml(viewModel.Message))
</p>
<p>
@viewModel.Name (@viewModel.EmailAddress)
</p>
</div>
</div>
</div>
}
else
{
<div class="row">
<div class="large-8 medium-7 small-12 columns">
@Html.Partial("ContactForm", new YourProjectName.Models.ContactViewModel())
</div>
</div>
}
}
</section>
</div>
</div>