Geeks With Blogs

News
Joe Mayo Devices and Things

Many sites have a contact form, instead of posting email addresses.  Admittedly, email addresses are convenient for customers because they can use a mailto link that brings up their email client and allow them to start typing, archive the communication, and manage the thread.  When I first started C# Station, that’s what I did; posted my email address for everyone.  Holy cow, what a mistake.  I received so much spam that my inbox was unusable. Fortunately, spam is more manageable these days, but it’s still a problem.  Therefore, C# Station takes a balanced approach by allowing people to contact me, yet protect my email address.  The following shows how I built the new contact form with ASP.NET MVC 3.

The Controller

Previously, I blogged about the organization of my site and how the About page was the last menu item. What I’m doing now is hanging the Contact menu item off About, along with other miscellaneous subjects like Terms, Contribute, and LinkToMe. Therefore, I created an About controller to group these items together:

using System.Web.Mvc;
using CssMvc.Library;
using CssMvc.Models;

namespace CssMvc.Controllers
{
    public class AboutController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult Contact()
        {
            return View(new ContactViewModel());
        }

        [HttpPost]
        public ActionResult Contact(ContactViewModel contactVM)
        {
            if (!ModelState.IsValid)
            {
                return View(contactVM);
            }

            var contact = new Contact
            {
                From = contactVM.From,
                Subject = contactVM.Subject,
                Message = contactVM.Message
            };

            new Email().Send(contact);

            return RedirectToAction("ContactConfirm");
        }

        public ActionResult ContactConfirm()
        {
            return View();
        }

        public ActionResult LinkToMe()
        {
            return View();
        }

        public ActionResult Contribute()
        {
            return View();
        }

        public ActionResult Terms()
        {
            return View();
        }
    }
}

As you can see, there is a parameterless Contact action whose purpose is to display a Contact view. There’s also a Contact action, with a ContactViewModel parameter that I’ll return to later. Right now, take a look at the parameterless Contact, which shows a blank contact form, it passes a new instance of ContactViewModel, which is empty, to the View.  If you’ve been working with ASP.NET MVC, this is nothing different than what you’ve seen before.  Let’s take an closer look at ContactViewModel.

The Model

“Model” is one of those overloaded and overused buzzwords that software engineers love to sprinkle into conversation. Okay, I love to say “Model”  because it makes me sound like I know what I’m talking about. Anyway, I like to suffix my model names with ViewModel, which is what plenty of other people do too.  Since I wanted  a form with contact data, I called my object ContactViewModel and coded it like this:

using System.ComponentModel.DataAnnotations;

namespace CssMvc.Models
{
    public class ContactViewModel
    {
        [Required]
        [DataType(DataType.EmailAddress)]
        public string From { get; set; }

        [Required]
        public string Subject { get; set; }

        [Required]
        public string Message { get; set; }
    }
}

ContactViewModel doesn’t show anything new. The annotations feature was introduced in MVC 2.  It’s a simple ViewModel, but it does reflect what I want to show on my screen.  As you know, email messages have many more fields than shown here.  The trick is to only use what you need in the ViewModel and let’s its purpose be presentation driven. Speaking of presentation, let’s see what the form looks like.

The View

So far, if already accustomed to MVC 2, you haven’t seen anything new. However, now I’ll show you the View, which uses the new MVC 3 Razor view engine. This view displays a Contact form that lets the user enter a From address, Subject, and Message; the same data items you saw in the ContactViewModel:

@model CssMvc.Models.ContactViewModel

@{
    View.Title = "Contact Joe Mayo";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Contact Joe Mayo</legend>
        <div class="editor-label">
            @Html.LabelFor(model => model.From)
        </div>
        <div class="editor-field">
            @Html.TextBoxFor(model => model.From)
            @Html.ValidationMessageFor(model => model.From)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.Subject)
        </div>
        <div class="editor-field">
            @Html.TextBoxFor(model => model.Subject)
            @Html.ValidationMessageFor(model => model.Subject)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.Message)
        </div>
        <div class="editor-field">
            @Html.TextBoxFor(model => model.Message)
            @Html.ValidationMessageFor(model => model.Message)
        </div>
        <p>
            <input type="submit" value="Send" />
        </p>
    </fieldset>
}

