Creating a contact form with ASP.NET MVC
Posted on May 13, 2010 by Frederik Vig in ASP.NET, JavaScriptWe’re going to create a contact form in ASP.NET MVC 2.0, that uses Ajax to send the form data and that uses client side validation to improve the user experience for our users.
Start by creating a new ASP.NET MVC 2.0 web application project in Visual Studio.
This will create a new project with the default ASP.NET MVC 2.0 sample code.
Inside the Models folder create a new class, and give it the name: Contact.cs. The class is very simple with just some properties for Name, Email and Comment.
using System.ComponentModel; using System.ComponentModel.DataAnnotations; namespace ContactForm.Models { public class Contact { [Required(ErrorMessage = "You need to fill in a name")] [DisplayName("Name")] public string Name { get; set; } [Required(ErrorMessage = "You need to fill in an email address")] [DataType(DataType.EmailAddress, ErrorMessage = "Your email address contains some errors")] [DisplayName("Email address")] public string Email { get; set; } [Required(ErrorMessage = "You need to fill in a comment")] [DisplayName("Your comment")] public string Comment { get; set; } } } |
Notice the Required, DisplayName and DataType attributes. This is called DataAnnotations, and is a new feature in ASP.NET MVC 2.0, which helps us add validation logic to our models.
Next step is creating the /home/contact URL and the contact view. Open up HomeController.cs, and add the following method.
public ActionResult Contact() { return View(); } |
Place your cursor inside View() and press Ctrl+M, Ctrl+V, or just right-click and choose Add View. Check the “Create a strongly-typed view” and type in: ContactForm.Models.Contact.
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<ContactForm.Models.Contact>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Contact </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2>Contact</h2> </asp:Content> |
We can now create the form markup.
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<ContactForm.Models.Contact>" %> <asp:Content ContentPlaceHolderID="TitleContent" runat="server"> Contact us </asp:Content> <asp:Content ContentPlaceHolderID="MainContent" runat="server"> <% Html.EnableClientValidation(); %> <% using (Ajax.BeginForm(new AjaxOptions { HttpMethod = "Post", OnComplete = "Contact.onComplete"})) { %> <%: Html.ValidationSummary(true, "A few fields are still empty") %> <fieldset> <legend>Contact us</legend> <div class="editor-label"> <%: Html.LabelFor(m => m.Name) %> </div> <div class="editor-field"><%: Html.TextBoxFor(m => m.Name) %> <%: Html.ValidationMessageFor(m => m.Name) %> </div> <div class="editor-label"> <%: Html.LabelFor(m => m.Email) %> </div> <div class="editor-field"> <%: Html.TextBoxFor(m => m.Email) %> <%: Html.ValidationMessageFor(m => m.Email) %> </div> <div class="editor-label"> <%: Html.LabelFor(m => m.Comment) %> </div> <div class="editor-field"> <%: Html.TextAreaFor(m => m.Comment, 10, 25, null) %> <%: Html.ValidationMessageFor(m => m.Comment) %> </div> <p> <input type="submit" value="Submit" /> </p> </fieldset> <p id="result"><%: TempData["Message"] %></p> <% } %> </asp:Content> |
<%: … %> is just a shortcut for HTML encoding the data, a new feature in ASP.NET 4.0. <% Html.EnableClientValidation(); %> enables client side validation for us, and must be included right before the start of the form. Ajax.BeginForm is a helper method that generates the form tag for us and attaches a little JavaScript code for sending the form data with Ajax, if the client supports it, otherwise the form data will be sent like normal.
Lets create the JavaScript method that gets called when the form is finished. Create a new JavaScript file inside the Scripts folder and give it the name: Site.js. Add the Contact object with the property function onComplete.
var Contact = { onComplete: function (content) { var result = eval(content.get_response().get_object()); var textNode = document.createTextNode(result.message); document.getElementById("result").appendChild(textNode); } }; |
I take the JSON result from the server and add the message to the result paragraph.
If you press F5, the site should open up in your default browser. If you add Home/Contact behind the URL, you should be taken to the Contact Us page.
For the client side validation to work we need to reference a few JavaScript files. Open up Site.master (located in the shared folder), and add the following code right before the closing body tag.
... <script src="../../Scripts/MicrosoftAjax.js" type="text/javascript"></script> <script src="../../Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script> <script src="../../Scripts/MicrosoftMvcValidation.js" type="text/javascript"></script> <script src="../../Scripts/Site.js" type="text/javascript"></script> </body> </html> |
You should now receive some friendly error messages when you click the submit button without filling out the form properly.
Next step is adding the action method to HomeController.cs that will handle the form data.
[HttpPost] public ActionResult Contact(Contact model) { string message = "There are a few errors"; if (ModelState.IsValid) { message = "Thanks! We'll get back to you soon."; } if (Request.IsAjaxRequest()) { return new JsonResult { ContentEncoding = Encoding.UTF8, Data = new { success = true, message = message } }; } TempData["Message"] = message; return View(); } |
Notice that I check if the request is an Ajax request, if it is I return a JSON object with the result, otherwise I return the whole view with the message.
You would also add some other logic here for saving the message in some way.
That’s it!
Roger says:
Post Author August 17, 2010 at 16:32Hi Frederick,
I’ve tried to replicate this but i get a 404 error when I try to navigate to my contact page.
Also I had to add a couple of declarations to HomeController.cs:-
using .model;
using System.text;
If I comment out ‘[HttpPost]’ in the HomeController, the page displays but with all of ther error messages showing.
Where do i put the address to send the email to, and or any CC or BCC options?
Can you please advise.
thanks in advance
Roger
roman says:
Post Author February 18, 2011 at 13:14nice, will use this for my website 🙂
however, your solution allowed me to fill in “r” in the email address field. therefore I added this regex check in the contact model for the email address:
[RegularExpression(@”[A-Za-z0-9._%+-][email protected][A-Za-z0-9.-]+\.[A-Za-z]{2,4}”, ErrorMessage = “Your email address contains some errors.”)]
Bryan says:
Post Author February 20, 2011 at 20:01Very nice, clean, clear tutorial. Excellent work, thanks!
Hardy Wang says:
Post Author March 16, 2011 at 04:10Very nice, exactly what I am looking for. Thanks!
Paul says:
Post Author March 16, 2011 at 12:16Nice but I stuck by doing all this sftuff in razor I get compilation error on this line:
@Html.EnableClientValidation();
what I’m doing wrong? or this can’t be used for razor?
Thanks
Lady Z says:
Post Author April 1, 2011 at 12:34What is the m variable for? You never explained it in this tutorial (which was, otherwise, very good).
Terry Cone says:
Post Author May 7, 2011 at 03:05Great information.
If you have time would you please explain how to add the code that will actually send the email.
I really appreciate your time.
Cheers,
Terry
Suze says:
Post Author May 24, 2011 at 15:12Nice clean solution. Thank you.
P11D says:
Post Author August 14, 2011 at 01:35@Paul
Razor:
@{Html.EnableClientValidation();}
@using (Ajax.BeginForm(new AjaxOptions { HttpMethod = “Post”, OnComplete = “Contact.onComplete” }))
{
Html.ValidationSummary(true, “A few fields are still empty”);
}
David says:
Post Author April 8, 2012 at 16:20Thank you, but what use is this to me when it really does nothing? It prepares for sending the message but to where is nowhere to be explained.
Jose Quinones says:
Post Author April 25, 2012 at 06:08Nice, thanks for this post. I found it easy to convert to a razor format and still use your structure. Here’s the code to my view based on the original code. Nice work!
@model RequestPortal.Models.Contact
@{
ViewBag.Title = “Email”;
Layout = “~/Views/Shared/_Layout.cshtml”;
}
@{ Html.EnableClientValidation(); }
@using (Ajax.BeginForm(new AjaxOptions { HttpMethod = “Post”, OnComplete = “Contact.onComplete” }))
{
@Html.ValidationSummary(true, “A few fields are still empty”)
Contact us
@Html.LabelFor(@model => @model.Name)
@Html.TextBoxFor(@model => @model.Name)
@Html.ValidationMessageFor(@model => @model.Name)
@Html.LabelFor(@model => @model.Email)
@Html.TextBoxFor(@model => @model.Email)
@Html.ValidationMessageFor(m => m.Email)
@Html.LabelFor(@model => @model.Comment)
@Html.TextAreaFor(@model => @model.Comment, 10, 25, null)
@Html.ValidationMessageFor(@model => @model.Comment)
@ViewBag.Message
}
var Contact = {
onComplete: function (content) {
var result = eval(content.get_response().get_object());
var textNode = document.createTextNode(result.message);
document.getElementById(“result”).appendChild(textNode);
}
};