How to dynamically (via AJAX) add new items to a bound list model, in ASP MVC.NET

Imagine you have a form, which allows a user to add n entries. In my case, a user was creating a Building and was defining each Room. Each room had a “Name” and “Area”;

public class Building
{
    public string Name { get; set; }
    public List<Room> Rooms { get; set; }

    public Building()
    {
        Rooms = new List<Room>();
    }
}

public class Room
{
    public string Name { get; set; }
    public int Area { get; set; }
}

I had EditorTemplates defined for both Building and Room;

// Views\Building\EditorTemplates\Building.cshtml
@model DynamicBindiingDemo.Models.Building

<div>
    @Html.LabelFor(x => x.Name)
    @Html.EditorFor(x => x.Name)
</div>

// Views\Building\EditorTemplates\Room.cshtml
@model DynamicBindiingDemo.Models.Room

<div>
    @Html.LabelFor(x => x.Name)
    @Html.EditorFor(x => x.Name)
</div>

<div>
    @Html.LabelFor(x => x.Area)
    @Html.EditorFor(x => x.Area)
</div>

… and my Create.cshtml view looked like this;

// Views\Building\Create.cshtml
@model DynamicBindiingDemo.Models.Building
@{
    ViewBag.Title = "Create";
}

@using (Html.BeginForm())
{ 
    <h2>Create</h2>

    <h3>Building</h3>
    @Html.EditorFor(x => x)

    <h3>Rooms</h3>
    @Html.EditorFor(x => x.Rooms)

    <input type="submit" />
}

In fact, you can download the skeleton of this solution from here.

Now, I didn’t know how many rooms each building had. My options were:

  1. Give the user an ample amount (say 20) of “Room” entries on the page to start off with, and hope the user wasn’t creating a mansion or castle.
  2. Load additional “Room” entries on-demand using AJAX.

If you’re wanting to use #1, unfortunately you’re in the wrong place, as this article explains how to go about #2. Sorry about that.

What makes #2 hard is how the DefaultModelBinder requires my list of rooms to be named (very specifically), like so;

<input type="text" name="Rooms[0].Name" />
<input type="number" name="Rooms[0].Area" />

<input type="text" name="Rooms[1].Name" />
<input type="number" name="Rooms[1].Area" />

<input type="text" name="Rooms[2].Name" />
<input type="number" name="Rooms[2].Area" />

There are 2 main problems with this:

  1. Imagine I allow my users to delete Rooms as well, and let’s say they delete Rooms[1]. The HTML becomes like so;
    <input type="text" name="Rooms[0].Name" />
    <input type="number" name="Rooms[0].Area" />
    
    <input type="text" name="Rooms[2].Name" />
    <input type="number" name="Rooms[2].Area" />
    

    Because of how DefaultModelBinder works, Room[2], will disappear from my model upon submission, as DefaultModelBinder requires index’s to be consecutive, and stops when it reaches a non-existent index.

  2. When loading additional fields in via AJAX, I need to be able to tell my endpoint what the next index is (because DefaultModelBinder requires index’s to be consecutive).

With these issues in mind, it’s very hard to allow your list of entries to be dynamically added and, potentially, deleted, whilst keeping these indexes sequential.

To make this less hard, Microsoft allow you to provide a .Index field (they just don’t tell anyone this…), which allows you to use any index you want; it doesn’t have to be sequential, and hell, it doesn’t even have to be a number.

We’d then be able to allow our users to delete fields, and the following HTML submission would now work;

<input type="hidden" name="Rooms.Index" value="0" />
<input type="text" name="Rooms[0].Name" />
<input type="number" name="Rooms[0].Area" />

<input type="hidden" name="Rooms.Index" value="2" />
<input type="text" name="Rooms[2].Name" />
<input type="number" name="Rooms[2].Area" />

However, our AJAX endpoint for adding new fields still needs to have some idea which index’s have been used, so it doesn’t generate additional fields with the same name. This approach also introduces the difficulty of using @Html.EditorFor(), whilst being able to output the .Index field.

To save the day, enter a HtmlHelper extension, EditorForMany();

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;
using System.Web.Mvc;
using System.Web.Mvc.Html;

