Skip to content

Instantly share code, notes, and snippets.

@naepalm
Created December 3, 2015 19:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save naepalm/2e2d0fb8ac302fa94a65 to your computer and use it in GitHub Desktop.
Save naepalm/2e2d0fb8ac302fa94a65 to your computer and use it in GitHub Desktop.
Contact Form for Umbraco with a Departments dropdown list. Assumes the dropdown list is NestedContent on the selected Email Template.
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Umbraco.Core.Models;
using Umbraco.Web;
namespace Forms.Web.Models
{
public class ContactForm
{
public int EmailTemplateId { get; set; }
public int ContentId { get; set; }
public string DepartmentEmail { get; set; }
public IEnumerable<IPublishedContent> Departments { get; set; }
public IEnumerable<SelectListItem> DepartmentsSelectList
{
get
{
return Departments != null ? Departments.Where(d => d.WillWork("email") && d.WillWork("headline")).Select(d => new SelectListItem()
{
Value = d.GetPropertyValue<string>("email"),
Text = d.GetPropertyValue<string>("headline")
}) : null;
}
}
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Message { get; set; }
}
}
@using Forms.Web.Controllers
@using Forms.Web
@using Forms.Web.Models
@inherits UmbracoViewPage<ContactForm>
@{
var msgs = (ValidationMessages)ViewBag.ValidationMessages;
@(msgs != null ? RenderValidationMessages(msgs) : RenderForm())
}
@helper RenderValidationMessages(ValidationMessages msgs)
{
if (!msgs.IsSuccessConfirmation)
{
// these should be error messages
if (msgs.Messages.Any(x => !string.IsNullOrEmpty(x)))
{
// Render the error summary
<ul class="errors application-errors">
@foreach (var m in msgs.Messages)
{
<li>@m</li>
}
</ul>
}
// Render the contact form again
@RenderForm()
}
else
{
var template = Umbraco.TypedContent(Model.EmailTemplateId);
if (template.WillWork("confirmation"))
{
@template.GetPropertyValue("confirmation")
}
else
{
<p>Your message has been sent.</p>
}
}
}
@helper RenderForm()
{
using (Html.BeginUmbracoForm<ContactFormController>("ContactFormSubmit", FormMethod.Post, new { @class = "contact-form", @id = "contactForm" }))
{
if (Model.Departments != null) {
<div class="form-group half-size">
@Html.LabelFor(m => m.DepartmentEmail, "Area of Interest")
@Html.DropDownListFor(m => m.DepartmentEmail, Model.DepartmentsSelectList, "Select your interest")
</div>
}
<div class="form-group half-size">
@Html.LabelFor(m => m.Name, "Name")
@Html.TextBoxFor(m => m.Name)
</div>
<div class="form-group half-size">
@Html.LabelFor(m => m.Email, "Email")
@Html.TextBoxFor(m => m.Email)
</div>
<div class="form-group half-size">
@Html.LabelFor(m => m.Phone, "Phone")
@Html.TextBoxFor(m => m.Phone)
</div>
<div class="form-group">
@Html.LabelFor(m => m.Message, "Message")
@Html.TextAreaFor(m => m.Message)
</div>
<div class="form-group">
@Html.HiddenFor(m => m.ContentId)
@Html.HiddenFor(m => m.EmailTemplateId)
</div>
<button type="submit" class="button button--solid-red">Send us a Message</button>
}
}
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using ClientDependency.Core;
using Forms.Web.Helpers;
using Forms.Web.Models;
using Umbraco.Web;
using Umbraco.Web.Mvc;
namespace Forms.Web.Controllers
{
public class ContactFormController : SurfaceController
{
[ChildActionOnly]
public ActionResult RenderForm(ContactForm model)
{
return PartialView("CourseApplicationForm", model);
}
[HttpPost]
[ActionName("ContactFormSubmit")]
public ActionResult ContactFormSubmit(ContactForm model)
{
var messages = new ValidationMessages();
messages.Messages = new List<string>();
if (ModelState.IsValid)
{
// Get the current page from the model
var current = Umbraco.TypedContent(model.ContentId);
// Set the e-mail template, selected on the form page
var emailTemplate = Umbraco.TypedContent(model.EmailTemplateId);
// Exclude non-string fields to enter manually
var excludedFields = new[]
{
"ContentId",
"EmailTemplateId",
"Departments",
"DepartmentEmail",
"DepartmentsSelectList"
};
// These fields may be empty on form submission and therefore not replaced
var optionalFields = new[]
{
"Phone",
"Message"
};
var fields = model.ToDictionary().Where(x => !excludedFields.Contains(x.Key));
// Add the string type fields to the dictionary
var formFields = fields.ToDictionary(field => field.Key, field => field.Value.ToString());
// Add the remaining, empty optional fields as empty strings
foreach (var key in optionalFields.Where(x => !formFields.ContainsKey(x)))
{
formFields.Add(key, string.Empty);
}
// Replace the "%%{0}%%" fields in the e-mail template with their actual values
var bodyContent = EmailHelpers.ReplacePlaceholders(emailTemplate.GetPropertyValue<string>("emailTemplate"), formFields, "%%{0}%%");
var mailVals = new EmailHelpers.MailVariables
{
ToName = model.DepartmentsSelectList.FirstOrDefault(x => x.Value == model.DepartmentEmail) != null ? model.DepartmentsSelectList.FirstOrDefault(x => x.Value == model.DepartmentEmail).Text : "NuWay Website",
From = emailTemplate.WillWork("fromAddress") ? emailTemplate.GetPropertyValue<string>("fromAddress") : "no-reply@nuway.com",
FromName = emailTemplate.WillWork("fromName") ? emailTemplate.GetPropertyValue<string>("fromName") : "NuWay",
Subject = emailTemplate.WillWork("subject") ? emailTemplate.GetPropertyValue<string>("subject") : "Contact Form Email Submission",
BodyContent = bodyContent,
IsHtml = true
};
//send the mail NuWay
mailVals.To = model.DepartmentEmail;
var mailSent = EmailHelpers.TrySendMail(mailVals);
if (mailSent)
{
// set the confirmation flags
messages.IsSuccessConfirmation = true;
//add the validation messages to the ViewData
ViewData["ValidationMessages"] = messages;
//Add current form model to ViewBag
ViewData["Model"] = model;
return CurrentUmbracoPage();
}
messages.IsSuccessConfirmation = false;
// pass the error back to the view
messages.Messages.Add("This form could not be submitted properly. Please contact us by phone and we'll be happy to help you.");
//add the validation messages to the ViewData
ViewData["ValidationMessages"] = messages;
//Add current form model to ViewBag
ViewData["Model"] = model;
return CurrentUmbracoPage();
}
messages.IsSuccessConfirmation = false;
var modelErrors = ModelState;
//Add model errors to Validation Messages
foreach (var fieldError in modelErrors)
{
foreach (var error in fieldError.Value.Errors)
{
messages.Messages.Add(error.ErrorMessage);
}
}
//add the validation messages to the ViewData
ViewData["ValidationMessages"] = messages;
//Add current form model to ViewBag
ViewData["Model"] = model;
return CurrentUmbracoPage();
}
}
}
@using Forms.Web
@using Forms.Web.Models
@inherits UmbracoTemplatePage
@{
Layout = "TwoColumn.cshtml";
var msgs = (ValidationMessages)ViewBag.ValidationMessages;
var formModel = (ContactForm)ViewBag.Model;
}
@Html.Partial("ContactForm", new ContactForm { ContentId = Model.Content.Id, EmailTemplateId = Model.Content.GetPropertyValue<int>("emailTemplate"), Departments = msgs == null ? Model.Content.GetPropertyValue<IEnumerable<IPublishedContent>>("departments") : formModel.Departments })
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using HtmlAgilityPack;
using Umbraco.Core;
using Umbraco.Core.Logging;
namespace Forms.Web.Helpers
{
/// <summary>
/// EmailMessage Helpers
/// </summary>
public static class EmailHelpers
{
/// <summary>
/// Data structure for storing mail related items
/// </summary>
public class MailVariables
{
public MailVariables() { this.IsReady = false; }
public string BodyContent { get; set; }
public string Subject { get; set; }
public string To { get; set; }
public string ToName { get; set; }
public string From { get; set; }
public string FromName { get; set; }
public string ReplyTo { get; set; }
public bool EnableSsl { get; set; }
public bool IsReady { get; set; }
public bool IsHtml { get; set; }
}
/// <summary>
/// Gets mail variables from EmailMessage document type
/// </summary>
/// <param name="id">
/// The node id of the EmailMessage
/// </param>
/// <returns>
/// The <see cref="MailVariables"/>.
/// </returns>
public static MailVariables GetMailVariables(int id)
{
var umbContentService = ApplicationContext.Current.Services.ContentService;
var emf = umbContentService.GetById(id);
MailVariables mailvars = new MailVariables();
try
{
mailvars.From = emf.GetValue<string>("from");
mailvars.FromName = emf.GetValue<string>("fromName");
mailvars.To = emf.GetValue<string>("to");
mailvars.ToName = emf.GetValue<string>("toName");
mailvars.Subject = emf.GetValue<string>("subject");
mailvars.BodyContent = emf.GetValue<string>("content");
mailvars.IsReady = true;
}
catch (Exception ex)
{
var msg = string.Format("Error creating or MailVariables. Exception: {0}", ex.Message);
LogHelper.Error(typeof(EmailHelpers), msg, new Exception(msg));
}
return mailvars;
}
/// <summary>
/// Attempts to send an email with mail variable package passed-in
/// </summary>
/// <param name="package">
/// The The <see cref="MailVariables"/> package.
/// </param>
/// <returns>
/// <see cref="bool"/> indicating successful send.
/// </returns>
public static bool TrySendMail(MailVariables package)
{
try
{
var msg = new System.Net.Mail.MailMessage();
msg.From = new System.Net.Mail.MailAddress(package.From, HttpUtility.HtmlEncode(package.FromName));
msg.Subject = package.Subject;
msg.Body = package.BodyContent;
msg.IsBodyHtml = package.IsHtml;
msg.To.Add(new System.Net.Mail.MailAddress(package.To, package.ToName));
var smtp = new System.Net.Mail.SmtpClient { EnableSsl = package.EnableSsl };
smtp.Send(msg);
return true;
}
catch (Exception ex)
{
var msg = string.Concat("TrySendMail: ", string.Format("Error creating or sending email, exception: {0}", ex.Message));
LogHelper.Error(typeof(EmailHelpers), msg, new Exception(msg));
}
return false;
}
/// <summary>
/// Using a dictionary of replacement keys with their corresponding values,
/// replace the placeholders in the Template content.
/// </summary>
/// <param name="templateContent">The email template content to process.</param>
/// <param name="placeholdersData">The placeholder data Dictionary</param>
/// <param name="templatePattern">The format pattern to indicate placeholders in the template content</param>
/// <param name="escapeHtml">Declare whether or not to escape the HTML</param>
public static string ReplacePlaceholders(string templateContent, Dictionary<string, string> placeholdersData, string templatePattern = "[{0}]", bool escapeHtml = false)
{
StringBuilder templ = new StringBuilder(templateContent);
foreach (var kv in placeholdersData)
{
var placeholder = string.Format(templatePattern, kv.Key);
var val = kv.Value;
if (escapeHtml)
{
val = HttpContext.Current.Server.HtmlEncode(val);
}
templ.Replace(placeholder, val);
}
return templ.ToString();
}
/// <summary>
/// Add an absolute path to all the img tags in the html of an e-mail.
/// </summary>
/// <param name="html"></param>
/// <returns></returns>
public static string AddImgAbsolutePath(string html)
{
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html);
var uri = new Uri(HttpContext.Current.Request.Url.AbsoluteUri);
var domainUrl = string.Format("{0}://{1}", uri.Scheme, uri.Authority);
if (doc.DocumentNode.SelectNodes("//img[@src]") != null)
{
foreach (HtmlNode img in doc.DocumentNode.SelectNodes("//img[@src]"))
{
HtmlAttribute att = img.Attributes["src"];
if (att.Value.StartsWith("/"))
{
att.Value = domainUrl + att.Value;
}
}
}
return doc.DocumentNode.InnerHtml;
}
}
}
namespace Forms.Web.Models
{
using System.Collections.Generic;
public class ValidationMessages
{
public string FormName { get; set; }
public bool IsSuccessConfirmation { get; set; }
public IList<string> Messages { get; set; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment