Javascript And ASP.Net Helpers Are Here To Help

Javascript is an often overlooked language within the development community. A lot developers steer away from Javascript because it is synonymous with client-side programming and design. But it does not have to be scary. Here are a few pointers on how to use Javascript as a helper to C# and MVC.

Javascript and JQuery

JQuery's catch phrase on their website is "The write less, do more, Javascript library". And that sums it up perfectly. JQuery is a library that sits on top of raw Javascript code. In much the same way as a HTML Helper sits over the top of raw C# and HTML. Take this code snippet for example.

@Html.ActionLink("About this Website", "About")
//	This has various uses, depending on the location of the view it appears in
//	For example, if the ActionLink occurs on the /Home/Index.cshtml view, the resulting hyperlink will be
<a href="/Home/About/">About this Website</a>

//	However, if the same ActionLink occurs on the /ContactUs/Index.cshtml view, the resulting hyperlink will be
<a href="/ContactUs/About/">About this Website</a>

This HTML Helper simplifies how to make a simple hyperlink. Not only that, it also means that routing is taken care of (see comments in the above code block). JQuery takes a similar approach to Javascript.

JQuery has a method called .each(). This method simplifies the for loop in Javascript. Here is another example. Both of these approaches will loop through all DIV elements on a page and add the active class to them. The JQuery version has less lines of code, is more succinct and (I think) more descriptive of what is actually happening.

$("div").each(function(){
	$(this).addClass("active");
})

var $divs = document.GetElementByTagName("div");
for(var i = 0; i < divs.length; i++){
    var thisDiv = divs[i];
    thisDiv.className += "active";
}

Let's look at some ways to incorporate Javascript (and JQuery) into our MVC development.

Posting HTML Form Data

MVC includes an HTML Helper to generate a HTML form. Look at this code.

@using (Html.BeginForm("Edit", "Person", FormMethod.Post, new { id = "editPerson" }))
{
	@Html.AntiForgeryToken()
	@Html.HiddenFor(model => model.Id)
	@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-horizontal">
	<div class="form-group">@Html.LabelFor(model => model.FirstName, htmlAttributes: new { @class = "control-label col-md-2" })
		<div class="col-md-10">
			<div class="col-md-10">@Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { @class = "form-control" } })</div>
			<div class="col-md-2">@Html.ValidationMessageFor(model => model.FirstName, "", new { @class = "text-danger" })</div>
		</div>
	</div>
	<div class="form-group">@Html.LabelFor(model => model.LastName, htmlAttributes: new { @class = "control-label col-md-2" })
		<div class="col-md-10">
			<div class="col-md-10">@Html.EditorFor(model => model.LastName, new { htmlAttributes = new { @class = "form-control" } })</div>
			<div class="col-md-2">@Html.ValidationMessageFor(model => model.LastName, "", new { @class = "text-danger" })</div>
		</div>
	</div>
	<div class="form-group">
		<div class="col-md-12 text-right"><input class="btn btn-primary btn-save" type="button" value="Save" /></div>
	</div>
</div>
}

I will go through each of the HTML Helpers in this code block.

  • @Html.BeginForm() - this creates an HTML form block and will include any other HTML Helpers inside it. There are lots of arguments and overloads to this HTML Helper so it is very handy to know.
  • @Html.AntiForgeryToken() - this will add a hidden form field to the form which ASP.Net uses to stop malicious form posts.
  • @Html.HiddenFor(model => model.Id) - this will create a hidden input form field and name it correctly and populate the value. The model argument is the model passed into the View. Therefore, this hidden field will be given an ID and Name attribute of Id and it's value will be the value of the Id field for the selected user in the database.
  • @Html.ValidationSummary(true, "", new { @class = "text-danger" }) - this will create a section within the form where validation errors will be displayed.
  • @Html.LabelFor(model => model.FirstName, htmlAttributes: new { @class = "control-label col-md-2" }) - this will create an HTML label element, set it's ID and Name attributes to FirstName and add the control-label and col-md-2 classes to the element.
  • @Html.EditorFor(model => model.LastName, new { htmlAttributes = new { @class = "form-control" } }) - this will do the same as the point above, except it will create an input element instead.
  • @Html.ValidationMessageFor(model => model.LastName, "", new { @class = "text-danger" }) - this will create an area in the form where validation errors are displayed that are specific to a specific element. For example, when you forget to type your firstname in a field and click submit. The validation engine puts some red text next to that element and reminds you that it is a mandatory field.

