Building Rich Web Apps: jQuery & MVC vs. Angular.js & WebAPI

As a developer,  you may have gotten used to hearing this: technology is changing! The web is no exception. Looking back 10 years ago it was amazing to be able to provide a web user experience that offered any degree of similarity to what was commonly available in thick clients or desktop applications. You might have been able to pull it off with ASP.NET Web Forms, but were probably plagued by complicated code, sluggish performance, ViewState bloat and a strong distaste for a language seemingly devised by the devil himself: JavaScript.

Fast forward to 2013: most of your customers are now used to rich web applications like Gmail or Facebook. Furthermore it is likely they aren’t using the web as much in a browser but but are instead using thick client applications on their smartphone or tablet. Regardless of the the platform, one thing is certainly true: your customers aren’t asking for a rich experience in their applications, they are demanding it.

What is a rich web application?

There can be a pretty big difference between a “web site” and a “rich web application” even though they both are accessed through a common medium: a web browser. A good example of a “web site” is CNN.com. This web site serves dynamic content from a database but offers little in the realm of user interactivity beyond paging through images, watching videos, and clicking on links.

In contrast, a good example of a “rich web application” as mentioned earlier is Facebook. This web application offers a high degree of interactivity with users for both content consumption, creation and general rich interactivity. Many business applications that may exist in a thick client would also fall into this category.

The scope of this post deals with “rich web applications” and not “web sites”.

The example app: a multi-page todo list

A perfect simple example of a “rich web application” can be demoed in the form of a todo list.

Before you read any more feel free to take a look at it in action here. The source will be very helpful to comprehension of this post and is available here.

In essence, the app has two “screens”;  One for adding and deleting todo list owners, and then another for editing each owner’s name and their todo list.

On the screenshot below, a user can view all the Todo lists that are registered in the application, edit, delete or add another list.

todo list

Once the user selects “Edit” or “Add”, a side panel expands to the right that allows for the creation/deletion of Todo list items as well as editing owner information.

expanded todo lists

After a list is saved or a new list is added, the original screen is refreshed to reflect the changes and the side panel disappears.

If you looked at the demo,  you’ve probably realized that this exact same todo list application has been created using ASP.NET MVC & jQuery and also in WebAPI & Angular.js. Lets explore the differences and see if we can uncover some useful information about the frameworks themselves.

jQuery + ASP.NET MVC

Alas, the solution to creating a rich web application with great performance and minimal code? Not so fast…

Lets review the good and bad about jQuery  + ASP.NET MVC using the todo list demo app example.   Source   Live Demo

jQuery

jQuery burst onto the scene in late 2006 as a solution to the downright nasty code that used to be needed to create even the most basic hints of a good, rich user experience in the web.

PROS

  • Provides a rich abstraction from raw cumbersome DOM manipulation and selection
  • Abstracts away the nuances of cross-browser compatibility
  • Adds the ability to easily create rich UX with animations, sliding, fading, you name it
  • Makes AJAX a one liner
  • Provides a consistent event bubbling and capture model
  • jQuery UI allows for rapid implementation of common UX paradigms like modals, datepickers, sliders, etc.

jQuery provides many benefits. Without a doubt, you would have to be a glutton for pain to attempt a rich UX without at least considering it’s use. jQuery is not without it’s significant downfalls, however, which are discussed below and will be demonstrated in part by the todo application.

CONS

The DOM is your “Model”

There are two main goals when developing an interactive application: content display and content creation. HTML in essence was not designed for creating dynamic views. It was designed to display “static” content and doesn’t offer an efficient means for manipulation after initial rendering. jQuery doesn’t effectively help with this shortcoming. It offers a way to manipulate the DOM but does not offer an easy way to write code against a changing model state, and then sync it back with the server again.

This is in part due to HTML’s poor ability to organize complex, structured user input that will need to eventually be mapped back to some sort of an object graph for server side storage. Furthermore, DOM objects (as retrieved and manipulated by jQuery) do not offer an efficient means to code against to provide a dynamic user interface without creating complicated, abstract code.

Let’s look at the todo list application; It quickly becomes complicated due to jQuery, ASP.NET MVC and the fact that the DOM is serving as the model:

Creating TODO list items

One of the requirements for the TODO list app is to allow for the user to build a list of TODOs in the client. Once they click save, the list and owner information is persisted back to the server. This task, which may likely seem rather trivial to your business stakeholders, is actually a lot more complex than it should be due to the nuances of jQuery and MVC.

In order to create each TODO list row, we essentially need to loop over each TODO item in the list. This is handled just fine in a C# foreach loop on the server when the page is initially rendered, but we cannot use C# to loop out additional TODO list items added client side. (We could of course do a full POST back somehow notifying MVC to add an additional empty row on the next render, but this could introduce a full DOM refresh as well as undesired legginess and latency to the user/application).

The HTML template that is looped for new TODO list items:

<tr>
  <td>
    <input data-val="true" data-val-required="The IsCompleted field is required." id="Items_###__IsCompleted" name="Items[###].IsCompleted" type="checkbox" value="false" >
    <input name="Items[###].IsCompleted" type="hidden" value="false">
    <span class="field-validation-valid" data-valmsg-for="Items[###].IsCompleted" data-valmsg-replace="true"></span>
  </td>
  <td>
    <input data-val="true" data-val-required="The Task field is required." id="Items_###__Task" name="Items[###].Task" type="text" >
    <span class="field-validation-valid" data-valmsg-for="Items[###].Task" data-valmsg-replace="true"></span>
  </td>
  <td>
    <select data-val="true"
        data-val-number="The field Priority must be a number."
        data-val-range="The field Priority must be between 1 and 10."
        data-val-range-max="10"
        data-val-range-min="1"
        data-val-required="The Priority field is required."
        id="Items_###__Priority" name="Items[###].Priority">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
      <option value="4">4</option>
      <option value="5">5</option>
      <option value="6">6</option>
      <option value="7">7</option>
      <option value="8">8</option>
      <option value="9">9</option>
      <option value="10">10</option>
    </select>
    <span class="field-validation-valid" data-valmsg-for="Items[###].Priority" data-valmsg-replace="true"></span>
  </td>
  <td>
    <button class="btn btn-danger delete-todo">
      <span class="glyphicon glyphicon-remove-sign"></span>
    </button>
  </td>
</tr>

The best solution I could muster for this was to use jQuery to clone the above template whenever an item is added. The index of the new item replaces the ### in the template above. Note that the name attribute convention is to comply with how the MVC model binder requires array items to be formatted. Also included is some unobtrusive validation attributes for MVC validation which introduces some verbosity as well.

Here is the corresponding jQuery:

//FROM MvcjQuery/Scripts/edit.js
//ID selectors are less than ideal due to conflict potential, but often necessary with jQuery
var $tbody = $('#grid').find('tbody');

//the template for another item, the index will replace ###
var todoListTemplate = $('#item-template').html();

