Liking this new Razor build! Looks like there's a lot to learn from it.
I wanted to add a simple drop down list of options to your form and wondered if you might be able to point me in the right direction?
I could just add a <select> tag but the reason I'm getting stuck is I still need to give it a value for the later functions in your script, i.e. adding it to the email and storing it.
I want to add something like:
@Html.DropDownList ("toothpaste", [get my list of toothpastes], form.Toothpaste)
I just don't know how to set the list of toothpastes (in this case). I'd like to keep it as simple as possible and set it within your macro script if possible.
Hi Jorge, many thanks for this. It's really appreciated.
Although this is very useful, I think I need to do something a lot simpler and just list a set of options, which I'd like to hard code within your contact form macro script.
Could you give me a pointer there? Obviously don't want to take up much of your time...
I have the value of my Toothpaste drop down list selection now being written to the email I received.
However if I add the string to the log contact form strings I get an error.
I've added the string as per...
// Log the item to the XML file var filePath = Server.MapPath("~/App_Data/contact_form_log.xml"); filePath.LogContactForm(strName, strToothpaste, strAddressLine1, strAddressLine2, strEmailFrom, strMessage);
But if I do this the script won't load and I find this error using Umb Debug:
CS1501: No overload for method 'LogContactForm' takes 6 arguments
Is this something I can fix? I've looked through your script but I can't find anything obvious. Is the LogContactForm method defined elsewhere?
The other option is to replace the logic in the "function" section in the Razor view. Example:
@using System.Text
@using System.Xml
@using Creative.Website.Starter
@using umbraco.MacroEngines
@inherits DynamicNodeContext
@{
dynamic form = Context.Request.Form.ToDynamic();
var valDic = new Dictionary<string, string>
{
{"forgery", "Invalid post"},
{"name", "Please enter your name"},
{"email", "Please enter a email"},
{"email-regex", "Please enter a valid e-mail address"},
{"enquiry", "Please enter a message"}
};
if (IsPost)
{
if (!Context.IsValidAntiForgery()) { ModelState.AddFormError(valDic["forgery"]); }
if (MainHelper.IsEmpty(form.Name)) { ModelState.AddError("name", valDic["name"]); }
if (MainHelper.IsEmpty(form.Name)) { ModelState.AddError("email", valDic["email"]); }
if (!MainHelper.IsEmail(form.Email)) { ModelState.AddError("email", valDic["email-regex"]); }
if (MainHelper.IsEmpty(form.Enquiry)) { ModelState.AddError("enquiry", valDic["enquiry"]); }
}
if (!IsPost || !ModelState.IsValid)
{
<form method="post" action="@Node.Url">
<div class="clearfix form">
<div class="left text">
@Html.Raw(library.RemoveFirstParagraphTag(Model.FormText.ToString()))
@if (!IsPost && ModelState.IsValid)
{
// force a ValidationSummary placeholder for client side validation
<div class="validation-summary-valid" data-valmsg-summary="true">
<ul><li style="display:none"></li></ul>
</div>
}
else
{
// For use in case cannot validate client side
@Html.ValidationSummary(new Dictionary<string, object> { { "data-valmsg-summary", "true" } })
}
</div>
<div class="left fields">
<fieldset>
<legend>Enquiry Form</legend>
@Html.Label("Name", "name")
@Html.TextBox("name", form.Name, new Dictionary<string, object>
{
{"class", !ModelState.IsValidField("name") ? "error" : string.Empty},
{"data-val", "true"},
{"data-val-required", valDic["name"]}
})
<br />
@Html.Label("Address", "address1")
@Html.TextBox("address1", form.Address1)
@Html.Label("Address Line 2", "address2", new { @class = "hide" })
@Html.TextBox("address2", form.Address2)
<br />
@Html.Label("Email Address", "email")
@Html.TextBox("email", form.Email, new Dictionary<string, object>
{
{"class", !ModelState.IsValidField("email") ? "error" : string.Empty},
{"data-val", "true"},
{"data-val-regex", valDic["email-regex"]},
{"data-val-regex-pattern", MainHelper.EmailRegex},
{"data-val-required", valDic["email"]}
})
<br />
@Html.Label("Enquiry", "enquiry")
@Html.TextArea("enquiry", form.Enquiry, new Dictionary<string, object>
{
{"rows", 5},
{"cols", 25},
{"class", !ModelState.IsValidField("enquiry") ? "error" : string.Empty},
{"data-val", "true"},
{"data-val-required", valDic["enquiry"]}
})
<br />
@{var toothpaste = new List<SelectListItem>()
{
new SelectListItem(){ Text = "Colgate", Value= "1", Selected = false},
new SelectListItem(){ Text = "Oral B", Value= "2", Selected = false},
new SelectListItem(){ Text = "Aquafresh", Value= "3", Selected = false}
};
@Html.DropDownList("toothpaste", toothpaste)
<br/>
@Context.GetAntiForgeryHtml()
<button id="SubmitForm" type="submit">Submit Enquiry</button>
</fieldset>
</div>
</div>
</form>
}
else
{
var ok = LogAndSend(form);
if (!ok)
{
<div id="errorMailSettings">
We are sorry but we coould not send the form request. Please contact us at (0) 207 123456789.
</div>
}
else
{
// Set Thankyou text from our contact node
<div id="thankYou">
<h2>@Model.ThankYouHeaderText</h2>
@Model.ThankYouMessageText
</div>
}
}
}
@functions
{
public bool LogAndSend(dynamic form)
{
// Get the variables from the form and set them in strings
string strName = Html.Encode(form.Name);
string strAddressLine1 = Html.Encode(form.Address1);
string strAddressLine2 = Html.Encode(form.Address2);
string strEmailFrom = Html.Encode(form.Email);
string strMessage = Library.StripHtml(form.Enquiry).ToString();
string strToothpaste = form.Toothpaste;
// Log the item to the XML file
var filePath = Server.MapPath("~/App_Data/contact_form_log.xml");
LogContactFormAndToothpaste(filePath, strName, strAddressLine1, strAddressLine2, strEmailFrom, strMessage, strToothpaste);
// Lets set the values passed in from the Macro
string strEmailTo = Model.EmailTo.ToString();
string strEmailSubject = Model.EmailSubject.ToString();
var now = DateTime.Now;
var strTime = String.Format("{0:HH:mm:ss}", now);
var strDate = String.Format("{0:dd/MM/yyyy}", now);
// Lets Replace the placeholders in the email message body
var strEmailBody = new StringBuilder(Model.EmailBody.ToString());
strEmailBody.Replace("[Name]", strName); // Find and Replace [Name]
strEmailBody.Replace("[AddressLine1]", strAddressLine1); // Find and Replace [AddressLine1]
strEmailBody.Replace("[AddressLine2]", strAddressLine2); // Find and Replace [AddressLine2]
strEmailBody.Replace("[Email]", strEmailFrom); // Find and Replace [Email]
strEmailBody.Replace("[Message]", strMessage); // Find and Replace [Message]
strEmailBody.Replace("[Time]", strTime); // Find and Replace [Time]
strEmailBody.Replace("[Date]", strDate); // Find and Replace [Date]
// Now the email is sent out to the owner, lets send out an email
// to let the user know we have recieved their email & will respond shortly
string strEmailReplySubject = Model.EmailReplySubject.ToString();
var strEmailReplyBody = new StringBuilder(Model.EmailReplyBody.ToString());
strEmailReplyBody.Replace("[Name]", strName); // Find and Replace [Name]
return MainHelper.TrySendMail(strEmailTo, strEmailSubject, strEmailBody.ToString()) && MainHelper.TrySendMail(strEmailFrom, strEmailReplySubject, strEmailReplyBody.ToString());
}
public static void LogContactFormAndToothpaste(string filePath, string strName, string strAddressLine1, string strAddressLine2, string strEmail, string strMessage, string strToothpaste)
{
var now = DateTime.Now;
var strTime = String.Format("{0:HH:mm:ss}", now);
var strDate = String.Format("{0:dd/MM/yyyy}", now);
// Check if XML file exists
if (!File.Exists(filePath))
{
// XML file DOES not exist yet.
// Create a new XmlTextWriter instance and set the XML writer to indent the XML as opposed to all one line.
using (var writer = new XmlTextWriter(filePath, Encoding.UTF8) { Formatting = Formatting.Indented })
{
writer.WriteStartDocument(); // start writing XML!
writer.WriteStartElement("logs"); // Create the <logs> root XML node
writer.WriteStartElement("log"); // Creating the <log> node
writer.WriteAttributeString("time", strTime); // Adding the time attribute to the <log> node. <log time="14:52:23">
writer.WriteAttributeString("date", strDate); // Adding the date attribute to the <log> node. <log time="14:52:23" date="22/02/2009">
writer.WriteStartElement("field"); // Creating the <field> node inside the <log> node
writer.WriteAttributeString("alias", "name"); // Add the alias attribute to the <field> node. <field alias="name">
writer.WriteString(strName); // Write value of the field node.
writer.WriteEndElement(); // Close the <field> node inside the <log> node
writer.WriteStartElement("field"); // Creating the <field> node inside the <log> node
writer.WriteAttributeString("alias", "addressLine1"); // Add the alias attribute to the <field> node. <field alias="addressLine1">
writer.WriteString(strAddressLine1); // Write value of the field node.
writer.WriteEndElement(); // Close the <field> node inside the <log> node
writer.WriteStartElement("field"); // Creating the <field> node inside the <log> node
writer.WriteAttributeString("alias", "addressLine2"); // Add the alias attribute to the <field> node. <field alias="addressLine2">
writer.WriteString(strAddressLine2); // Write value of the field node.
writer.WriteEndElement(); // Close the <field> node inside the <log> node
writer.WriteStartElement("field"); // Creating the <field> node inside the <log> node
writer.WriteAttributeString("alias", "email"); // Add the alias attribute to the <field> node. <field alias="email">
writer.WriteString(strEmail); // Write value of the field node.
writer.WriteEndElement(); // Close the <field> node inside the <log> node
writer.WriteStartElement("field"); // Creating the <field> node inside the <log> node
writer.WriteAttributeString("alias", "message"); // Add the alias attribute to the <field> node. <field alias="message">
// Here we add the toothpaste
writer.WriteStartElement("field"); // Creating the <field> node inside the <log> node
writer.WriteAttributeString("alias", "toothpaste"); // Add the alias attribute to the <field> node. <field alias="message">
writer.WriteCData(strToothpaste); // Write value of the field node, wrapped inside a CData tag
writer.WriteCData(strMessage); // Write value of the field node, wrapped inside a CData tag
writer.WriteEndElement(); //Close the <field> node inside the <log> node
writer.WriteEndElement(); //Close the <log> node
writer.WriteEndDocument(); //Close the <logs> node
}
}
else
{
// XML file already exists so lets add to the XML file.
// Open up the XML file we already have.
var xmlDoc = new XmlDocument();
xmlDoc.Load(filePath);
XmlElement logNode = xmlDoc.CreateElement("log"); // Create a new XML <log> node
logNode.SetAttribute("time", strTime); // Adding the time attribute to the <log> node. <log time="14:52:23">
logNode.SetAttribute("date", strDate); // Adding the date attribute to the <log> node. <log time="14:52:23" date="22/02/2009">
XmlElement fieldNodeName = xmlDoc.CreateElement("field"); // Create a new xml <field> node
fieldNodeName.SetAttribute("alias", "name"); // Add the alias attribute to the <field> node. <field alias="name">
fieldNodeName.InnerText = strName; // Write value of the field node.
logNode.AppendChild(fieldNodeName); // Add our <field> node to our <log> node
XmlElement fieldNodeAddressLine1 = xmlDoc.CreateElement("field"); // Create a new xml <field> node
fieldNodeAddressLine1.SetAttribute("alias", "addressLine1"); // Add the alias attribute to the <field> node. <field alias="addressLine1">
fieldNodeAddressLine1.InnerText = strAddressLine1; // Write value of the field node.
logNode.AppendChild(fieldNodeAddressLine1); // Add our <field> node to our <log> node
XmlElement fieldNodeAddressLine2 = xmlDoc.CreateElement("field"); // Create a new xml <field> node
fieldNodeAddressLine2.SetAttribute("alias", "addressLine2"); // Add the alias attribute to the <field> node. <field alias="addressLine2">
fieldNodeAddressLine2.InnerText = strAddressLine2; // Write value of the field node.
logNode.AppendChild(fieldNodeAddressLine2); // Add our <field> node to our <log> node
XmlElement fieldNodeEmail = xmlDoc.CreateElement("field"); // Create a new xml <field> node
fieldNodeEmail.SetAttribute("alias", "email"); // Add the alias attribute to the <field> node. <field alias="email">
fieldNodeEmail.InnerText = strEmail; // Write value of the field node.
logNode.AppendChild(fieldNodeEmail); // Add our <field> node to our <log> node
XmlElement fieldNodeMessage = xmlDoc.CreateElement("field"); // Create a new xml <field> node
fieldNodeMessage.SetAttribute("alias", "message"); // Add the alias attribute to the <field> node. <field alias="message">
XmlCDataSection fieldNodeCData = xmlDoc.CreateCDataSection(strMessage); // Create a CDATA section that wraps the message text
fieldNodeMessage.AppendChild(fieldNodeCData); // Add our cdata tag/node to our <field> node
// Here we update the toothpaste
XmlElement fieldNodeToothpaste = xmlDoc.CreateElement("field"); // Create a new xml <field> node
fieldNodeToothpaste.SetAttribute("alias", "toothpaste"); // Add the alias attribute to the <field> node. <field alias="email">
fieldNodeToothpaste.InnerText = strToothpaste; // Write value of the field node.
logNode.AppendChild(fieldNodeToothpaste); // Add our <field> node to our <log> node
logNode.AppendChild(fieldNodeMessage); // Add our <field> node to our <log> node
xmlDoc.SelectSingleNode("/logs").AppendChild(logNode); // Add our built up logNode that contains our <field> nodes to the main xml document
xmlDoc.Save(filePath);
}
}
}
Adding a DropDownList
Hi Wazza and chums,
Liking this new Razor build! Looks like there's a lot to learn from it.
I wanted to add a simple drop down list of options to your form and wondered if you might be able to point me in the right direction?
I could just add a <select> tag but the reason I'm getting stuck is I still need to give it a value for the later functions in your script, i.e. adding it to the email and storing it.
I want to add something like:
@Html.DropDownList ("toothpaste", [get my list of toothpastes], form.Toothpaste)
I just don't know how to set the list of toothpastes (in this case). I'd like to keep it as simple as possible and set it within your macro script if possible.
This page seems to be describing something similar, but it's not in a CSHTML file:
http://stackoverflow.com/questions/7409394/html-dropdownlist-mvc3-confusion
Any help you can offer greatly received as ever!
Barney
Do you really want to do this in Razor? Because Umbraco 4 is still webforms it's easier to just do it in a usercontrol. Here is a topic which might be helpful: http://our.umbraco.org/forum/developers/razor/27417-Use-Razor-code-in-UserControl?p=1#comment102639
Jeroen
Hi Jeroen,
I just thought if there was a quick easy way to add one to this form I'd prefer that.
Barney
Here is an example for a Razor contact form in Umbraco: http://our.umbraco.org/projects/website-utilities/cultiv-razor-contact-form. It only uses texboxes, but you can probably also add a dropdown in there.
Jeroen
Cheers for your help Jereon, I'll have a little poke about there and see if it can help me.
Hi Barney,
This is how I would create a dropdown list for the favourite gallery in the contact form:
And this is how it looks
Hope it make sense.
Cheers,
J
Hi Jorge, many thanks for this. It's really appreciated.
Although this is very useful, I think I need to do something a lot simpler and just list a set of options, which I'd like to hard code within your contact form macro script.
Could you give me a pointer there? Obviously don't want to take up much of your time...
Cheers,
Barney
Hi again, is anyone able to help here?
Maybe I'm asking something dumb or too simple and I should really know better :)
Would appreciate any help anyone can offer... hopefully it would help other folk too?
Many thanks,
Barney
Looks like this might do it. Can anyone see any problem to me doing it this way?
Nope, that the way to do it :)
Ok cheers Jorge, I'll have a crack at getting this working through the rest of the functions (the email and the log file).
Will keep you posted :)
Hi Jorge,
Everything is going swimmingly.
I have the value of my Toothpaste drop down list selection now being written to the email I received.
However if I add the string to the log contact form strings I get an error.
I've added the string as per...
But if I do this the script won't load and I find this error using Umb Debug:
CS1501: No overload for method 'LogContactForm' takes 6 arguments
Is this something I can fix? I've looked through your script but I can't find anything obvious. Is the LogContactForm method defined elsewhere?
Cheers,
Barney
Hi Barney,
You should get the sourcecode from http://umbracocws.codeplex.com/ and modify the LogContactForm method located in the MainHelper.cs http://umbracocws.codeplex.com/SourceControl/changeset/view/74490#1670543
Cheers,
J
Hi Jorge,
Normally I wouldn't go near this sort of thing because I'm very much a front end chap.
However, I'm really keen to get this working so it seems I need to roll my sleeves up a bit :)
Would you mind briefly telling me what i should do once I've updated MainHelper.cs?
Can I drop it in the installation of Umbraco I'm running with the CWS package?
Or do I need to do something a bit more complex to compile it? Is this possible on WebMatrix?
Thanks again Jorge, I really do appreciate your taking the time to help me here.
Barney
Hi Barney,
Yes, you need to change the code in the MainHelper.cs and recompile. If you are not using Visual Studio but Webmatrix, I'd recommend you to have a quick look at http://umbraco.com/help-and-support/video-tutorials/getting-started/working-with-webmatrix.aspx.
The other option is to replace the logic in the "function" section in the Razor view. Example:
That's amazing Jorge, thanks very much. I owe you a pint or two! ;)
is working on a reply...