There are many more MVC HTML Helpers so you should become familiar with them. Here is a detailed explanation of each.

I mentioned above that MVC HTML Helpers scaffold the HTML elements with the ID and Name of the model field. Once that is done, with the use of the JQuery Validation javascript files, MVC can do validation without posting the form to the server. This is how validation functionality works. For example, say you typed a string into a textbox that was configured to only allow numbers. The validation scripts jump into action as soon as you lose focus on the textbox.

You can even force validation to work from Javascript. Say, for example, you have the above form. But instead of posting it to the controller via HTTP (regular HTTP POST method), you want to send it via AJAX to avoid refreshing the page. You can write a Javascript function that bundles up the form fields and sends them to the Action. But you still want to force the form to be validated first. You can do all of that in a Javascript function. See this code sample.

<script>// <![CDATA[
$(function(){
	$(".btn-save").click(function() {
		//	Firstly, let the JQuery validation routine run
		//	If the form is not validated, return false.
		//	Otherwise, send the requestData to the controller
		if ($("#editPerson").valid()) {
			var requestData = {
				MovieId: "@(Model.Id)",
				FirstName: $("#FirstName").val(),
				LastName: $("#LastName").val(),
			};

			$.ajax({
				url: '@Url.Action("Edit", "Person")',
				type: "POST",
				data: JSON.stringify(requestData),
				contentType: 'application/json; charset=utf-8',
				complete: function() {
					location.href = "@Url.Action("Index")";
				},
				async: true,
				processData: false
			});
		} else
			return false;	
	});
})
// ]]></script>

Custom HTML Helpers

A simple way to create your own HTML Helpers is by using static class methods. A static class is a class that cannot be instantiated. That simply means, you cannot use the new keyword to create a variable of the class's type. This means you can access the members of the class just by using the class name. Let's say we have a static class called DigAHole that has public methods called Shallow, Deep, Infinite. We can call those methods by simply using the class name, then the method. For example, DigAHole.Shallow().

So let's create a static class that we will use as a Helper. All we need to do is create the static class with a public member that returns a string.

public class BootstrapLabel
{
	public static string Label(string target, int colWidth, string text)
	{
		return String.Format("<label class="control-label col-xs-{1} col-sm-{1} col-md-{1} col-lg-{1}" for="{0}">{2}</label>", target, colWidth, text);
	}
}

This will give us a nicely formatted label with the bootstrap layout classes applied.

Another way to create your own HTML Helpers is with Extension Methods. Just as the name suggests, these methods extend existing methods. We discussed earlier that there are lots of HTML Helpers in MVC. We can use those helper methods, and extend them so they are customised to our needs. Extension Methods allow you to add new methods to an existing class. Again, we need to start with a static class and this class name will be our starting point. Let's look at this code.

public static class StringExtension
{
	public static string Format( this string str, params Expression<Func<string,object>>[] args)
	{
		var parameters = args.ToDictionary
							( e=>string.Format("{{{0}}}",e.Parameters[0].Name)
							, e=>e.Compile()(e.Parameters[0].Name));

		var sb = new StringBuilder(str);
		foreach(var kv in parameters)
		{
			sb.Replace( kv.Key
					  , kv.Value != null ? kv.Value.ToString() : "");
		}

		return sb.ToString();
	}
}

So we start with a static class called StringExtension. That class has a public static method called Format which returns a string. Now take notice of the method's arguments. The very first argument of an extension method is always the class that the extension method is extending. In this case, we are extending the String method. So this means we can use our extension method like this.

emailBody = emailBody.Format(
	FirstName => model.User.FirstName,
	FullName => userFullName);

The method we are extending is the string method, so all we need is a string variable. The extension method becomes available as a method of a simple string variable. There is even Intellisense for you.

I hope that helps you realise the server-side and client-side development are not totally exclusive of each other. We have these amazing tools so let's integrate them as much as possible to build great looking and functional solutions.

Til next time ...