Besides my personal branding, the first thing you might notice is that the Razor view engine is much cleaner than the ASPX view engine. Binding directives, “<%= … %>”, are replaced by "@…”. The helpers and logic are the same.  MVC 3 has more helpers, but I’m not covering those in this post.

Notice the @model directive at the top of the View. This is the new way to specify that this is a strongly typed view.  It’s new for the latest release of MVC 3 also because the strongly typed view syntax was more verbose in the previous MVC3 release. @ScottGu does a good job of covering Razor in his blog and in subsequent posts.

A code block, denoted by “@{ … }”, follows the @model directive, where you can write multiple lines of code.  View.Title demonstrates a new feature in Razor, using the new dynamic type feature added to C# 4.0.  There is no Title property on View. Behind the scenes, the syntax is really View[“Title”], which you would have used in MVC 2; more discussion later to round out the picture and show how this is used.  Layout is analogous to an ASPX Master page and I’ll discuss that in a moment.

A very nice feature of Razor is that you don’t need to block off normal code with <% and %>. As demonstrated by the using statement, all you need to do is use the @ prefix, as in @using, and Razor will recognize the difference between code and HTML. This was a normal *.cshtml View page; layout pages, which I breezed over, use similar syntax.

The Layout Page

Instead of Master pages, Razor has Layout pages. Many of the concepts between Master and Layout are the same, except for the syntax. In your VS 2010 project structure, Layout pages reside in Views\Shared, just like Master pages.  Here’s the (work in progress) Layout page for C# Station:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>@View.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
</head>

<body>
    <div class="page">

        <div id="header">
            <div id="title">
                <h1>C# Station</h1>
            </div>

            <div id="logindisplay">
                @Html.Partial("_LogOnPartial")
            </div>

            <div id="menucontainer">

                <ul id="menu">
                    <li>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li>@Html.ActionLink("About", "Index", "About")</li>
                    <li>@Html.ActionLink("Contact", "Contact", "About")</li>
                </ul>

            </div>
        </div>

        <div id="main">
            @RenderBody()
            <div id="footer">
            </div>
        </div>
    </div>
</body>
</html>

If you recall from the last section, I discussed how the Title in View.Title was using the dynamic typing features in C#. In the <head> you can see how <title> is set, using this dynamic type.  This  is easier to type, read, and eliminates needing to explicitly use string indexes.

Again, you can see how the @Url and @Html syntax helps reduce typing and results in cleaner code.

The linkage between View and Layout occurs at @RenderBody().  The View specifies what the Layout is and the Layout page specifies where where the contents of the view are rendered. There are more Layout features that allow you to define where parts of the View render for more sophisticated scenarios, but what you’re seeing here covers many situations, is minimal syntax, and very simple.

Next, we’ll take a step back to the controller so we can round out the discussion with the business logic that makes this Contact form work.

The Business Logic

Clicking the input button, from the code in the previous section on The View, posts the form contents to the Contacts action in the About controller, repeated here for your convenience:

        [HttpPost]
        public ActionResult Contact(ContactViewModel contactVM)
        {
            if (!ModelState.IsValid)
            {
                return View(contactVM);
            }

            var contact = new Contact
            {
                From = contactVM.From,
                Subject = contactVM.Subject,
                Message = contactVM.Message
            };

            new Email().Send(contact);

            return RedirectToAction("ContactConfirm");
        }

I can validate the model because of the annotations in ContactViewModel. If the model is valid, I populate the business object, of type Contact, which is passed to the Send method of an instance of another custom business object named Email. Here’s Contact:

namespace CssMvc.Library
{
    public class Contact
    {
        public string From { get; set; }

        public string Subject { get; set; }

        public string Message { get; set; }
    }
}

You can see that Contact looks nearly identical to ContactViewModel. A common question is “Why duplicate the same object in two places?”. Really, this isn’t duplication. ContactViewModel has annotations that are only meaningful in the presentation layer. You don’t want annotations in your business objects because it makes them only usable in a context that understands the annotations. Before you ding me for splitting hairs, there’s more to the value of separating the ViewModel from the business model.