public static class HtmlHelperExtensions
{
    public static MvcHtmlString EditorForMany<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, IEnumerable<TValue>>> expression, string htmlFieldName = null) where TModel : class
    {
        var items = expression.Compile()(html.ViewData.Model);
        var sb = new StringBuilder();

        if (String.IsNullOrEmpty(htmlFieldName))
        {
            var prefix = html.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix;

            htmlFieldName = (prefix.Length > 0 ? (prefix + ".") : String.Empty) + ExpressionHelper.GetExpressionText(expression);
        }

        foreach (var item in items)
        {
            var dummy = new { Item = item };
            var guid = Guid.NewGuid().ToString();

            var memberExp = Expression.MakeMemberAccess(Expression.Constant(dummy), dummy.GetType().GetProperty("Item"));
            var singleItemExp = Expression.Lambda<Func<TModel, TValue>>(memberExp, expression.Parameters);

            sb.Append(String.Format(@"<input type=""hidden"" name=""{0}.Index"" value=""{1}"" />", htmlFieldName, guid));
            sb.Append(html.EditorFor(singleItemExp, null, String.Format("{0}[{1}]", htmlFieldName, guid)));
        }

        return new MvcHtmlString(sb.ToString());
    }
}

Now, I’ll save how this works for another article; all we care about in this one is that it does. To use it, all I do is substitute my Html.EditorFor(x => x.Rooms) in Create.cshtml with:

@Html.EditorForMany(x => x.Rooms);

… and all of our problems are solved! You’ll see that Html.EditorForMany() uses GUIDs rather than numbers for indexes. This removes the need for us to tell our AJAX endpoint which indexes as been used; as our AJAX endpoint will instead just generate a new GUID. Html.EditorForMany() also takes care of seamlessly producing the .Index field for us as well.

All that’s left to do is to get our AJAX endpoint up and running. To do this, I define a new action on my BuildingController;

public ActionResult AddRoom()
{
    return View(new List<Room>() { new Room() });
}

… and create a view Views\Building\AddRoom.cshml;

@model IEnumerable<DynamicBindiingDemo.Models.Room>
@{
    Layout = null;
}

@Html.EditorForMany(x => x, "Rooms")

… and lo-and-behold, after adding the necessary JavaScript to AJAX in a new Room entry at the click of a button (for a listing, download the finished project at the end of this article), my form now works like a dream. You’ll notice the second argument passed to Html.EditorForMany() in the AddRoom.cshtml view; this ensures the elements are generated with the right names. Without it, we’d end up with the following (note the missing Room prefix), and the dynamically generated fields wouldn’t be automatically bound to our list model upon submission;

<input type="hidden" name=".Index" value="f1d9cb81-a1dc-4e00-9e50-8c010d545f2b" />
<input type="text" name="[f1d9cb81-a1dc-4e00-9e50-8c010d545f2b].Name" />
<input type="number" name="[f1d9cb81-a1dc-4e00-9e50-8c010d545f2b].Area" />

In closing, I’d first like to point you to a blog post on haaked.com, and an answer by DaveMorganTexas on Stack Overflow; which helped me massively on this. You can download the final state of the project from here.

Understanding the JavaScript “this” keyword: Part 2

In the previous article, we uncovered the fundamental rules around how the value of this is determined when inside a function. If you haven’t read it yet, head over to the first article, and pop back here when you’re done.

From this point onwards, we’re going to explore a number of JavaScript features that throw those rules out of the window, and allow the caller to choose the value of this.

  1. Changing the value of this using call() and apply()We know if you call someObject.foo() that this inside foo will be someObject. What if we want it to be anotherObject?

    Well, we could do this;

    anotherObject.foo = someObject.foo;
    anotherObject.foo();
    delete anotherObject.foo;

    Bit of a hack, no? Enter call() and apply(). All you have to do is;

    someObject.foo.call(anotherObject);

    What if you want to pass arguments to foo() as well? No problem!

    someObject.foo.call(anotherObject, 1, 2, "abc");

    apply() works exactly the same, but the difference is how they let you pass arguments to the function. call() expects each argument as a separate parameter, whereas apply() expects a single array, whose elements are all the parameters. The equivalent apply() call for the above would be;

    someObject.foo.apply(anotherObject, [1, 2, "abc"]);
  2. Forcing the value of this using bind()bind() is a tricky addition to the JavaScript language (introduced in ES5). If you call someObject.foo.bind(anotherObject), bind() will return a new function; and no matter how you call the returned function (even using call() and apply()), the value of this will always be anotherObject.
    var obj = {
        val: 4
    };
    
    function foo() {
        alert(this.val);
    }
    
    var bar = foo.bind(obj);
    
    foo(); // behaves as expected; alerts `undefined` as `foo` is not attached to an object
    bar(); // breaks the rules! alerts `4` because `bind()` sets `this` to `obj`.
    
    bar.call(window); // this has no effect; still alerts `4`.

    Try it yourself!

    You might wonder how bind() works; but even if ES5 hadn’t included bind(); well, we could roll out our own really easily;

    Function.prototype.ourBind = function(thisArg) {
        var that = this;
    
        return function() {
            return that.apply(thisArg, arguments);
        };
    };

    We could then use ourBind() exactly how we’d use bind(); see it in action on jsFiddle!

  3. The new keyword has the last say…One last feature in JavaScript that I’d like to mention before finishing this article is the new keyword.

    If you’re not quite clued up on the behaviour of new you can read more about it here.

    Using new when calling a function is the final way to change the value of this when calling a function. When you use new, this points to a new object, whose “prototype” is set to the prototype of the function you called new on. Yep; that might take a few reads to sink in.

    The only use case for this is when creating instances of a object; but I just wanted to complete the list of “ways-this-can-be-changed”.

