ASP.NET MVC and Revealing Module Pattern

Intro

In this article, we will see how to structure the javascript code using revealing module pattern.

We will create a simple ASP.NET MVC application for demonstration purposes.

It will have one contact form:

Name, Email, and Message fields are required. If some of those fields are empty, the application should paint those fields in red.

If all required fields are filled in, and the user clicks on Submit button, the application will make an AJAX request, clear the form fields and display a message to the user:

We will be using:

  • ASP.NET MVC for server side
  • TwitterBootstrap for front-end
  • Bootbox for popups
  • jquery 1.9.0 for DOM manipulation
  • jquery.validate.js and jquery.validate.unobtrusive for client side validation

The basic code structure

First, we start by creating the Layout.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>@ViewBag.Title</title>

        <!-- Bootstrap -->
        <link href="~/assets/css/bootstrap.min.css" rel="stylesheet">
        <!-- Custom CSS -->
        <link href="~/assets/css/site.css" rel="stylesheet" />

        <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
        <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
        <!--[if lt IE 9]>
            <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
            <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
        <![endif]-->
    </head>
    <body>
        @RenderBody()
        <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
        <!-- Include all compiled plugins (below), or include individual files as needed -->
        <script src="~/assets/js/bootstrap.min.js"></script>
        <script src="~/assets/js/bootbox.min.js"></script>
        <script src="~/assets/js/jquery.validate.min.js"></script>
        <script src="~/assets/js/jquery.validate.unobtrusive.min.js"></script>
        @RenderSection("Scripts", false)
    </body>
</html>

Then we define the view model:

public class MessageViewModel
{
    [Required]
    public string Name { get; set; }

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

    public string Subject { get; set; }

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

controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var viewModel = new MessageViewModel();

        return View(viewModel);
    }

    [HttpPost]
    public JsonResult SendMessage(MessageViewModel viewModel)
    {
        // the logic goes here
        return Json(new { isSuccess = true });
    }
}

and finally, the view:

@model MvcDemo.Controllers.HomeController.MessageViewModel
@{
    ViewBag.Title = "Contact us";
}

<div class="container">
    <h2>@ViewBag.Title</h2>
    <form role="form" id="frmMessage">
        <div class="form-group">
            @Html.LabelFor(x => x.Name)
            @Html.TextBoxFor(x => x.Name, new { @class = "form-control", placeholder = "Enter name" })
        </div>
        <div class="form-group">
            @Html.LabelFor(x => x.Email)
            @Html.TextBoxFor(x => x.Email, new { @class = "form-control", placeholder = "Enter email" })
        </div>
        <div class="form-group">
            @Html.LabelFor(x => x.Subject)
            @Html.TextBoxFor(x => x.Subject, new { @class = "form-control", placeholder = "Enter subject" })
        </div>
        <div class="form-group">
            @Html.LabelFor(x => x.Message)
            @Html.TextAreaFor(x => x.Message, new { @class = "form-control", placeholder = "Enter message" })
        </div>
        <a href="#" id="btnSend" class="btn btn-default">Submit</a>
    </form>    
</div>
@section Scripts
{
    <script>
        // the code goes here
    </script>
}

The code is pretty much straightforward; we can skip to the javascript part.

Basic javascript

We can start by writing the javascript code inside the Scripts section of our view:

@section Scripts
{
    <script>
        var myVariable = // ...
        function myFunction() {
            // ...
        }
    </script>
}

The problem with this code is that myVariable and myFunction belong to the global scope. Which means, if you have more javascript files that have the same variable or function names, you'll get the naming conflicts because you cannot have two global variables or two global functions with the same name.

I also like to keep all javascript code in external .js files because:

a) I can spot the duplicate code more easily
b) I can combine and minify all javascript files into one, use gzip compression, and cache them in browser

Revealing module pattern

Many javascript patterns can solve the naming conflict issues. I like to use revealing module pattern because it's very simple to use.

First, we will create a homepage.js file and reference it in our Layout:

<body>
    @RenderBody()
    ...
    <script src="~/assets/js/homepage.js"></script>
    @RenderSection("Scripts", false)
</body>

And here's the homepage.js:

var homePage = (function() {
    // private variables and functions

    function sendMessage() {
        // collect form data
        var data = {
            name: $('#Name').val(),
            email: $('#Email').val(),
            subject: $('#Subject').val(),
            message: $('#Message').val()
        };

        $.ajax({
            type: 'POST',
            url: '/home/sendmessage',
            data: data
        }).done(function() {
            clearFormFields();
            bootbox.alert('Your message has been sent successfully!');
        }).fail(function() {
            bootbox.alert('Something went wrong.');
        });
    }

    function clearFormFields() {
        $('#Name').val('');
        $('#Email').val('');
        $('#Subject').val('');
        $('#Message').val('');
    }

    var init = function() {
        $('#btnSend').on('click', function(e) {
            // stop click event
            e.preventDefault();
            // stop event bubbling
            e.stopPropagation();

            // check if form is valid
            if ($('#frmMessage').valid()) {
                sendMessage();
            }
        });
    }

    // public API
    return {
        init: init
    };
})();

And then we simply call this code from our view like this:

@section Scripts
{
    <script>
        homePage.init();
    </script>
}

For the end

You can find the full source code on this link: https://github.com/dejancaric/asp.net-mvc-and-revealing-module-pattern

To learn more about javascript design patterns, I recommend this book:
http://addyosmani.com/resources/essentialjsdesignpatterns/book/

Happy coding!

comments powered by Disqus