You can’t see it in this example, because both objects contain the same fields, but in most scenarios the ViewModel differs in content and structure from the business model.  The business logic will often return a set of data in a shape that is either flat or separated from different calls into business logic. However, the ViewModel should shape the data for how it will appear on the screen.  If you let me wave my hands for a moment -- you could have some basic information, such as a Product defined by fields in a ProductViewModel, and then have details of that product in a List<ProductDetailViewModel>. Coming from your repository, this data might be separate and you would need to combine it into a single ViewModel object, in a form that mirrors the HTML layout in the View. 

Another aspect to be aware of is that the business model will often contain more data than the view requires. Model binding is an automatic process (can be custom, but that’s orthogonal to the point I’m trying to make) and you don’t want to waste CPU cycles on trying to bind business object fields that aren’t being used.

You might then wonder, “What if you wrote the business logic to return the data in the right shape?”.  However, that’s just plain bass-ackwards to proper architecture and design because the business logic shouldn’t have any knowledge of the presentation layer.  Besides, like annotations, that would tie your business logic to a particular implementation, precluding reuse. To continue the focus on separate business logic, here’s the Email implementation:

using System.Configuration;
using System.Net.Mail;

namespace CssMvc.Library
{
    public class Email
    {
        public void Send(Contact contact)
        {
            MailMessage mail = new MailMessage(
                contact.From,
                ConfigurationManager.AppSettings[Keys.ContactToEmail],
                contact.Subject,
                contact.Message);

            new SmtpClient().Send(mail);
        }
    }
}

My mail server configuration is in Web.config system.net\mailSettings and Keys is a class I use to add a set of const string fields to avoid string typos in my code. Frequently, I’ll encounter a need to send email in different configurations, so it’s just easy to create an Email class and group the different email methods in one place.

Notice the CssMvc.Library namespace (Css means C# Station, in case you were subliminally confused with some other meaning), which implies a separation between the MVC code and the business logic. In fact, the separation is explicit because I put the business logic in a separate class library. This is handy for a number of reasons, but I’ll leave that for another discussion; I personally like the explicit separation between presentation and business logic.

Summary

You’ve seen how I created a simple Contact form, combining current MVC 2 coding techniques with new MVC 3 features. The most noticeable change in MVC 3 is the Razor view engine.  As you see, the coding experience is quicker and cleaner.  I’d also like to give honorable mention to the clever use of dynamic typing, as demonstrated with the View.Title property, which makes View model dictionary access easier to create and read.  I finally got around to discussing my views on separation of presentation and business logic by describing why I think the ViewModel should be separate from the business model and how I place business logic into a separate library.  Most of the code shown here is on the Happy Path, except for field validation, but it simplified the example and hopefully let me share something you might find useful.

Joe

Posted on Saturday, October 30, 2010 6:27 PM C# , ASP.NET MVC | Back to top


Comments on this post: An MVC 3 Contact Form

# Great post
Requesting Gravatar...
Great topic, detailed walkthrough. I'm enjoying it!
Left by Lei on Nov 17, 2010 8:24 AM

# re: An MVC 3 Contact Form
Requesting Gravatar...
It's a good write up and exactly what i was looking for, thanks. I'm not sold on the separation of view model and business model purely because of the data annotations though. I don't think those data annotations are only a presentation thing. They describe the data, which is a major idea behind a data model. Sure they're used to provide presentation validation to the end user, but they could equally be used in the business or data layer to validate the same data before saving to a database for example. This could be especially helpful where the presentation layer and business layer are physically seperate and data passed between the two can't be trusted. In a pure data sense (ie getting away from UI) SQL provides these same kind of attributes (required, field types, etc.) to model data. I also think there could be a case for having one complete data model as the source of truth for the whole application.
Left by Frank on Dec 21, 2010 2:56 AM

# re: An MVC 3 Contact Form
Requesting Gravatar...
I want to know if this code is ready to use ,or there is some thing to add because I have not understand how it's can work without contact Email ,sorry but I am just a beginner and it's my first MVC application and I really need to this for my contact page
Left by saloua on Aug 23, 2014 12:11 PM

Your comment:
 (will show your gravatar)


Copyright © Joe Mayo | Powered by: GeeksWithBlogs.net | Join free