That concludes the articles on this; I hope you now have a much better understanding about how it works! If you want to read a few more articles to help it sink in, I’d recommend this quirksmode article and this Stack Overflow question

Understanding the JavaScript “this” keyword: Part 1

This article is the first of two articles which explain the this keyword in JavaScript. In this first post, we’ll look at what the value of this will be under various invocation scenarios. In the second article, we’ll look at how these rules can be bent by the caller.

Before we begin, I’d like to go over two JavaScript concepts. It’s crucial these are understood to be able to grasp the behaviour of this:

  1. The value of this within a function is not resolved until the function is called.This means that one function can be called 10 different times, and each time a different value of this could be observed.
  2. Whenever you name a function in JavaScript, what you actually do is create a named variable which references that function (i.e. the named variable points to the function). When you assign that named variable to another variable (i.e. alias the function), what you actually do is pass that reference by value, which leaves both variables pointing to the same function.
    // "foo" points to a function which alerts "hi"
    function foo() {
        alert("Hi");  
    }
    
    // Set "b" to point to the same function as "foo" points to (which alerts "hi").
    var b = foo;
    
    // "bar" points to a function which accepts a parameter which points to a function.
    // The body of the function simply executes the function provided.
    function bar(f) {
        f();   
    }
    
    // Pass the function pointed to be "foo" to the function pointed to by "bar".
    bar(foo);

    This means you can have one function, which can be pointed to by multiple variables. If this is still unclear, perhaps the answers to this Stack Overflow question will help the point sink in.

Once you’ve understood the two concepts above, the rules as to what the value of this is is quite straightforward; it’s the rule-bending we discuss in the next article that makes everything more more complicated!

  1. If you access the function via a property of an object, the value of this will be the object.
    var obj = {
        foo: function () {
            alert(this.bar); 
        },    
        bar: 4
    };
    
    obj.foo(); // alerts "4", as `this` inside `foo()` is `obj`.
    
  2. If the variable you access the function from is just a normal variable, the value of this depends on whether you’re in strict mode. Unless you know otherwise, chances are you won’t be.
    • If you are in strict mode, this will be undefined
    • If you aren’t in strict mode, this will the global object. In browsers, the global object is window.
    function foo() {
        "use strict";
        
        alert(typeof this === "undefined");
    }
    
    function bar() {
        alert(typeof this === "object" && this === window);
    }
    
    foo();  // alerts `true`, as inside strict mode, `this` is undefined
    bar();  // alerts `true`, as inside non-strict mode, this is the global (window) object
    

That’s all there is to it! One common “got-cha” however is when you pass a function (which was pointed to by a object member) as a parameter to another function, people still expect this to be the object.

// Define an object which has a property "foo", which points to a function.
// that function alerts "this.val".
var obj = {
    foo: function () {
        alert(this.val);   
    },

    val: "bar"
};

// Remember, if the function we're calling is a member of an object, the value of `this` will be the object.
// In this case "this" resolves to "obj", so we see "bar" being alerted.
obj.foo();

// Lets define another function, which accepts a function as a parameter. All it does is call that function.
function baz(f) {
    f(); 
}

// Now we pass the function pointed to by "obj.foo" to "baz()". "this" will now be the global object, and
// "this.val" will be undefined.
baz(obj.foo);

No! Don’t forget when you alias a function (either by assigning it to another variable or passing it as a parameter to another function), a new pointer to the same function is created. That new pointer has it’s own behaviour; and it’ll follow behaviour #2.

With the rules out of the way, lets go through some examples to see the rules being applied in practise;

function foo() {
    console.log(this);   
}

foo(); // This will be the global object ("window")

var obj = {
    bar: foo  
};

obj.bar(); // This will be "obj"

var baz = obj.bar;

baz(); // This will be the global object ("window") again.

Tracking/ joining parallel AJAX requests with jQuery

When launching a number of AJAX requests simultaneously, it can often be painful to track the requests, and seemingly necessitates the introduction of counter variables to detect when all the AJAX requests have completed. However, since jQuery 1.5, the various AJAX methods have returned a Promise object (an object which exposes only the “safe” methods of a Deferred). This, coupled with the jQuery.when method, allows you to easily add handlers to handle either the successful completion of all AJAX requests, or the failure of one; without the need for you to track anything yourself! To use this approach, simply pass the Promise’s returned by your AJAX calls as arguments to jQuery.when(), then add handlers using the done(), fail() and always() to the Promise returned by jQuery.when(), as demonstrated in the example below.

jQuery.when(jQuery.get('/foo'), jQuery.post('/bar'), jQuery.get('/baz')).done(function (a, b, c) {
    $('#output_a').text(a[0]);
    $('#output_b').text(b[0]);
    $('#output_c').text(c[0]);
});

The ith argument passed to done() is an array of arguments that correspond to the response of the ith Promise passed to when() (i.e. the arguments are available in the order they were provided; the order the responses were received in make no difference). For the example above, this means that a, b and c are all arrays of [ data, textStatus, jqXhr ]. To get the textStatus of the second AJAX call we’d use b[1]. To get the jqXhr object of the 3rd AJAX call we’d use c[2]. All fail() handlers are invoked the first time one of the provided Promises fails. Here however, the arguments are provided as they would be passed into a fail() handler bound directly to the failed AJAX request; i.e. the first argument is the jqXHR object, the second is the textStatus and the third is the error thrown. The behaviour of always() changes depending on whether a request failed or not; if all requests succeed, always() behaves like done(). If a request fails, always() behaves like fail().

jQuery.when(jQuery.get('/foo'), jQuery.post('/bar'), jQuery.get('/baz')).done(function (a, b, c) {
    $('#output_a').text(a[0]);
    $('#output_b').text(b[0]);
    $('#output_c').text(c[0]);
}).fail(function (jqXhr, textStatus, error) {
    alert('A request failed with the error "' + jqXhr.status + '"');
}).always(function () {
    // because of the varying parameter behaviour, its difficult to
    // do anything which uses them.

    $('#loading_spinner ').hide();
});

The signature of jQuery.when() (e.g. having to pass each Promise as a separate argument) can be cumbersome, and make it seem impossible to use when the number of AJAX requests you have cannot be determined. However, we can easily use Function.apply(), and use jQuery.when() using an array of Promise‘s instead;

var ajaxRequests = [jQuery.get('/foo'), jQuery.post('/bar'), jQuery.get('/baz')];

jQuery.when.apply(jQuery, ajaxRequests).done(function () {
    for (var i=0;i<arguments.length;i++) {
        console.log('Response for request #' + (i + 1) + ' is ' + arguments[i][0]);
    }
});

If you have not come across the arguments object yet, you can read about it here. As can be seen in the example above, apply() returns the “master-Deferred” the same way using jQuery.when() directly does, allowing you to bind done(), fail() and always() handlers as before.


For more reading, check out the jQuery documentation for jQuery.when(), or the question on Stack Overflow that triggered me to write this blog post!

What is the minimum valid JSON?

The short, but entirely unhelpful, answer to this question is that… it depends; it depends on both what the language you are sending from, and receiving to, deems as the minimum valid JSON.

For example, if you are sending JSON between PHP and a browser (in either direction), the minimum valid JSON is a JSON literal. Between a browser and Ruby however, it is a JSON object (or array).

The reason for this lack of consensus is best explained by the “creator” of JSON himself; Douglas Crockford:

JSON is just a grammar, and the grammar includes numbers and strings. Uses of JSON must necessarily be more restrictive. RFC-4627 is one possible use, and was never intended to be the standard for JSON itself.

So yeah. You don’t just send or receive “JSON”. Technically, you receive a JSON formatted text which adheres to a particular format; commonly described in a standard. RFC-4627 is one of those. ECMA-404 is another. RFC-4627 defines a JSON array/ object as the minimum valid JSON, whilst ECMA-404 permits JSON literals (JSONValue‘s in the spec.) as well.

This is why you need to look at the documentation for the stringifer and parser you are using; to check what standard they adhere to.

To make things more confusing however, many JSON implementations do not perfectly adhere to a particular specification, and will add their own exceptions to their implementation. This is why JSON literals are accepted as valid JSON between PHP and browsers; as even though both technically adhere to RFC-4627, both also specifically add the exception that they also accept JSON literals as well as JSON object/arrays as the minimum JSON (relevant part of the ECMAScript 5 spec., relevant part of the PHP docs.).

With Ruby on Rails however, no exceptions exist; it adheres to RFC-4627 plain and simple. So whilst browsers can create and parse JSON texts which contain only literals, Ruby on Rails cannot parse or create them itself.


This post summarises the content of two answers on Stack Overflow; my own answer to ‘What is the minimum valid JSON’, and other answer by Jeremy Banks to ‘After the publication of ECMA-404, is ‘2’ or ‘”hello”‘ considered a valid JSON text?’.