$('#addTodo').on('click', function (e) {

   var nextItemIdx = $tbody.find('tr').length;

   //the template for another item, the index will replace ###
   var nextItem = todoListTemplate.replace(/###/g, nextItemIdx);

   $tbody.append(nextItem);

   //block click handler bubble, don't forget or this will cause the form to post!
   return false;
});

This code isn’t too bad (just wait…) but here are a few problems already with this approach other than the items in the comments  above JavaScript:

  • Since the DOM is serving as the model instead of just creating a new object instance (which is what we would do in C# right?) we have to clone template HTML and do some DOM wizardy which is tightly coupled to EXACTLY how the screen is laid out in order to figure out what ID to use for the new item, and then finally append it to the table. This wizardry is necessary ultimately due to the fact that we are using the ASP.NET model binder which expects ‘normal’ key value pairs from a form POST.  In addition to this being very verbose, in order to really figure out what this code is doing it is almost necessary to have both the JavaScript and HTML up at the same time due to the coupling.
  • The template that is cloned is free to get out of sync with what Razor will generate (It was initially copied from a rendered view to start with). We have essentially duplicated the TODO item markup and lost strong typing as a result. You must remember to change both if anything changes!

Deleting TODO list items

This is where jQuery and MVC really fall apart: a user is free to delete ANY existing TODO list item. This means that in order for the MVC model binder to work, the indices of all items below the item that was deleted need to be shifted up one. The below code will likely hurt your eyes and feel like a dirty hack. However, this was the best way I could think of to handle it in a strictly jQuery + MVC approach without doing slow and chatty server side rendering of each delete:

//FROM MvcjQuery/Scripts/edit.js
$('.delete-todo').on('click', function (e) {
    var $deleteTargetRow = $(e.target).closest('tr');
    var $siblingsAfter = $deleteTargetRow.nextAll();

    $deleteTargetRow.remove();

    $siblingsAfter.each(function () {

        //shift indexes accordingly so the MVC model binder still functions server side
        //and client validation still works client side
        var $row = $(this);

        var newIndex = $row.index();
        var oldRowNbr = newIndex + 2;
        var newRowNbr = newIndex + 1;

        //re-wire up elements with ids
        //so client side validation still works
        $row.find('[id]').each(function () {
            this.id = this.id.replace("_" + oldRowNbr + "__", "_" + newRowNbr + "__");
        });

        //rewire up elements with indexor for client validation and server side model binding to work
        $row.find('[id]').each(function () {
            this.id = this.id.replace("_" + oldRowNbr + "__", "_" + newRowNbr + "__");
        });

        $row.find('[data-valmsg-for]').each(function () {
            var current = $(this).prop('data-valmsg-for');
            $(this).prop('data-valmsg-for', current.replace("[" + oldRowNbr + "]", "[" + newRowNbr + "]"));
        });

        $row.find('[name]').each(function () {
            this.name = this.name.replace("[" + oldRowNbr + "]", "[" + newRowNbr + "]");
        });

    });

    return false; //block click handler bubble
});

Lack of separation of concerns

The lack of separation of concerns that jQuery provides is quite apparent from the above code. How about a common generic example of something you would do with jQuery:

  1. select an element by the ID present in the DOM
  2. within that element select the items with ‘some-class’
  3. append a <span> to those items after setting the class of the <span> to “foo”. 

Here is the code:

$('#someId').find('some-class').append($('<span>').class('foo'))

If that sounded or looks confusing that’s because it is! jQuery JavaScript code is  often very tightly coupled to to the exact structure of the DOM that you are manipulating. This is one of the many reasons that JavaScript isn’t a good way to manipulate the DOM.

Here is another example that may be near to your heart: Do you remember that awful designer file that WinForms would create when you dragged and dropped and edited files in the GUI? (Maybe you were just happy you didn’t have to code that thing your self right?) You may also remember that you wanted to avoid touching that file at all costs! Here’s why…

Manipulating a GUI’s layout with code is and has always been cumbersome at best. This is why Silverlight and WPF took a 180 degree turn on the WinForms paradigm. However, at the heart of it, jQuery DOM manipulation for a dynamic UI looks far more like WinForms than it does like WPF/Silverlight.

Even worse, the tight coupling (and the lack of conspicuousness of this coupling) often means that if designers move some HTML around, or even add/remove a CSS class name (because CSS classes are often overriden to be used as jQuery selectors) it can have disastrous side effects that can render large portions of jQuery code useless. Worse yet, when the problem is discovered it can be very difficult to change and re-factor existing jQuery code to ‘work’ with a new layout.

Code organization and compartmentalization

Another problem that quickly becomes apparent when you build even a few pages of an application using jQuery is how little guidance and structure comes with it out of the box. I have even seen well planned heavy jQuery applications with the best intent turn into something like this…

jQuery Spaghetti Code (if this sounds delicious trust me it’s not!):

jquery spaghetti

JavaScript (unfortunately) doesn’t include much guidance for how to organize your code. More often than not when using jQuery, a developer ends up with a bunch of global functions that do various things:

//"global.js"

function openWindow(url) {/*...*/}

function doSomething() {/*...*/}

function doSomethingWithArgs(arg) {/*...*/}

//and so on...

Imagine if you were to create a C# application with no namespaces and no classes (and the scoping that classes can create). Sounds like a mess, right? Bingo! The above code turns into just that in no time! Just wait until someone in one part of the app defines another openWindow because they want to do it differently….

Let’s say we have adopted a paradigm that asserts that we will have one JavaScript file per page, for example from the TODO list app:

//FROM MvcjQuery/Scripts/edit.js
//the below closure is good because it creates "variable privacy"
$(function () {

    //ID selectors are less than ideal due to conflict potential, but often necessary with jQuery
    var $tbody = $('#grid').find('tbody');

	//...
});

First off you probably will end up combining/minifying your Javascript into a single “bundle” to improve client performance. Taking this into consideration:

Right away I can spot one blaring problem with the above code: what if an ID with “grid” exists anywhere else in the application, or heck, even on this page? This example is a bit contrived, but any time a jQuery selector is used it must be used very carefully and scoped appropriately, otherwise you may be effecting a whole different set of elements than you intended. For this reason, even well separated and best intentioned jQuery organization schemes quickly become cumbersome with even medium sized applications.

ASP.NET MVC

ASP.NET MVC is arguably the successor to ASP.NET Web Forms and most developers that have switched haven’t looked back. It provides a strongly typed, testable, and a “simpler than Web Forms” way to create complex web sites.

PROS

  • Model binder and view engine provides a simply amazing way to strongly type your views to C# view models and move that data back and forth between the client and server with ease using common web paradigms such as form POSTs and GETs.
  • Provides a simple API that abstracts away the nuts and bolts of ASP.NET to allow for highly compartmentalized testable code.
  • Very customizable and extendable: do what you need to meet business requirements without creating a hacked, hard-to-maintain mess.

For what ASP.NET MVC is designed to do it works very well: creating dynamic web sites with some basic form-based interactions.  As soon as you venture too far outside that box and try to create a rich web application (or lets call it a ‘desktop app replacement’) ASP.NET MVC starts to become a burden. Let’s see why below…

CONS

The DOM is your model

Hopefully by this point you are beginning to question using the DOM as your model (read the first jQuery con above if you haven’t already). The DOM is simply not a good means in which to store complex, nested, list-based, hierarchical or really any sort of data structure that hydrate into rich object model(s) in server side C#. Unfortunately most of the ‘helpers’ built into ASP.NET MVC assume a very flat, very basic object model, and as soon as you venture much outside of that, things start to fall apart and the hacking begins…

The TODO list demo has a pretty basic example of where ASP.NET MVC helpers and the key value form post based model binder fall apart: rendering and allowing for editing of anything that is list based. (You’ve never had to deal with lists before right?)

<!-- MvcjQuery/Views/Index.cshtml -->
<tbody>
  @for (var i = 0; i < Model.Items.Count; i++)
  {
    <tr>
      <td>
        @Html.CheckBoxFor(model => model.Items[i].IsCompleted)
        @Html.ValidationMessageFor(model => model.Items[i].IsCompleted)
      </td>
      <td>
        @Html.TextBoxFor(model => model.Items[i].Task)
        @Html.ValidationMessageFor(model => model.Items[i].Task)
      </td>
      <td>
        @*
        Setting select list value in for loop
        doesn't work (though this style is required by model binder)

http://stackoverflow.com/questions/2631397/dropdownlistfor-does-not-select-value-if-in-for-loop

        Select the item in each iteration manually
        *@

        @{
          foreach (var selectListItem in priorities)
          {
            selectListItem.Selected = false;
          }

          var toSelect = priorities.FirstOrDefault(x => x.Value == Model.Items[i].Priority.ToString());
          if (toSelect != null)
          {
            toSelect.Selected = true;
          }
        }

        @Html.DropDownListFor(model => model.Items[i].Priority, priorities)
        @Html.ValidationMessageFor(model => model.Items[i].Priority)
      </td>
      <td>
        <button class="btn btn-danger delete-todo">
          <span class="glyphicon glyphicon-remove-sign"></span>
        </button>
      </td>
    </tr>
  }
</tbody>

There are a couple things to note about the above code:

  • A “foreach” loop cannot be used because this is an editable grid. Because of this a “for” loop must be used. The odd [i]ndex based for syntax must be used to allow the model binder to parse the incoming name value pairs of form POST values that look something like this:
Id=TodoLists-1&OwnerFirstName=John&OwnerLastName=Culviner&Items%5B0%5D.IsCompleted=false&Items%5B0%5D.Task=Clean+house&Items%5B0%5D.Priority=10&Items%5B1%5D.IsCompleted=false&Items%5B1%5D.Task=Write+code&Items%5B1%5D.Priority=1&Items%5B2%5D.IsCompleted=true&Items%5B2%5D.IsCompleted=false&Items%5B2%5D.Task=Mow+lawn&Items%5B2%5D.Priority=5&X-Requested-With=XMLHttpRequest

(hope you never have to debug that right?)

  • Select lists require a pretty significant hack in order to work in a loop as well
  • The only thing that works well and straightforward in this example is simple flat form fields. (Which is ironically exactly what MVC is pretty good at!)

Creating/Deleting TODO list items

In addition to hacks to get a list to work with MVC, I ended up having to copy and paste the generated HTML output from the “TodoList.cshtml”  file in order to allow for the model binder to work when adding items client side. Take a look at “Creating TODO list items” and “Deleting TODO list items” in the jQuery section above to see exactly what this looks like. Essentially, in order to prevent slow UX whenever a TODO list item is added, an HTML template is cloned client side and then the names of fields are filled in with their correct array index so that the model binder can pick it up on a POST. The huge down side of this is the complete duplication of code: a for-loop for rendering the list items on the server and then another for-loop for rendering on the client.

Use of age old, outdated web paradigm

As we can probably agree at this point, using the DOM as a model for anything more complicated than a flat simple collection of a few input fields is not a good idea. Unfortunately, MVC is mostly designed and intended to be used with <form>s which means exactly this.

Why use <form>s?

Forms are great for doing simple things with flat data. Unfortunately they are  a hold over from a time when about as interactive as the web got was animated GIFs, image maps and guestbooks. The web has changed significantly since then and has arguably evolved into a first class application development platform that can compete with, and even beat traditional thick client applications in terms of ease of development AND user experience. The <form> was not intended to be used for creating rich, interactive applications in this manner.

JavaScript + AJAX instead of <form>s

A form was really designed for and intended to be used with a full page POST back in the early 90’s. It offers a simple key-value based approach to sending data to a server and then rendering a new page (a new DOM) as a result. If we make the accurate assumption that a client is running JavaScript (and let’s be honest, if they aren’t, the web will barely work for them in this day and age) we can dump the <form> and all the problems associated with it:

  • A full page POST via a form is:
    • unnecessarily bloated and results in a slow user experience
    • causes a page that flickers
    • does not feel like a traditional thick client app to the user
    • doesn’t allow for a thick client like experience as the developer cannot readily store data/state in memory on the client because the DOM keeps getting blown away. WebForms tried it’s hand in fixing this with ViewState, one form per page (with lots of magic) and the POST-back but this resulted in lots of problems and complexity as we know.
  • As already discussed a <form> with its associated <input>s result in a very ‘nasty’ key-value structure that is difficult to parse into a rich object model. The MVC model binder does a good job for simple stuff but becomes unnecessarily complicated when you venture from the simple and flat.

If we ditch full page POSTs and use AJAX with <form>s we lose some of the above issues but one huge problem still remains: the DOM is being used as a model and an overly complicated model binder still needs to be used. If only there was a way to use an ‘object like’ structure for model binding in the client and over-the-wire serialization which would fit in nicely to server side C# object graphs. Wait… how about…

Angular.js + ASP.NET WebAPI

Angular.js and WebAPI is a new way to build rich interactive web applications that fully embraces what can be done with a Web browser, JavaScript and C# rather than relying on out-dated paradigms that complicate the process for all but simple use cases. If your users and clients are expecting an application in a web browser that behaves like a native app on their desktop or smart phone, then jQuery + ASP.NET MVC is not the most straightforward way to build it.

Client-side model binding and JSON serialization

At the heart of Angular.js and WebAPI’s effectiveness at producing rich web applications are two things that plague  jQuery and ASP.NET MVC: client side model representation and serialization.

Angular.js’ approach looks and feels similar to what you may have seen using Silverlight or WPF with a few twists.

The DOM isn’t your model: Anguar.js Scope

For the purposes of this post we won’t cover a deep dive on what scope is but we will cover the basics: scope in Angular.js can be used a lot like a 2-way bound ViewModel.

Two-way model binding

Angular.js uses something called “scope” to communicate and achieve two-way model binding between the DOM and a rich JavaScript object model. For example this GUI:

todo detail

is two-way bound to this JavaScript object graph off by using scope (a “viewmodel”):

scope = {
  todoList: {
     Id: "TodoLists-1",
     OwnerFirstName: "John",
     OwnerLastName: "Culviner",
     Items:[
      {
        IsCompleted: false,
        Task: "Clean house",
        Priority: 10
      },
      {
        IsCompleted: false,
        Task: "Write code",
        Priority: 1
      },
      {
        IsCompleted: true,
        Task: "Mow lawn",
        Priority: 5
      }
     ]
  }
}

Any time a change occurs to scope either via JavaScript code (ex: removing an item from “Items”) or via user interaction to the DOM (ex: typing text in a textbox) both JavaScript AND the DOM reflect the changes instantly as often as every keystroke.

Since Angular.js has a templating engine built in, there is no duplication of code: all rendering is done on the client as it is two-way bound to scope rather than duplicating rendering logic on both the client and server. Here is what the entire TODO detail edit view looks like as it is bound to the above model.

<!-- WebApiAngular/Views/todoLists.detail.html -->
<div ng-form="todoDetailForm">
  <div class="row">
    <!-- essentially a foreach loop -->
    <div ng-repeat="error in errors" class="validation-summary-errors">{{error}}</div>
  </div>
  <h2>
    <!-- Text and markup can be intermixed with text bound to scope
         that changes with every keystroke-->
    Todo List for {{todoList.OwnerFirstName}} {{todoList.OwnerLastName}}
  </h2>
  <div class="row">
    <div class="col-lg-4">
      <div class="form-group">
        <label>Owner First Name</label>
        <!-- ng-model 2-way binds the textbox to a JavaScript field -->
        <input type="text" class="form-control" ng-model="todoList.OwnerFirstName" required="" />
      </div>

      <div class="form-group">
        <label>Owner Last Name</label>
        <input type="text" class="form-control" ng-model="todoList.OwnerLastName" required="" />
      </div>
    </div>
  </div>
  <div class="row">
    <table class="table grid" id="grid">
      <thead>
        <tr>
          <th>Complete</th>
          <th>Name</th>
          <th>Priority</th>
          <th></th>
        </tr>
      </thead>
      <tbody>
        <!-- essentially a foreach loop -->
        <tr ng-repeat="todo in todoList.Items">
          <td>
            <input type="checkbox" ng-model="todo.IsCompleted"/>
          </td>
          <td>
            <input type="text" ng-model="todo.Task" required="" />
          </td>
          <td>
            <select ng-model="todo.Priority" required="">
              <option value="1">1</option><option value="2">2</option><option value="3">3</option><option value="4">4</option><option value="5">5</option><option value="6">6</option><option value="7">7</option><option value="8">8</option><option value="9">9</option><option value="10">10</option>
            </select>
          </td>
          <td>
            <button class="btn btn-danger" ng-click="todoList.Items.splice($index, 1)">
              <span class="glyphicon glyphicon-remove-sign"></span>
            </button>
          </td>
        </tr>
      </tbody>
    </table>
  </div>

  <div class="row">
    <a id="cancel" class="btn btn-warning pull-left" href="#">
      Cancel
    </a>
    <!-- when the button is clicked the save function on scope is called -->
    <button ng-disabled="todoDetailForm.$invalid" type="submit" ng-click="save()" class="btn btn-primary pull-left">
      Save
    </button>
    <button id="addTodo" class="btn btn-success pull-left" ng-click="addTodo()">
      Add Todo
    </button>
  </div>
</div>

JSON Serialization

As you have noticed we have a rich object graph attached to scope as our “viewmodel”. Have no fear: this doesn’t have to go away when the data is sent to WebAPI for rehydration into C# types. The types in C# look exactly like how they did attached to scope in JSON. Here is what the over-the-wire JSON looks like in contrast to how MVC does things. Look familiar to the above JavaScript?

{
  "Id": "TodoLists-1",
  "OwnerFirstName": "John",
  "OwnerLastName": "Culviner",
  "Items": [{
    "IsCompleted": false,
    "Task": "Clean house",
    "Priority": 10
  },
  {
    "IsCompleted": false,
    "Task": "Write code",
    "Priority": 1
  },
  {
    "IsCompleted": true,
    "Task": "Mow lawn",
    "Priority": 5
  }]
}

JSON or JavaScript Object Notation serializes the “todoList” object attached to scope in the exact same manner you saw it above (only it is text instead of an object in memory). JSON.NET is used C# side to hydrate the C# type “TodoList”:

//TodoApiController.cs
public class TodoApiController : ApiController
{
  private TodoListService _todoListService;

  public TodoApiController()
  {
    //simple demo, no real DI
    _todoListService = new TodoListService();
  }

  //...

  public HttpResponseMessage Post(TodoList todoList)
  {
    _todoListService.Post(todoList);
    return Request.CreateResponse(HttpStatusCode.OK);
  }

  //...
}

Near-perfect separation of concerns

Not a whole lot more needs to be said about this if you have noted the above examples. Note that no DOM manipulation or even knowledge of the DOM is required: The 2-way model binding afforded by scope and the ability to run functions attached to scope makes DOM manipulation unnecessary. In fact any sort of DOM manipulation outside of directives is perhaps the #1 cardinal sin of Angular. Don’t do it! It’s pretty easy to not even be tempted since the 2-way model binding works so well with the suite of built in directives (ng-model is a directive for example). The community around Angular.js is so extensive that custom directives often only need to be hand-written for very domain specific problems in general.

Simple, flexible code organization and compartmentalization

The perfect way to illustrate how good Angular.js’ good organization and compartmentalization is compared to the frequent jQuery mess is to show all the JavaScript required for the TODO demo in a single file and break it down:

//WebApiAngular/Scripts/app.js

angular.module("todoApp", ['ui.router', 'ngResource'])
  .config(function ($stateProvider, $urlRouterProvider, $httpProvider) {
    //configure Angular.js before the app starts.
    //dependencies are injected in specified by argument name (not position)
    //compare this to Application_Start in Global.asax or a Web.config

    //default to application/json for AJAX delete
    $httpProvider.defaults.headers.delete = { 'Content-Type': 'application/json' };

    //set up robust, extendable routing that supports 1-to-lots of different pages
    $urlRouterProvider.otherwise("/todoLists");
    $stateProvider
      .state('todoLists', {
        url: "/todoLists", //when the url starts with this the above state is active
        templateUrl: "/WebApiAngular/Views/todoLists.html",
        controller: 'todoLists' //activating this controller
      })
      .state('todoLists.detail', {
        //this state becomes active on /todoLists/some-id-here
        //the some-id-here is parsed and passed into the controller
        url: "/:id",
        templateUrl: "/WebApiAngular/Views/todoLists.detail.html",
        controller: 'todoDetail' //active this controller
      });
  })

  //factories can be injected using DI (they are singletons)
  //note how TodoList is called out by argument name as a dependency
  //in both the below controllers
  .factory('TodoList', function ($resource) {
    //resource provides easy interaction with a RESTful endpoint. Factory is DI'ed into controllers below
    return new $resource('/api/TodoApi/:id');
  })

  //controller for the summary view, could put in separate file if desired
  .controller('todoLists', function ($scope, TodoList) {
    $scope.todoLists = TodoList.query();

    //delete remove just the item from DB and client, don't re-query. less chatty
    $scope.delete = function (todoList, index) {
      todoList.$delete(function () {
        $scope.todoLists.splice(index, 1);
      });
    };

    $scope.$on('todoChanged', function () {
      //we could get crazy here and ONLY replace the item that changed
      //if we wanted to make the application even more efficient
      //but keeping it like this for brevity
      $scope.todoLists = TodoList.query();
    });
  })

  //controller for the todo detail view, could put in separate file if desired
  .controller('todoDetail', function ($scope, TodoList, $stateParams, $state) {

    //if the route specifies a new todo list item create one client side
    //otherwise get it with AJAX from the server
    $scope.todoList = $stateParams.id === 'new' ?
      new TodoList({Items: []}) :
      TodoList.get({ id: $stateParams.id });

    $scope.save = function () {
      //perform ajax to save the todo list item
      $scope.todoList.$save(function () {
        //on ajax success
        $scope.errors = null;
        $state.go('^');         //navigate to parent summary view
        $scope.$emit('todoChanged');  //notify parent to refresh
      }, function (resp) {
        //on ajax failure display errors
        $scope.errors = resp.data;
      });
    };

    $scope.addTodo = function () {
      //add a new TODO item
      todoList.Items.push({});
    };
  });

Perhaps the first thing you think when you look at the above code is: why is everything in the same file? Angular.js is very flexible. Since this is a small application, I chose to put everything into a single file and use the fluent syntax to define my application. I could have just as easily split apart each ‘dot’ component of the application into separate files . Furthermore, you can even bundle components into modules. Note on line 1 that the application pulls a dependency on two other 3rd party modules that are free to define their own things.  In this manner modules function in a very similar manner to namespaces or assemblies in C#.

Dependency Injection

At the heart of everything in Angular.js is dependency injection. Not only do explicit dependencies allow for ease of code comprehension and organization but they also allow Angular.js to be extremely unit testable. One way of injecting dependencies into Angular.js is to simply specify the dependency’s name as the argumentName in which they are to be injected. This is a bit mind-blowing to see at first but there are many examples of this occurring above.

Factories

Factories are a way to instantiate types for consumption as downstream dependencies. Factories are also singletons and can be used as a way to share state between different things. Note that a factory is used to create a “resource” to interact with the WebAPI RESTful service for TODOs above.

Controllers

A controller is a type of directive that is essentially a “scope container”. In the TODO example app there is one controller per view; a common pattern in Angular.js development. The scope that is DI’ed into each controller is it’s own separate, isolated “viewmodel” which can be used as a communication medium to the controller’s underlying associated view. See “routing” below to see how the controllers and views are associated.

Routing

The router provided by angular-ui is nothing short of amazing in terms of simplicity and scalability. This app might only have two routes but you could easily make that number 200 with little loss in simplicity or comprehension ability. Routes are a way to tie a particular hash fragment URL (EX: #/todoLists) to the activation of a particular specified controller and an associated, bound view. Routes can also specify parameters which are parsed and passed into the activated controller (for example #/todoLists/TodoLists-1 informs the controller to load a TodoList with the ID “TodoLists-1”). Contrast the router to the method in which I hacked together “routing” with jQuery. It is not robust enough to be maintainable for much larger an app than this one.

AJAX and REST

Angular.js and it’s “resource” plugin make interacting with RESTful APIs (that follow REST conventions) a snap. It is being used above. I can’t readily think of a more concise abbreviated syntax in which to do it. Angular also has it’s own AJAX wrapper, “$http” that can be DI’ed whenever you need it as you would expect.

Data-binding

Angular.js takes a different approach to data-binding that differs from pretty much any other JavaScript “MVVM-like” framework out there: it uses dirty checking as opposed to special objects. (For example Knockout.js has “observables” that are actually functions). Coming from a pretty extensive experience using Knockout and a bit of time on Angular.js, I can easily say that the way Angular.js handles this makes development leaps and bounds easier. Angular.js feels like developing on JavaScript where the dynamic nature of it is fully embraced with no problems and little headaches. Knockout on the other hand feels like developing a C# MVVM application but without strong typing or classes (to no benefit I might add!) and lots of headaches. An entire book could be written on a comparison between the two and is out of the scope of this post. So far I’ve had far less problems with Angular.js and higher speed of development than with Knockout or its SPA wrapper Durandal.js (The addition of Drundal.js to Knockout makes it more comparable to Angular.js)

Community

The JavaScript community has really rallied behind Angular.js (perhaps because its developed by a full team of Google developers?) The angular-ui project is an excellent example of a large free OSS suite of ui utilities that fill in a few shortcomings in what Angular.js provides out of the box. (It is of course easy to build your own directives your self as well!) Even though Knockout.js has been around (and stable) considerably longer than Angular.js, I’ve already found much better, free, less hacked-together tooling out there for Angular. Google trends shows angular rapidly overtaking other serious SPA/model binding contenders out there as well.

WebAPI

Not a whole lot has been mentioned about the other half of this stack: WebAPI. That’s because if you are familiar with ASP.NET MVC, then WebAPI will also be pretty familiar to you with a few caveats:

  • Designed to make implementing RESTful APIs as easy as possible.
  • Designed around returning HttpResponseMessages or objects (as JSON by “default” or any way you want!) directly rather than rendering views. Removes a lot of AJAX/JSON pain that ASP.NET MVC has.
  • Has first class Async and OData support.
  • Looks a lot like ASP.NET MVC but everything lives in a different assembly/namespace.

Some Cons of Angular.js + WebAPI

I’d be lying if I told you Angular.js is perfect and does everything without a doubt better than all the alternatives out there. Here are some things I’ve noticed coming from a 4 year background in ASP.NET MVC + jQuery and pretty extensive use of Knockout.js/Durandal.js

Strongly typed HTML helpers with Intellisense

No strong typing… welcome to JavaScript right? Well not so fast… If we have C# Models that are often 1:1 represented as JavaScript models some sort of strong typing should be possible in the views at least. For example, C# TodoList’s fields are fully represented in the Angular.js view. I created the FluentKnockoutHelpers project for this purpose in Knockout.js which I plan on porting over to Angular. To be completely honest however, I’ve found that I rarely have a problem with my C# model / JavaScript representation not matching up. It’s just a matter of being careful when you re-factor things; Although I will be first to admit that a compiler helps (especially intellisense).

Validation rendering / sharing with server

Another downside of pure Angular.js in contrast to ASP.NET MVC is validation (look below I have a partial solution to this though!). In particular, validation messages that tie to particular fields  is a very manual process. Angular.js’ method of validation is actually excellent and quite a bit different than any way I’ve seen before, but it doesn’t automatically tie into the server out of the box. Any sort of client side validation currently would have to be coded (rather concisely though) on the client and then again on the server. I plan on addressing this con of Angular with an upcoming plugin for Angular.js and WebAPI that should make the experience fully integrated with C# DataAnnotations and overall better than what MVC offers. It’s not there yet though. In the meantime check out AngularAgility Form Extensions (Source) (Demo) (Blog Posts) which I’ve been working on which implements a bunch of common form UX patterns to make development way easier than it already is with Angular:

  • Auto generate entire bootstrap (or whatever) form fields with automatic error message generation and notification in 1 line of HTML
  • Invalid form submit prevention (and error message showing)
  • Form changed tracking
  • Form reset to unchanged
  • Loading indicators
  • On-navigate away handling
  • Etc.

Angular.js learning curve

I saved perhaps the most daunting one for last: Angular.js is complicated. This was my initial excuse to not learn it and I regret that immensely. I found Knockout.js + Durandal.js far easier to learn (coming from a Knockout .js and MVC background mind you) but it is the wrong approach in my opinion.

I’ve found though that once you invest the time to learn Angular.js and all of it’s intricacies, it is definitely way more than worth it. The speed, ease of development, scalability, lack of code you have to write, and lack of complexity is simply amazing. Stuff just works, but it is going to take you a month or two to become extremely effective in the framework. Contrast this to something like ASP.NET MVC + jQuery or Durandal.js/Knockout.js: You can use the frameworks for a long time and become pretty proficient but your code will still be riddled with hacks, disorganization, complexity and WAY too much code if you are trying to create a rich web application.

It is far better to learn how to use the right/best tool for the job than to use an inferior tool that was a little quicker to learn, but you end up regretting. (Especially when you have to maintain all that code…!)

In conclusion

I hope this post has made you think about Angular.js + WebAPI as being a more-than-viable replacement to jQuery + ASP.NET MVC development. Without a doubt the latter was one of the best stacks out there a few years ago, but as it always does, technology keeps improving!  I have personally been using Angular.js + WebAPI for an ever-increasing-in-size complicated, interactive SPA and haven’t looked back. There are plans to expand the app even more, and I have no doubt that it will be easy to extend with little to no added complexity since it was started with the right foundation.

Make sure to download the demo code or view the demo live if you haven’t already. I hope this post was useful, leave any feedback below!

If your interested in finding out more about Angular and my experiences in it feel free to take a look at my personal blog. I am also working on an open source project, AngularAgility, which aims to make common UI paradigms even easier to implement in Angular.js such as rich client side validation with messages, notifications and more. For example AngularAgility Form Extensions is a DSL that allows you to create Twitter Bootstrap form fields with interactive client side validation and dirty tracking in one line of HTML! You can check out the project’s source here and a demo here.

Please let ILM know if you are interested in hearing more about Angular + WebAPI, custom application development or to arrange for training. We would be more than happy to help!

John Culviner
http://www.johnculviner.com

Comments

  1. Very good post. It cleared all my doubts about angular js usage. Thanks again!

  2. nmconsulting says:

    Excellent work, this gives me background and motivation to get going on angular.

  3. Great post! Where you able to create the Validation plugin?

    • johnculviner says:

      Hi Daniel. Glad you liked it! I didn’t end up writing that part yet (having to run CSHTML *just* to get a few validators/labels to go out always seemed a little clunky) however I did write something probably even more valuable… Been working on AngularAgility Form Extensions that does a bunch of cool stuff: Defines a DSL for HTML to make generating bootstrap (or whatever) markup w/ validation a 1 liner. Automatically generates Angular form validation messages. Form change tracking, form resets, loading indicators, on navigate away handling (both SPA and DOM). Let me know how you like it I’ve found it very useful on many of my projects: Code | Live Demo | Some blog posts

      • Wow, the form extensions look really cool! I checked out the code and did some tests on the Live Demo and it looks exactly like what I was looking for.

        We come from a PHP MVC background (CakePHP in the backend and using AngularJS on newer views – manually setting the scope) and I have been playing with the idea of going full AngularJS with a REST API in the backend. I’m going to try to move our development process toward this (although existing projects will stay PHP for the forseeable future)

        Also we just got a request from a customer to use ASP.NET MVC for a new project and I was investigating wether going full API or not. To a point it seems like *some* work might be duplicated while using an API, but having this simplifies the process greatly.

        Thank you!

  4. Hi

    I like the examples but i dont really agree with your pros and cons.

    I think your cons against jquery are a bit harsh. Jquery certainly makes it easy to manipulate com and that is pretty much a requirement of almost every single page app. Just as it makes it easy though doesn’t automatically make dom your model. Every framework that renders in the browser manipulates dom one way or another – so just because jquery is a lower level library than some other frameworks does it mean you shouldn’t make a framework using jquery just as many of those others do? Personally I see a parallel between dom on a webpage and a memory mapped graphics or probably more closely a vector based graphics facility and if you choose to start at a low level of dom you can get fantastic results in a clean way if you build up your own libraries or framework on top.

    I guess you chose to use dom as your model in your jquery example but in the real world that’s ok if an extremely small program. With the separation of concerns exactly the same argument. As the developer of your todo list you can define your own concerns which are important for you to separate based on what you feel might best suit your apps future roadmap. Now imagine if you wrote a Toronto list class that had the option of rendering to a provided com element – that is one example of separation of concerns and it may even have a separate model if that is also important to you. Why a class? What if you want to programatically manipulate a todo list? Perhaps have a method to merge multiple of them? Or even display multiple on the one form? That decoupling of the todo logic certainly makes that easier.

    ASP.net definitely has its fans but it is so full of restrictions it makes it hard to do anything really good but again it depends on if you go with its forced structure or break its rules and separate your concerns in your most appropriate way – just my way fights ASP.net’s MVC a lot.

    I agree on the JS+Ajax over forms as it gives you greatest flexibility.

    AngularJS is interesting but also restrictive like Microsoft MVC and I really wouldn’t call it an application framework but a step above (or aside) from JQuery. I am a fan of Jquery – although not perfect its pretty good for what its designed to do. Angular seems geared towards 90s style web apps with a cleaner codebase. Its binding works well but slowly it has scoping and a separation of concerns but their forced choice of concerns. Some features are useful sometimes but rather than making them totally optional they have encouraged their use (such as routing) making some apps annoying to develop in AngularJS. Noone should have to fight a framework.

    My typical web app such as demonstrated here http://www.youtube.com/webrenovators is based on our own ‘app framework’ that only really depends on JQuery as a minimum because we like the way selectors work. Its an app framework because it has proper app facilities and services (we called the framework RapidOS though). Print services (direct to printer including thermal as well as remote printing even from a mobile device to a printer across the World) – single page and multiple page support even mixed in the same app – sdi and mdi – multitasking – multimonitor support (for operations bridge) – interprocess communication – API – security – and more importantly than anything else is its so easy to program with even high school students can create apps with it.

    Julian Cassin

    • johnculviner says:

      Hi Julian,

      I really appreciate the comment! Just to give you a little more background on myself before I specifically address your concerns with Angular vs jQuery.

      I’ve been using jQuery to build pretty complex (even SPAs before they were cool) applications since 2009. It is definitely a powerful framework for doing DOM manipulation. There is no disagreement on that point by me, the authors of Angular or really anyone I’ve met. In fact when you use Angular and you have jQuery as part of your DOM Angular uses jQuery internally and you can use it as well when you write custom directives: Qhich are a sandboxed space in which you have full reign to do whatever you want with the DOM. I don’t talk about them in this article but I’ve done most of what you can do with directives in my open source project here: https://github.com/AngularAgility/AngularAgility One can use directives to ‘sandbox’ and readily test any direct jQuery DOM manipulation they need to do or you could almost pretend you aren’t using Angular. (You are not restricted in the least!)

      I’ve been using Angular for the past year in a lead-type role to develop multiple SPAs totaling a few hundred pages and this is what I’ve found: Unless I’m writing a DSL or trying to make a ‘very re-usable component (like AngularAgility)’ 95% of the time I don’t even need to think about DOM nuances because an ‘MVVM style’ object model works absolutely perfect for what I’m trying to accomplish. Angular provides a very nice abstraction in this sense and avoids you having to know some pretty in-depth DOM manipulation rules (which I’ve seen JR and SR devs alike trip over).

      What I’ve also found over the last year is I end up writing 5-10x less code than I would have written using jQuery to build a interactive application. Angular definitely has a learning curve but once you pick it up you really appreciate the “there is probably no way to make this code any more tearse” mentality that Angular provides. And you can always drop into jQuery *whenever* you want. Angular just forces you to do it in a little sandbox which is *really good* if you’ve seen the jQuery messes I have! I haven’t taught Angular to anyone that has wanted to go back to jQuery or Knockout for that matter after using it and I think that says something.

      Most people would always like to have less, easy to understand code (once you have Angular understanding) than have 5-10x more code that requires an entirely different set of domain knowledge. (5-10x more code and I’ve often seen jQuery apps become a tangled, unmaintainable mess unless you have extreme organization skills and/or use something like Backbone to help).

      I’d like to draw an analogy here: if you have sufficient domain knowledge you could always write a faster program in assembly but it’s not going to be done a feasible time scale that’s why we use .NET, Java and JavaScript to be more productive. I don’t see Angular much differently than that. The nice part is Angular let’s you readily drop into “assembly” if you need to. Otherwise, most of the time, you can reap the huge increases in productivity without going there!

      Thoughts?

      John

      • First, please excuse the typos in the original post, mobile devices love to think they know what you want to type and decide to screw it up… ‘todos’ = Toronto? ‘dom’ = com?

        I looked at Angular Agility and it certainly reduces code in the examples, but… why would anyone want to write code as per the pre-reduced code in the first place? Why would they want to put logic in the HTML? And put so many static messages in the HTML like that? If you want to test your logic without the presence of Angular, how do you do it? How do you easily replace Angular when it comes to end of life and your code base is now half a million lines long?

        I do actually like AngularJS in some ways, but not in others. It might in the end come down to which flavour of tomato sauce you like most, but I still found it inflexible for doing typical things. It seemed too ‘html’-centric which is ok if you want to output html, but not giving you much flexibility when you don’t want to. What if you choose now to render it on a canvas instead of html? or don’t want to render anything at all, such as with a print spooler (where it might send a noficiation when complete)?

        Writing less code is always good and i doubt anyone will dispute that – but the code will ideally be the least you need to write to keep it maintainable, understandable and actually achieve what you want to achieve. I found when playing with AngularJS, it was just too messy to create a proper MDI system that can fall back to SDI, the routes can work, but came down to creating custom routers that didn’t have much to do with what AngularJS was trying to encourage you to do – although I’m unsure what they were thinking when they did it, how it’s supposed to work in a typical MDI type environment? I guess rather than criticise AngularJS for what it doesn’t provide, I should praise it for what it does – that is a clean way to create somewhat simple dynamic html (only) pages with not much code.

        I’m not yet convinced with AngularJS, but I won’t totally disregard it yet either – it’s probably one of the 3 noteworthy frameworks outside of roll-your-own better one that I can think of. SomaJS, RappidJS (NOT related to RapidOS) and AngularJS in that order… (JQuery or Underscore to me aren’t frameworks – but very good libraries).

        Julian Cassin

      • johnculviner says:

        Hi Julian,

        The current tagline for Angular.js is “HTML enhanced for web apps!” I’ll rephrase it, it’s “a framework for building dynamic views with HTML and JavaScript”. It’s not a generalized abstraction on top of “any interface problem you might ever want to try to solve”. I’m pretty thankful for that too because I’ve seen ‘academic abstraction ad-nauseam’ often in my career with the benign goal of being able to swap things out later on or develop something extremely generalized that doesn’t really do anything that well, but it’s extensible! (if you have the timeline to do it). I’ve found this approach to often make development overly verbose, difficult to develop and maintain for the problem you are trying to solve *now*. More than likely you are going to do a system re-write before the abstraction ever becomes useful. Angular offers a good balance for me between a general DOM abstraction (to avoid writing pointless DOM manipulation code) and extreme productivity to meet your deadlines or allow for ‘agile’ course changes.

        I looked at the other frameworks you mentioned and they look interesting. Soma looks a lot like Angular minus directives, as much of a DOM abstraction and a little more verbose. Rappid looks like they were trying to pull off XAML in HTML without the awesome 2-way binding on POJOs that Angular has (which is one of the most important things with Angular for me). Everything else aside I would say the biggest issue with both of them for me is Angular has about 23,500 more stars on Github than either of them do and there are about 1000 articles/plugins to do anything with Angular that you can think of almost. Using a popular framework is a huge due-diligence consideration for me because you need to be able to hire people to work on things and also get answers to questions/issues online. Angular also has a team of 20 full time “google smart” people working on the project which also gives it a huge *unfair* advantage.

        To date I haven’t really met anyone that used Angular extensively and wanted to switch to anything else. (I’m sure this will change as time goes on but the only serious contender I’ve seen to Angular right now is Ember.js in my opinion but that’s a whole different discussion) I’ve been around the framework block a few times on huge applications and still just love it. Build out a big app with it and see how it goes!

        John

  5. Julian Cassin says:

    Hi John.

    i am not using soma nor rappidjs but of all the frameworks ive looked at soma was one of the nice ones style wise and probably my first choice after jquery or rapidos. I like parts of rappidjs not including the templates and xaml. Actually meteor is one to follow also and is very automatic like angularjs although also restrictive in the same way but i think its early days still for meteor.

    Even with rapidos there isn’t a lot of dom manipulation code. Sure there is a bit but for an extremely complicated form it might be only 20 lines of code. Hardly worth worrying about and they are actually similar to the html directives of angularjs but done differently. Jquery i really am a fan but you can use it in many ways. I use it to create a vb6 like form structure in a few lines of code but more flexible and structured than vb6. Flexibility is important but just as important is the maintainibility and scalability. A good balance between them is important for a project with a long expected life.

    I agree about the adoption of commonly used frameworks but only if they do something useful you need that you can save time using it than doing it yourself.

    Julian Cassin

  6. J McGowan says:

    Slightly unfair to label standard server-side MVC plus jQuery as using the DOM to store the model. In the old days, this was true, but in the last few years i’ve been using json as the model, and driving the dome from that using templating (hidden dom templates) – as long as your json elements contains an indexer, then you don’t need to worry about shuffling indexes in the dom.

    • johnculviner says:

      I see what you are saying, I certainly wouldn’t advocate for ASP.NET MVC use verbatim for most CRUD situations anymore. I think how you do it is a step in the right direction. I would say most people using ASP.NET MVC are probably using it verbatim however. Even in the manner you describe you might be ‘fighting the framework’ vs going an Angular route. The point of the post is the illustrate how you can have that example very easily using Angular.

  7. Hi John, great article, really convinced me that angular if the way forward for rich client apps.

    I have one concern though. Would it be difficult to implement authentication using angular with asp.net identity? Do you have any recommendations for this?

    Thanks.
    Chris

    • Bruno Marques says:

      I like how you made the most pertinent question, regarding authentication which is an important step in Enterprise Applications but there’s no mention or answer about it.

    • johnculviner says:

      No problem using ASP.NET identity. AJAX works with cookies and you will likely be doing a bit of AJAX if you are building a SPA. You will want to make sure to authorize all actions on your server though (just cause the client sends a request w/ some data in it doesn’t mean they are allowed to perform that action, make sure!) This is no different than how any app should be coded though.

      • Bruno Marques says:

        Thanks, the one thing I can’t really find an answer anywhere is how to prevent static html pages, that are used as templates, from being seen by an unauthorized user who types a direct url to them, like http://www.site.com/templates/home.html

      • johnculviner says:

        Single page apps by nature run on the client rather than on the server so there aren’t really any easy ways to prevent users from seeing JS code or HTML that they don’t necessarily have access to unless you are dynamically loading all your HTML/JS (not recommended).

        More likely what you really want is to make sure that users don’t see data or are allowed to update data that they don’t have access to. As is the case with any API interactions this sort of security should be handled on the server rather than on the client. I’ve talked about this sort of thing in a blog post here before: http://johnculviner.com/dont-trust-the-client/ Make sense?

  8. pratish arora says:

    Nice post.. Gives good explanation on why should angular be used. Thanks Dude

  9. Hi John,
    Thanks for the brilliant article!

    I have been a windows forms (.NET/C#) developer for years (from the start), and now I just started learning web development from scratch. I’ve just finished learning the plain javascript.

    I have noted the two options in your post. (1) Angular.js + WebAPI and (2) jQuery + ASP.NET MVC

    So, If i jump start with Angular.js + WebAPI, don’t you think i may lose some background or valuable experience of using jQuery?. Perhaps something employers will look for if i am to seach job in the future?

    PS . I know MVVM from WPF.

    Thank you!

  10. Thanks for the post, it was just the information I needed to learn to decide me for Angular+MVC. Great knowledge and communicative skills!

  11. Thanks for a good “Break Down” and not simply a “How To”. When looking at Angular demos, I too was drawn to the scope and the “strong objects”. But this great writeup solidifies and bridges the gap in some stuff my rudimentary understanding was trying to make.

  12. I would make a suggestion to make everything non ambiguous. The app.js setup is very hard to navigate with ambiguous names.
    todoList and TodoList and todoLists shows up many times, and is difficult to navigate for a newbie because of the ambiguity.
    Thanks.

  13. You mentioned other alternatives. What are the alternatives that you would recommend?

  14. use a partialview per row, and ajax-load it everytime someone wants to add a row. Don’t do things clientside that MVC does best serverside.

    • same with delete-statement
      simple do a post deleting that row (by id) and drop that part of the html.

      MVC doesn’t require full page loads or posts, neither does jquery.

      I’m not saying angular is not better than jquery, just pointing out your MVC/jquery solution is suboptimal at least.

  15. And finally, another con of angular:

    You’re programming in javascript.
    Which means, even if you don’t think it’s a half-baked language, you’ll lack a lot of support you would get when programming in C#.

    • johnculviner says:

      Sure but JavaScript runs in a browser and Node.js is taking off like a rocketship to boot so it must be doing something right. (Love C# though but NOT for this) Hopefully the article illustrates while there are many ways you could do it with MVC it’s probably going to be harder in the long run (not to mention not using a more microservices based, decoupled approach to the backend). If your doing it in a browser JavaScript seems to be the path of least resistance, highest clarity and code re-use.

      • True, IF you’re doing it in the browser, you should go Angular. But AngularJs vs MVC is just about that question, should your MVC-framework be client or server side. And being forced to program in javascript is still a con, even if you still choose the angular-route.

      • The article has some value butvis floored in comparing two different JS frameworks both written in JS then criticising one for not doing the same as the other. jQuery is an awesome lower level tool than AngularJS. Both serve a purpose but to say jQuery doesnt let you write nice code with separation of concerns (knowing that plain JS does – afterall even AngularJS is written in JS) just means whoever wrote the sloppy code with jQuery is a sloppy developer.

  16. Reblogged this on Grey matter.

  17. Al b Good says:

    I have seen many implementations of e-commerce websites with angular go bad, because programmers think that a funnel equal is to an application and therefore they need angular.

    Angular is slower to start a page than other frameworks, because it does not use the dom. every second slower is about 7% less conversion… so Angular costs your client money, often a lot of money. Amazon does not use angular, Google does not use angular (except one playstation 3 youtube site…) how many big ecommerce sites can you name with angular?

    Angular performance is actually so bad that version 2 will be a complete rewrite, with mobile first.

    Angular is worse, because online marketeers (you know, those people that need to work with the site after is is finished) cannot use the optimization tools they wants, because angular changes parts of the dom all the time, in ways that other tools cannot use. Only after more programming some things might work. bye bye flexibility and change to improve your site.

    Building websites is not about how easy it is to program, it is about making money with the finished product. angular for ecommerce is not the best choice.

    • johnculviner says:

      I can’t really comment on using Angular for e-commerce websites since I haven’t used it for that. Regardless I’ve seen some pretty awfully slow, horribly designed jQuery or Backbone e-commerce sites (you can make a crappy site regardless of what you are doing, I’d argue its easier to make less crappy sites w/ Angular). I’ve seen it work awesome for line of business applications using rich APIs which I think is it’s bread and butter. Google actually uses it for many of their more line-of-business applications. I actually saw it in the wild quite recently because their entire MASSIVE google cloud manager application is built entirely in Angular. It sounds to me like you have a bone to pick against Angular also for a pretty narrow set of applications rather than it’s utility across most other application types.

    • This is a good point, going fully client-side with Angular is not great for basic marketing websites (e-commerce or not, it doesn’t matter) because you’re going to be fighting SEO, conversion tracking, etc. etc. plus you’re not going to be supporting those pesky consumers who refuse to upgrade their browsers and are still in the dark ages. Angular is great for rich single-page applications, but don’t confuse it for the way to build full-blown marketing websites.

  18. I want to thank you for this post which is very enlightening. I believe you are the best person to answer one related question I’ve posted in stackoverflow. The question was well received by the community but unfortunatelly it lacks answers: http://stackoverflow.com/questions/32584823/should-webservices-be-used-to-create-entire-pages

  19. Excelent article. Do you have full woking source? With woking APIs? Thanks

  20. Thanks for this – confusingly your Angular demo has the same title as the Ajax one “Todo List – jQuery and ASP.NET MVC” – would be clearer if you correct the titles. Thanks.

  21. Hi, you have save button to do bulk operation in . For this you dont need to depend on page submit and extract the value of the table from server side, you can use $each on the table and extract each row and build populate a json object and push that json object to json array and simply send the json array to server side using ajax . From server side u can convert this json to xml and send to db and using openxml extended stored procedure and cursor to do your bulk save . Your example doesnt prove use- case where angular should be used. Its just a two way binding , i think its an overkill . Plus for complex admin tool where you need lot of plugin support angular will be time consuming and overkill.

  22. var ToDoList = function(id,fname,lname,item){
    this.Id = id;
    this.OwnerFirstName = fname;
    this.OwnerLastName = lname;
    this.Items = [];
    }

    var Item = function (isCompleted, task, priority) {
    this.IsCompleted = isCompleted;
    this.Task = task;
    this.Priority = priority;
    }

    $(“#btnSave”).click(function () {

    var toDoList = new ToDoList();
    toDoList.Id = 1;
    toDoList.OwnerFirstName = “John”;
    toDoList.OwnerLastName = “Thomas”;

    //$each table rows here and populate toDoList.Items it this way

    toDoList.Items.push(new Item(true, “clean”, 1));
    toDoList.Items.push(new Item(false, “paint”, 2));

    alert(JSON.stringify(toDoList));

    //send this toDoList through ajax post

    });

    • johnculviner says:

      Hi Rahul, glad you figured out a way to do it. I guess I found the Angular approach to be much simpler, better separation of concerns and far less code than doing DOM munging with jQuery as I’d say most people would agree. JSON to XML and then into stored procedures with a cursor sounds pretty yucky and overkill to me from what I usually do so I guess to each their own there! 🙂

Trackbacks

  1. […] Read it here: Building Rich Web Apps: jQuery & MVC vs. Angular.js & WebAPI […]

Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: